8174749: Use hash table/oops for MemberName table
authorcoleenp
Sat, 27 May 2017 09:21:01 -0400
changeset 46505 fd4bc78630b1
parent 46504 38048d4d20e7
child 46506 1c48f011d709
8174749: Use hash table/oops for MemberName table Summary: Add a Java type called ResolvedMethodName which is immutable and can be stored in a hashtable, that is weakly collected by gc Reviewed-by: sspitsyn, stefank, jrose
hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp
hotspot/src/cpu/arm/vm/methodHandles_arm.cpp
hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
hotspot/src/cpu/s390/vm/methodHandles_s390.cpp
hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/javaClasses.hpp
hotspot/src/share/vm/classfile/javaClasses.inline.hpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/classfile/systemDictionary.hpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp
hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp
hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp
hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp
hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp
hotspot/src/share/vm/gc/serial/genMarkSweep.cpp
hotspot/src/share/vm/interpreter/linkResolver.cpp
hotspot/src/share/vm/interpreter/linkResolver.hpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
hotspot/src/share/vm/logging/logTag.hpp
hotspot/src/share/vm/memory/universe.cpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/oops/instanceKlass.hpp
hotspot/src/share/vm/prims/jvm.cpp
hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp
hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp
hotspot/src/share/vm/prims/methodHandles.cpp
hotspot/src/share/vm/prims/methodHandles.hpp
hotspot/src/share/vm/prims/resolvedMethodTable.cpp
hotspot/src/share/vm/prims/resolvedMethodTable.hpp
hotspot/src/share/vm/prims/stackwalk.cpp
hotspot/src/share/vm/prims/stackwalk.hpp
hotspot/src/share/vm/runtime/mutexLocker.cpp
hotspot/src/share/vm/runtime/mutexLocker.hpp
hotspot/src/share/vm/runtime/thread.cpp
hotspot/test/runtime/MemberName/MemberNameLeak.java
--- a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp	Sat May 27 09:21:01 2017 -0400
@@ -137,8 +137,9 @@
   __ verify_oop(method_temp);
   __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())));
   __ verify_oop(method_temp);
-  // the following assumes that a Method* is normally compressed in the vmtarget field:
-  __ ldr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())));
+  __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())));
+  __ verify_oop(method_temp);
+  __ ldr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())));
 
   if (VerifyMethodHandles && !for_compiler_entry) {
     // make sure recv is already on stack
@@ -282,7 +283,8 @@
 
     Address member_clazz(    member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()));
     Address member_vmindex(  member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()));
-    Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()));
+    Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()));
+    Address vmtarget_method( rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()));
 
     Register temp1_recv_klass = temp1;
     if (iid != vmIntrinsics::_linkToStatic) {
@@ -335,14 +337,16 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
       }
-      __ ldr(rmethod, member_vmtarget);
+      __ load_heap_oop(rmethod, member_vmtarget);
+      __ ldr(rmethod, vmtarget_method);
       break;
 
     case vmIntrinsics::_linkToStatic:
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
       }
-      __ ldr(rmethod, member_vmtarget);
+      __ load_heap_oop(rmethod, member_vmtarget);
+      __ ldr(rmethod, vmtarget_method);
       break;
 
     case vmIntrinsics::_linkToVirtual:
--- a/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp	Sat May 27 09:21:01 2017 -0400
@@ -157,8 +157,9 @@
   __ load_heap_oop(tmp, Address(tmp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())));
   __ verify_oop(tmp);
 
-  // the following assumes that a Method* is normally compressed in the vmtarget field:
-  __ ldr(Rmethod, Address(tmp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())));
+  __ load_heap_oop(Rmethod, Address(tmp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())));
+  __ verify_oop(Rmethod);
+  __ ldr(Rmethod, Address(Rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())));
 
   if (VerifyMethodHandles && !for_compiler_entry) {
     // make sure recv is already on stack
@@ -320,7 +321,8 @@
 
     Address member_clazz(   member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()));
     Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()));
-    Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()));
+    Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()));
+    Address vmtarget_method(Rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()));
 
     Register temp1_recv_klass = temp1;
     if (iid != vmIntrinsics::_linkToStatic) {
@@ -375,14 +377,17 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
       }
-      __ ldr(Rmethod, member_vmtarget);
+      __ load_heap_oop(Rmethod, member_vmtarget);
+      __ ldr(Rmethod, vmtarget_method);
       break;
 
     case vmIntrinsics::_linkToStatic:
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
       }
-      __ ldr(Rmethod, member_vmtarget);
+      __ load_heap_oop(Rmethod, member_vmtarget);
+      __ ldr(Rmethod, vmtarget_method);
+      break;
       break;
 
     case vmIntrinsics::_linkToVirtual:
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Sat May 27 09:21:01 2017 -0400
@@ -174,8 +174,9 @@
   __ verify_oop(method_temp);
   __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2);
   __ verify_oop(method_temp);
-  // The following assumes that a Method* is normally compressed in the vmtarget field:
-  __ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp);
+  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), method_temp);
+  __ verify_oop(method_temp);
+  __ ld(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), method_temp);
 
   if (VerifyMethodHandles && !for_compiler_entry) {
     // Make sure recv is already on stack.
@@ -361,14 +362,16 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2);
       }
-      __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg);
+      __ load_heap_oop(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg);
+      __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), member_reg);
       break;
 
     case vmIntrinsics::_linkToStatic:
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2);
       }
-      __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg);
+      __ load_heap_oop(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg);
+      __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), member_reg);
       break;
 
     case vmIntrinsics::_linkToVirtual:
--- a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp	Sat May 27 09:21:01 2017 -0400
@@ -200,10 +200,13 @@
                      Address(method_temp,
                              NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())));
   __ verify_oop(method_temp);
-  // The following assumes that a method is normally compressed in the vmtarget field.
+  __ load_heap_oop(method_temp,
+          Address(method_temp,
+                  NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())));
+  __ verify_oop(method_temp);
   __ z_lg(method_temp,
           Address(method_temp,
-                  NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())));
+                  NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())));
 
   if (VerifyMethodHandles && !for_compiler_entry) {
     // Make sure recv is already on stack.
@@ -371,7 +374,8 @@
 
   Address  member_clazz(   member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()));
   Address  member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()));
-  Address  member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()));
+  Address  member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()));
+  Address  vmtarget_method(Z_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()));
   Register temp1_recv_klass = temp1;
 
   if (iid != vmIntrinsics::_linkToStatic) {
@@ -424,7 +428,8 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
       }
-      __ z_lg(Z_method, member_vmtarget);
+      __ load_heap_oop(Z_method, member_vmtarget);
+      __ z_lg(Z_method, vmtarget_method);
       method_is_live = true;
       break;
 
@@ -432,7 +437,8 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
       }
-      __ z_lg(Z_method, member_vmtarget);
+      __ load_heap_oop(Z_method, member_vmtarget);
+      __ z_lg(Z_method, vmtarget_method);
       method_is_live = true;
       break;
 
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Sat May 27 09:21:01 2017 -0400
@@ -181,8 +181,9 @@
   __ verify_oop(method_temp);
   __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())),  method_temp);
   __ verify_oop(method_temp);
-  // the following assumes that a Method* is normally compressed in the vmtarget field:
-  __ ld_ptr(       Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())), method_temp);
+  __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), method_temp);
+  __ verify_oop(method_temp);
+  __ ld_ptr(       Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())),   method_temp);
 
   if (VerifyMethodHandles && !for_compiler_entry) {
     // make sure recv is already on stack
@@ -332,7 +333,8 @@
 
     Address member_clazz(    member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()));
     Address member_vmindex(  member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()));
-    Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()));
+    Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()));
+    Address vmtarget_method( G5_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()));
 
     Register temp1_recv_klass = temp1;
     if (iid != vmIntrinsics::_linkToStatic) {
@@ -384,14 +386,16 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2);
       }
-      __ ld_ptr(member_vmtarget, G5_method);
+      __ load_heap_oop(member_vmtarget, G5_method);
+      __ ld_ptr(vmtarget_method, G5_method);
       break;
 
     case vmIntrinsics::_linkToStatic:
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2);
       }
-      __ ld_ptr(member_vmtarget, G5_method);
+      __ load_heap_oop(member_vmtarget, G5_method);
+      __ ld_ptr(vmtarget_method, G5_method);
       break;
 
     case vmIntrinsics::_linkToVirtual:
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Sat May 27 09:21:01 2017 -0400
@@ -169,8 +169,9 @@
   __ verify_oop(method_temp);
   __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())));
   __ verify_oop(method_temp);
-  // the following assumes that a Method* is normally compressed in the vmtarget field:
-  __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())));
+  __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())));
+  __ verify_oop(method_temp);
+  __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())));
 
   if (VerifyMethodHandles && !for_compiler_entry) {
     // make sure recv is already on stack
@@ -331,7 +332,8 @@
 
     Address member_clazz(    member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()));
     Address member_vmindex(  member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()));
-    Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()));
+    Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()));
+    Address vmtarget_method( rbx_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()));
 
     Register temp1_recv_klass = temp1;
     if (iid != vmIntrinsics::_linkToStatic) {
@@ -383,14 +385,16 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
       }
-      __ movptr(rbx_method, member_vmtarget);
+      __ load_heap_oop(rbx_method, member_vmtarget);
+      __ movptr(rbx_method, vmtarget_method);
       break;
 
     case vmIntrinsics::_linkToStatic:
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
       }
-      __ movptr(rbx_method, member_vmtarget);
+      __ load_heap_oop(rbx_method, member_vmtarget);
+      __ movptr(rbx_method, vmtarget_method);
       break;
 
     case vmIntrinsics::_linkToVirtual:
--- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Sat May 27 09:21:01 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,8 @@
         static final ResolvedJavaType lambdaFormType;
         static final ResolvedJavaField methodHandleFormField;
         static final ResolvedJavaField lambdaFormVmentryField;
-        static final HotSpotResolvedJavaField memberNameVmtargetField;
+        static final ResolvedJavaField methodField;
+        static final HotSpotResolvedJavaField vmtargetField;
 
         /**
          * Search for an instance field with the given name in a class.
@@ -88,7 +89,10 @@
                 lambdaFormType = resolveType("java.lang.invoke.LambdaForm");
                 methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
                 lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);
-                memberNameVmtargetField = (HotSpotResolvedJavaField) findFieldInClass(memberNameType, "vmtarget", resolveType(long.class));
+                ResolvedJavaType methodType = resolveType("java.lang.invoke.ResolvedMethodName");
+                methodField = findFieldInClass(memberNameType, "method", methodType);
+                vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(HotSpotJVMCIRuntime.getHostWordKind().toJavaClass()));
+
             } catch (Throwable ex) {
                 throw new JVMCIError(ex);
             }
@@ -139,24 +143,30 @@
             memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
             assert memberName.isNonNull();
         }
-        return getTargetMethod(memberName);
+        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        return getTargetMethod(method);
     }
 
     @Override
     public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) {
-        return getTargetMethod(memberName);
+        if (memberName.isNull()) {
+            return null;
+        }
+        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        return getTargetMethod(method);
     }
 
     /**
-     * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName.
+     * Returns the {@link ResolvedJavaMethod} for the method of a java.lang.invoke.MemberName.
      */
-    private static ResolvedJavaMethod getTargetMethod(JavaConstant memberName) {
-        if (memberName.isNull()) {
-            return null;
+    private static ResolvedJavaMethod getTargetMethod(JavaConstant method) {
+        if (method == null) {
+            // If readFieldValue returns NULL the type was wrong
+            throw new IllegalArgumentException("unexpected type for memberName");
         }
 
-        Object object = ((HotSpotObjectConstantImpl) memberName).object();
-        /* Read the ResolvedJavaMethod from the injected field MemberName.vmtarget */
-        return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset());
+        Object object = ((HotSpotObjectConstantImpl) method).object();
+        /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */
+        return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.vmtargetField.offset());
     }
 }
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Sat May 27 09:21:01 2017 -0400
@@ -45,6 +45,7 @@
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "oops/typeArrayOop.hpp"
+#include "prims/resolvedMethodTable.hpp"
 #include "runtime/fieldDescriptor.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
@@ -2228,11 +2229,11 @@
   return method;
 }
 
-void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) {
+void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS) {
   // set Method* or mid/cpref
   Handle mname(Thread::current(), stackFrame->obj_field(_memberName_offset));
   InstanceKlass* ik = method->method_holder();
-  CallInfo info(method(), ik);
+  CallInfo info(method(), ik, CHECK);
   MethodHandles::init_method_MemberName(mname, info);
   // set bci
   java_lang_StackFrameInfo::set_bci(stackFrame(), bci);
@@ -3083,9 +3084,9 @@
 }
 
 void java_lang_invoke_DirectMethodHandle::compute_offsets() {
-  Klass* klass_oop = SystemDictionary::DirectMethodHandle_klass();
-  if (klass_oop != NULL) {
-    compute_offset(_member_offset, klass_oop, vmSymbols::member_name(), vmSymbols::java_lang_invoke_MemberName_signature());
+  Klass* k = SystemDictionary::DirectMethodHandle_klass();
+  if (k != NULL) {
+    compute_offset(_member_offset, k, vmSymbols::member_name(), vmSymbols::java_lang_invoke_MemberName_signature());
   }
 }
 
@@ -3098,36 +3099,43 @@
 int java_lang_invoke_MemberName::_name_offset;
 int java_lang_invoke_MemberName::_type_offset;
 int java_lang_invoke_MemberName::_flags_offset;
-int java_lang_invoke_MemberName::_vmtarget_offset;
-int java_lang_invoke_MemberName::_vmloader_offset;
+int java_lang_invoke_MemberName::_method_offset;
 int java_lang_invoke_MemberName::_vmindex_offset;
 
+int java_lang_invoke_ResolvedMethodName::_vmtarget_offset;
+int java_lang_invoke_ResolvedMethodName::_vmholder_offset;
+
 int java_lang_invoke_LambdaForm::_vmentry_offset;
 
 void java_lang_invoke_MethodHandle::compute_offsets() {
-  Klass* klass_oop = SystemDictionary::MethodHandle_klass();
-  if (klass_oop != NULL) {
-    compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature());
-    compute_offset(_form_offset, klass_oop, vmSymbols::form_name(), vmSymbols::java_lang_invoke_LambdaForm_signature());
+  Klass* k = SystemDictionary::MethodHandle_klass();
+  if (k != NULL) {
+    compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature());
+    compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_lang_invoke_LambdaForm_signature());
   }
 }
 
 void java_lang_invoke_MemberName::compute_offsets() {
-  Klass* klass_oop = SystemDictionary::MemberName_klass();
-  if (klass_oop != NULL) {
-    compute_offset(_clazz_offset,     klass_oop, vmSymbols::clazz_name(),     vmSymbols::class_signature());
-    compute_offset(_name_offset,      klass_oop, vmSymbols::name_name(),      vmSymbols::string_signature());
-    compute_offset(_type_offset,      klass_oop, vmSymbols::type_name(),      vmSymbols::object_signature());
-    compute_offset(_flags_offset,     klass_oop, vmSymbols::flags_name(),     vmSymbols::int_signature());
-    MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
-  }
+  Klass* k = SystemDictionary::MemberName_klass();
+  assert (k != NULL, "jdk mismatch");
+  compute_offset(_clazz_offset,   k, vmSymbols::clazz_name(),   vmSymbols::class_signature());
+  compute_offset(_name_offset,    k, vmSymbols::name_name(),    vmSymbols::string_signature());
+  compute_offset(_type_offset,    k, vmSymbols::type_name(),    vmSymbols::object_signature());
+  compute_offset(_flags_offset,   k, vmSymbols::flags_name(),   vmSymbols::int_signature());
+  compute_offset(_method_offset,  k, vmSymbols::method_name(),  vmSymbols::java_lang_invoke_ResolvedMethodName_signature());
+  MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
+}
+
+void java_lang_invoke_ResolvedMethodName::compute_offsets() {
+  Klass* k = SystemDictionary::ResolvedMethodName_klass();
+  assert(k != NULL, "jdk mismatch");
+  RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
 }
 
 void java_lang_invoke_LambdaForm::compute_offsets() {
-  Klass* klass_oop = SystemDictionary::LambdaForm_klass();
-  if (klass_oop != NULL) {
-    compute_offset(_vmentry_offset, klass_oop, vmSymbols::vmentry_name(), vmSymbols::java_lang_invoke_MemberName_signature());
-  }
+  Klass* k = SystemDictionary::LambdaForm_klass();
+  assert (k != NULL, "jdk mismatch");
+  compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::java_lang_invoke_MemberName_signature());
 }
 
 bool java_lang_invoke_LambdaForm::is_instance(oop obj) {
@@ -3195,9 +3203,12 @@
   mname->int_field_put(_flags_offset, flags);
 }
 
-Metadata* java_lang_invoke_MemberName::vmtarget(oop mname) {
+
+// Return vmtarget from ResolvedMethodName method field through indirection
+Method* java_lang_invoke_MemberName::vmtarget(oop mname) {
   assert(is_instance(mname), "wrong type");
-  return (Metadata*)mname->address_field(_vmtarget_offset);
+  oop method = mname->obj_field(_method_offset);
+  return method == NULL ? NULL : java_lang_invoke_ResolvedMethodName::vmtarget(method);
 }
 
 bool java_lang_invoke_MemberName::is_method(oop mname) {
@@ -3205,32 +3216,9 @@
   return (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0;
 }
 
-void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) {
+void java_lang_invoke_MemberName::set_method(oop mname, oop resolved_method) {
   assert(is_instance(mname), "wrong type");
-  // check the type of the vmtarget
-  oop dependency = NULL;
-  if (ref != NULL) {
-    switch (flags(mname) & (MN_IS_METHOD |
-                            MN_IS_CONSTRUCTOR |
-                            MN_IS_FIELD)) {
-    case MN_IS_METHOD:
-    case MN_IS_CONSTRUCTOR:
-      assert(ref->is_method(), "should be a method");
-      dependency = ((Method*)ref)->method_holder()->java_mirror();
-      break;
-    case MN_IS_FIELD:
-      assert(ref->is_klass(), "should be a class");
-      dependency = ((Klass*)ref)->java_mirror();
-      break;
-    default:
-      ShouldNotReachHere();
-    }
-  }
-  mname->address_field_put(_vmtarget_offset, (address)ref);
-  // Add a reference to the loader (actually mirror because anonymous classes will not have
-  // distinct loaders) to ensure the metadata is kept alive
-  // This mirror may be different than the one in clazz field.
-  mname->obj_field_put(_vmloader_offset, dependency);
+  mname->obj_field_put(_method_offset, resolved_method);
 }
 
 intptr_t java_lang_invoke_MemberName::vmindex(oop mname) {
@@ -3243,13 +3231,37 @@
   mname->address_field_put(_vmindex_offset, (address) index);
 }
 
-bool java_lang_invoke_MemberName::equals(oop mn1, oop mn2) {
-  if (mn1 == mn2) {
-     return true;
+
+Method* java_lang_invoke_ResolvedMethodName::vmtarget(oop resolved_method) {
+  assert(is_instance(resolved_method), "wrong type");
+  Method* m = (Method*)resolved_method->address_field(_vmtarget_offset);
+  assert(m->is_method(), "must be");
+  return m;
+}
+
+// Used by redefinition to change Method* to new Method* with same hash (name, signature)
+void java_lang_invoke_ResolvedMethodName::set_vmtarget(oop resolved_method, Method* m) {
+  assert(is_instance(resolved_method), "wrong type");
+  resolved_method->address_field_put(_vmtarget_offset, (address)m);
+}
+
+oop java_lang_invoke_ResolvedMethodName::find_resolved_method(const methodHandle& m, TRAPS) {
+  // lookup ResolvedMethod oop in the table, or create a new one and intern it
+  oop resolved_method = ResolvedMethodTable::find_method(m());
+  if (resolved_method == NULL) {
+    InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass();
+    if (!k->is_initialized()) {
+      k->initialize(CHECK_NULL);
+    }
+    oop new_resolved_method = k->allocate_instance(CHECK_NULL);
+    new_resolved_method->address_field_put(_vmtarget_offset, (address)m());
+    // Add a reference to the loader (actually mirror because anonymous classes will not have
+    // distinct loaders) to ensure the metadata is kept alive.
+    // This mirror may be different than the one in clazz field.
+    new_resolved_method->obj_field_put(_vmholder_offset, m->method_holder()->java_mirror());
+    resolved_method = ResolvedMethodTable::add_method(Handle(THREAD, new_resolved_method));
   }
-  return (vmtarget(mn1) == vmtarget(mn2) && flags(mn1) == flags(mn2) &&
-          vmindex(mn1) == vmindex(mn2) &&
-          clazz(mn1) == clazz(mn2));
+  return resolved_method;
 }
 
 oop java_lang_invoke_LambdaForm::vmentry(oop lform) {
@@ -3856,6 +3868,7 @@
   java_lang_invoke_MethodHandle::compute_offsets();
   java_lang_invoke_DirectMethodHandle::compute_offsets();
   java_lang_invoke_MemberName::compute_offsets();
+  java_lang_invoke_ResolvedMethodName::compute_offsets();
   java_lang_invoke_LambdaForm::compute_offsets();
   java_lang_invoke_MethodType::compute_offsets();
   java_lang_invoke_CallSite::compute_offsets();
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Sat May 27 09:21:01 2017 -0400
@@ -1005,10 +1005,33 @@
 // Interface to java.lang.invoke.MemberName objects
 // (These are a private interface for Java code to query the class hierarchy.)
 
+#define RESOLVEDMETHOD_INJECTED_FIELDS(macro)                                   \
+  macro(java_lang_invoke_ResolvedMethodName, vmholder, object_signature, false) \
+  macro(java_lang_invoke_ResolvedMethodName, vmtarget, intptr_signature, false)
+
+class java_lang_invoke_ResolvedMethodName : AllStatic {
+  friend class JavaClasses;
+
+  static int _vmtarget_offset;
+  static int _vmholder_offset;
+
+  static void compute_offsets();
+ public:
+  static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
+
+  static Method* vmtarget(oop resolved_method);
+  static void set_vmtarget(oop resolved_method, Method* method);
+
+  // find or create resolved member name
+  static oop find_resolved_method(const methodHandle& m, TRAPS);
+
+  static bool is_instance(oop resolved_method);
+};
+
+
 #define MEMBERNAME_INJECTED_FIELDS(macro)                               \
-  macro(java_lang_invoke_MemberName, vmloader, object_signature, false) \
-  macro(java_lang_invoke_MemberName, vmindex,  intptr_signature, false) \
-  macro(java_lang_invoke_MemberName, vmtarget, intptr_signature, false)
+  macro(java_lang_invoke_MemberName, vmindex,  intptr_signature, false)
+
 
 class java_lang_invoke_MemberName: AllStatic {
   friend class JavaClasses;
@@ -1019,14 +1042,13 @@
   //    private String     name;        // may be null if not yet materialized
   //    private Object     type;        // may be null if not yet materialized
   //    private int        flags;       // modifier bits; see reflect.Modifier
-  //    private intptr     vmtarget;    // VM-specific target value
+  //    private ResolvedMethodName method;    // holds VM-specific target value
   //    private intptr_t   vmindex;     // member index within class or interface
   static int _clazz_offset;
   static int _name_offset;
   static int _type_offset;
   static int _flags_offset;
-  static int _vmtarget_offset;
-  static int _vmloader_offset;
+  static int _method_offset;
   static int _vmindex_offset;
 
   static void compute_offsets();
@@ -1045,8 +1067,9 @@
   static int            flags(oop mname);
   static void       set_flags(oop mname, int flags);
 
-  static Metadata*      vmtarget(oop mname);
-  static void       set_vmtarget(oop mname, Metadata* target);
+  // Link through ResolvedMethodName field to get Method*
+  static Method*        vmtarget(oop mname);
+  static void       set_method(oop mname, oop method);
 
   static intptr_t       vmindex(oop mname);
   static void       set_vmindex(oop mname, intptr_t index);
@@ -1078,10 +1101,8 @@
   static int type_offset_in_bytes()             { return _type_offset; }
   static int name_offset_in_bytes()             { return _name_offset; }
   static int flags_offset_in_bytes()            { return _flags_offset; }
-  static int vmtarget_offset_in_bytes()         { return _vmtarget_offset; }
+  static int method_offset_in_bytes()           { return _method_offset; }
   static int vmindex_offset_in_bytes()          { return _vmindex_offset; }
-
-  static bool equals(oop mt1, oop mt2);
 };
 
 
@@ -1358,7 +1379,7 @@
 public:
   // Setters
   static void set_declaringClass(oop info, oop value);
-  static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci);
+  static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS);
   static void set_bci(oop info, int value);
 
   static void set_version(oop info, short value);
@@ -1472,6 +1493,7 @@
 #define ALL_INJECTED_FIELDS(macro)          \
   CLASS_INJECTED_FIELDS(macro)              \
   CLASSLOADER_INJECTED_FIELDS(macro)        \
+  RESOLVEDMETHOD_INJECTED_FIELDS(macro)     \
   MEMBERNAME_INJECTED_FIELDS(macro)         \
   CALLSITECONTEXT_INJECTED_FIELDS(macro)    \
   STACKFRAMEINFO_INJECTED_FIELDS(macro)     \
--- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp	Sat May 27 09:21:01 2017 -0400
@@ -143,7 +143,11 @@
 }
 
 inline bool java_lang_invoke_MemberName::is_instance(oop obj) {
-  return obj != NULL && is_subclass(obj->klass());
+  return obj != NULL && obj->klass() == SystemDictionary::MemberName_klass();
+}
+
+inline bool java_lang_invoke_ResolvedMethodName::is_instance(oop obj) {
+  return obj != NULL && obj->klass() == SystemDictionary::ResolvedMethodName_klass();
 }
 
 inline bool java_lang_invoke_MethodType::is_instance(oop obj) {
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Sat May 27 09:21:01 2017 -0400
@@ -42,8 +42,10 @@
 #include "code/codeCache.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc/shared/gcLocker.hpp"
+#include "gc/shared/gcTraceTime.inline.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/interpreter.hpp"
+#include "logging/log.hpp"
 #include "memory/filemap.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
@@ -57,6 +59,7 @@
 #include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "prims/jvmtiEnvBase.hpp"
+#include "prims/resolvedMethodTable.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/biasedLocking.hpp"
@@ -1915,23 +1918,43 @@
 // Assumes classes in the SystemDictionary are only unloaded at a safepoint
 // Note: anonymous classes are not in the SD.
 bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive,
-                                    bool clean_previous_versions) {
-  // First, mark for unload all ClassLoaderData referencing a dead class loader.
-  bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive,
-                                                               clean_previous_versions);
+                                    GCTimer* gc_timer,
+                                    bool do_cleaning) {
+
+
+  bool unloading_occurred;
+  {
+    GCTraceTime(Debug, gc, phases) t("ClassLoaderData", gc_timer);
+
+    // First, mark for unload all ClassLoaderData referencing a dead class loader.
+    unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive,
+                                                            do_cleaning);
+  }
+
   if (unloading_occurred) {
+    GCTraceTime(Debug, gc, phases) t("Dictionary", gc_timer);
     dictionary()->do_unloading();
     constraints()->purge_loader_constraints();
     resolution_errors()->purge_resolution_errors();
   }
-  // Oops referenced by the system dictionary may get unreachable independently
-  // of the class loader (eg. cached protection domain oops). So we need to
-  // explicitly unlink them here instead of in Dictionary::do_unloading.
-  dictionary()->unlink(is_alive);
+
+  {
+    GCTraceTime(Debug, gc, phases) t("ProtectionDomainCacheTable", gc_timer);
+    // Oops referenced by the system dictionary may get unreachable independently
+    // of the class loader (eg. cached protection domain oops). So we need to
+    // explicitly unlink them here instead of in Dictionary::do_unloading.
+    dictionary()->unlink(is_alive);
 #ifdef ASSERT
-  VerifySDReachableAndLiveClosure cl(is_alive);
-  dictionary()->oops_do(&cl);
+    VerifySDReachableAndLiveClosure cl(is_alive);
+    dictionary()->oops_do(&cl);
 #endif
+  }
+
+  if (do_cleaning) {
+    GCTraceTime(Debug, gc, phases) t("ResolvedMethodTable", gc_timer);
+    ResolvedMethodTable::unlink(is_alive);
+  }
+
   return unloading_occurred;
 }
 
@@ -1945,6 +1968,10 @@
 
   // Visit extra methods
   invoke_method_table()->oops_do(strong);
+
+  if (weak != NULL) {
+    ResolvedMethodTable::oops_do(weak);
+  }
 }
 
 void SystemDictionary::oops_do(OopClosure* f) {
@@ -1957,6 +1984,8 @@
 
   // Visit extra methods
   invoke_method_table()->oops_do(f);
+
+  ResolvedMethodTable::oops_do(f);
 }
 
 // Just the classes from defining class loaders
@@ -2526,9 +2555,8 @@
                                                TRAPS) {
   methodHandle empty;
   if (mname.not_null()) {
-    Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
-    if (vmtarget != NULL && vmtarget->is_method()) {
-      Method* m = (Method*)vmtarget;
+    Method* m = java_lang_invoke_MemberName::vmtarget(mname());
+    if (m != NULL) {
       oop appendix = appendix_box->obj_at(0);
       if (TraceMethodHandles) {
     #ifndef PRODUCT
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Sat May 27 09:21:01 2017 -0400
@@ -78,6 +78,7 @@
 template <MEMFLAGS F> class HashtableBucket;
 class ResolutionErrorTable;
 class SymbolPropertyTable;
+class GCTimer;
 
 // Certain classes are preloaded, such as java.lang.Object and java.lang.String.
 // They are all "well-known", in the sense that no class loader is allowed
@@ -155,6 +156,7 @@
   do_klass(MethodHandle_klass,                          java_lang_invoke_MethodHandle,             Pre                 ) \
   do_klass(VarHandle_klass,                             java_lang_invoke_VarHandle,                Pre                 ) \
   do_klass(MemberName_klass,                            java_lang_invoke_MemberName,               Pre                 ) \
+  do_klass(ResolvedMethodName_klass,                    java_lang_invoke_ResolvedMethodName,       Pre                 ) \
   do_klass(MethodHandleNatives_klass,                   java_lang_invoke_MethodHandleNatives,      Pre                 ) \
   do_klass(LambdaForm_klass,                            java_lang_invoke_LambdaForm,               Opt                 ) \
   do_klass(MethodType_klass,                            java_lang_invoke_MethodType,               Pre                 ) \
@@ -366,7 +368,8 @@
   // Unload (that is, break root links to) all unmarked classes and
   // loaders.  Returns "true" iff something was unloaded.
   static bool do_unloading(BoolObjectClosure* is_alive,
-                           bool clean_previous_versions = true);
+                           GCTimer* gc_timer,
+                           bool do_cleaning = true);
 
   // Used by DumpSharedSpaces only to remove classes that failed verification
   static void remove_classes_in_error_state();
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Sat May 27 09:21:01 2017 -0400
@@ -288,11 +288,13 @@
   template(java_lang_invoke_VarHandle,                "java/lang/invoke/VarHandle")               \
   template(java_lang_invoke_MethodType,               "java/lang/invoke/MethodType")              \
   template(java_lang_invoke_MethodType_signature,     "Ljava/lang/invoke/MethodType;")            \
+  template(java_lang_invoke_ResolvedMethodName_signature, "Ljava/lang/invoke/ResolvedMethodName;")\
   template(java_lang_invoke_MemberName_signature,     "Ljava/lang/invoke/MemberName;")            \
   template(java_lang_invoke_LambdaForm_signature,     "Ljava/lang/invoke/LambdaForm;")            \
   template(java_lang_invoke_MethodHandle_signature,   "Ljava/lang/invoke/MethodHandle;")          \
   /* internal classes known only to the JVM: */                                                   \
   template(java_lang_invoke_MemberName,               "java/lang/invoke/MemberName")              \
+  template(java_lang_invoke_ResolvedMethodName,       "java/lang/invoke/ResolvedMethodName")      \
   template(java_lang_invoke_MethodHandleNatives,      "java/lang/invoke/MethodHandleNatives")     \
   template(java_lang_invoke_MethodHandleNatives_CallSiteContext, "java/lang/invoke/MethodHandleNatives$CallSiteContext") \
   template(java_lang_invoke_LambdaForm,               "java/lang/invoke/LambdaForm")              \
@@ -413,8 +415,8 @@
   template(values_name,                               "values")                                   \
   template(receiver_name,                             "receiver")                                 \
   template(vmtarget_name,                             "vmtarget")                                 \
-  template(next_target_name,                          "next_target")                              \
-  template(vmloader_name,                             "vmloader")                                 \
+  template(vmholder_name,                             "vmholder")                                 \
+  template(method_name,                               "method")                                   \
   template(vmindex_name,                              "vmindex")                                  \
   template(vmcount_name,                              "vmcount")                                  \
   template(vmentry_name,                              "vmentry")                                  \
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Sat May 27 09:21:01 2017 -0400
@@ -5232,7 +5232,7 @@
       GCTraceTime(Debug, gc, phases) t("Class Unloading", _gc_timer_cm);
 
       // Unload classes and purge the SystemDictionary.
-      bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure);
+      bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure, _gc_timer_cm);
 
       // Unload nmethods.
       CodeCache::do_unloading(&_is_alive_closure, purged_class);
@@ -5254,7 +5254,6 @@
     }
   }
 
-
   // Restore any preserved marks as a result of mark stack or
   // work queue overflow
   restore_preserved_marks_if_any();  // done single-threaded for now
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Sat May 27 09:21:01 2017 -0400
@@ -74,6 +74,7 @@
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
+#include "prims/resolvedMethodTable.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/init.hpp"
 #include "runtime/orderAccess.inline.hpp"
@@ -3843,12 +3844,36 @@
   }
 };
 
+class G1ResolvedMethodCleaningTask : public StackObj {
+  BoolObjectClosure* _is_alive;
+  volatile jint      _resolved_method_task_claimed;
+public:
+  G1ResolvedMethodCleaningTask(BoolObjectClosure* is_alive) :
+      _is_alive(is_alive), _resolved_method_task_claimed(0) {}
+
+  bool claim_resolved_method_task() {
+    if (_resolved_method_task_claimed) {
+      return false;
+    }
+    return Atomic::cmpxchg(1, (jint*)&_resolved_method_task_claimed, 0) == 0;
+  }
+
+  // These aren't big, one thread can do it all.
+  void work() {
+    if (claim_resolved_method_task()) {
+      ResolvedMethodTable::unlink(_is_alive);
+    }
+  }
+};
+
+
 // To minimize the remark pause times, the tasks below are done in parallel.
 class G1ParallelCleaningTask : public AbstractGangTask {
 private:
   G1StringAndSymbolCleaningTask _string_symbol_task;
   G1CodeCacheUnloadingTask      _code_cache_task;
   G1KlassCleaningTask           _klass_cleaning_task;
+  G1ResolvedMethodCleaningTask  _resolved_method_cleaning_task;
 
 public:
   // The constructor is run in the VMThread.
@@ -3856,7 +3881,8 @@
       AbstractGangTask("Parallel Cleaning"),
       _string_symbol_task(is_alive, true, true, G1StringDedup::is_enabled()),
       _code_cache_task(num_workers, is_alive, unloading_occurred),
-      _klass_cleaning_task(is_alive) {
+      _klass_cleaning_task(is_alive),
+      _resolved_method_cleaning_task(is_alive) {
   }
 
   // The parallel work done by all worker threads.
@@ -3870,6 +3896,9 @@
     // Clean the Strings and Symbols.
     _string_symbol_task.work(worker_id);
 
+    // Clean unreferenced things in the ResolvedMethodTable
+    _resolved_method_cleaning_task.work();
+
     // Wait for all workers to finish the first code cache cleaning pass.
     _code_cache_task.barrier_wait(worker_id);
 
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp	Sat May 27 09:21:01 2017 -0400
@@ -1752,7 +1752,7 @@
   // Unload Klasses, String, Symbols, Code Cache, etc.
   if (ClassUnloadingWithConcurrentMark) {
     GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm);
-    bool purged_classes = SystemDictionary::do_unloading(&g1_is_alive, false /* Defer klass cleaning */);
+    bool purged_classes = SystemDictionary::do_unloading(&g1_is_alive, _gc_timer_cm, false /* Defer cleaning */);
     g1h->complete_cleaning(&g1_is_alive, purged_classes);
   } else {
     GCTraceTime(Debug, gc, phases) debug("Cleanup", _gc_timer_cm);
--- a/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1MarkSweep.cpp	Sat May 27 09:21:01 2017 -0400
@@ -165,7 +165,7 @@
     GCTraceTime(Debug, gc, phases) trace("Class Unloading", gc_timer());
 
     // Unload classes and purge the SystemDictionary.
-    bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);
+    bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive, gc_timer());
 
     g1h->complete_cleaning(&GenMarkSweep::is_alive, purged_class);
   } else {
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Sat May 27 09:21:01 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -540,7 +540,7 @@
     GCTraceTime(Debug, gc, phases) t("Class Unloading", _gc_timer);
 
     // Unload classes and purge the SystemDictionary.
-    bool purged_class = SystemDictionary::do_unloading(is_alive_closure());
+    bool purged_class = SystemDictionary::do_unloading(is_alive_closure(), _gc_timer);
 
     // Unload nmethods.
     CodeCache::do_unloading(is_alive_closure(), purged_class);
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Sat May 27 09:21:01 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2120,7 +2120,7 @@
     GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", &_gc_timer);
 
     // Follow system dictionary roots and unload classes.
-    bool purged_class = SystemDictionary::do_unloading(is_alive_closure());
+    bool purged_class = SystemDictionary::do_unloading(is_alive_closure(), &_gc_timer);
 
     // Unload nmethods.
     CodeCache::do_unloading(is_alive_closure(), purged_class);
--- a/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/gc/serial/genMarkSweep.cpp	Sat May 27 09:21:01 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -223,7 +223,7 @@
     GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", gc_timer());
 
     // Unload classes and purge the SystemDictionary.
-    bool purged_class = SystemDictionary::do_unloading(&is_alive);
+    bool purged_class = SystemDictionary::do_unloading(&is_alive, gc_timer());
 
     // Unload nmethods.
     CodeCache::do_unloading(&is_alive, purged_class);
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Sat May 27 09:21:01 2017 -0400
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/defaultMethods.hpp"
+#include "classfile/javaClasses.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -131,7 +132,7 @@
 }
 
 // utility query for unreflecting a method
-CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass) {
+CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass, TRAPS) {
   Klass* resolved_method_holder = resolved_method->method_holder();
   if (resolved_klass == NULL) { // 2nd argument defaults to holder of 1st
     resolved_klass = resolved_method_holder;
@@ -180,9 +181,19 @@
   _call_kind  = kind;
   _call_index = index;
   _resolved_appendix = Handle();
+  // Find or create a ResolvedMethod instance for this Method*
+  set_resolved_method_name(CHECK);
+
   DEBUG_ONLY(verify());
 }
 
+void CallInfo::set_resolved_method_name(TRAPS) {
+  Method* m = _resolved_method();
+  assert(m != NULL, "Should already have a Method*");
+  oop rmethod_name = java_lang_invoke_ResolvedMethodName::find_resolved_method(m, CHECK);
+  _resolved_method_name = Handle(THREAD, rmethod_name);
+}
+
 #ifdef ASSERT
 void CallInfo::verify() {
   switch (call_kind()) {  // the meaning and allowed value of index depends on kind
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp	Sat May 27 09:21:01 2017 -0400
@@ -56,6 +56,7 @@
   int          _call_index;             // vtable or itable index of selected class method (if any)
   Handle       _resolved_appendix;      // extra argument in constant pool (if CPCE::has_appendix)
   Handle       _resolved_method_type;   // MethodType (for invokedynamic and invokehandle call sites)
+  Handle       _resolved_method_name;   // Object holding the ResolvedMethodName
 
   void set_static(Klass* resolved_klass, const methodHandle& resolved_method, TRAPS);
   void set_interface(Klass* resolved_klass, Klass* selected_klass,
@@ -88,8 +89,9 @@
   }
 
   // utility to extract an effective CallInfo from a method and an optional receiver limit
-  // does not queue the method for compilation
-  CallInfo(Method* resolved_method, Klass* resolved_klass = NULL);
+  // does not queue the method for compilation.  This also creates a ResolvedMethodName
+  // object for the resolved_method.
+  CallInfo(Method* resolved_method, Klass* resolved_klass, TRAPS);
 
   Klass*  resolved_klass() const                 { return _resolved_klass; }
   Klass*  selected_klass() const                 { return _selected_klass; }
@@ -97,6 +99,9 @@
   methodHandle selected_method() const           { return _selected_method; }
   Handle       resolved_appendix() const         { return _resolved_appendix; }
   Handle       resolved_method_type() const      { return _resolved_method_type; }
+  Handle       resolved_method_name() const      { return _resolved_method_name; }
+  // Materialize a java.lang.invoke.ResolvedMethodName for this resolved_method
+  void     set_resolved_method_name(TRAPS);
 
   BasicType    result_type() const               { return selected_method()->result_type(); }
   CallKind     call_kind() const                 { return _call_kind; }
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Sat May 27 09:21:01 2017 -0400
@@ -668,7 +668,7 @@
   oop base_object = JNIHandles::resolve(base);
   if (base_object == NULL) {
     method = *((Method**)(offset));
-  } else if (base_object->is_a(SystemDictionary::MemberName_klass())) {
+  } else if (base_object->is_a(SystemDictionary::ResolvedMethodName_klass())) {
     method = (Method*) (intptr_t) base_object->long_field(offset);
   } else if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
     method = *((Method**)(HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object) + offset));
--- a/hotspot/src/share/vm/logging/logTag.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/logging/logTag.hpp	Sat May 27 09:21:01 2017 -0400
@@ -83,6 +83,7 @@
   LOG_TAG(logging) \
   LOG_TAG(mark) \
   LOG_TAG(marking) \
+  LOG_TAG(membername) \
   LOG_TAG(memops) \
   LOG_TAG(methodcomparator) \
   LOG_TAG(metadata) \
@@ -128,6 +129,7 @@
   LOG_TAG(subclass) \
   LOG_TAG(survivor) \
   LOG_TAG(sweep) \
+  LOG_TAG(table) \
   LOG_TAG(task) \
   DEBUG_ONLY(LOG_TAG(test)) \
   LOG_TAG(thread) \
--- a/hotspot/src/share/vm/memory/universe.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp	Sat May 27 09:21:01 2017 -0400
@@ -56,6 +56,7 @@
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/typeArrayKlass.hpp"
+#include "prims/resolvedMethodTable.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/commandLineFlagConstraintList.hpp"
@@ -686,6 +687,8 @@
     Universe::initialize_verify_flags();
   }
 
+  ResolvedMethodTable::create_table();
+
   return JNI_OK;
 }
 
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Sat May 27 09:21:01 2017 -0400
@@ -2131,17 +2131,6 @@
     FreeHeap(jmeths);
   }
 
-  // Deallocate MemberNameTable
-  {
-    Mutex* lock_or_null = SafepointSynchronize::is_at_safepoint() ? NULL : MemberNameTable_lock;
-    MutexLockerEx ml(lock_or_null, Mutex::_no_safepoint_check_flag);
-    MemberNameTable* mnt = member_names();
-    if (mnt != NULL) {
-      delete mnt;
-      set_member_names(NULL);
-    }
-  }
-
   // Release dependencies.
   // It is desirable to use DC::remove_all_dependents() here, but, unfortunately,
   // it is not safe (see JDK-8143408). The problem is that the klass dependency
@@ -2770,32 +2759,6 @@
   return NULL;
 }
 
-oop InstanceKlass::add_member_name(Handle mem_name, bool intern) {
-  jweak mem_name_wref = JNIHandles::make_weak_global(mem_name);
-  MutexLocker ml(MemberNameTable_lock);
-  DEBUG_ONLY(NoSafepointVerifier nsv);
-
-  // Check if method has been redefined while taking out MemberNameTable_lock, if so
-  // return false.  We cannot cache obsolete methods. They will crash when the function
-  // is called!
-  Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name());
-  if (method->is_obsolete()) {
-    return NULL;
-  } else if (method->is_old()) {
-    // Replace method with redefined version
-    java_lang_invoke_MemberName::set_vmtarget(mem_name(), method_with_idnum(method->method_idnum()));
-  }
-
-  if (_member_names == NULL) {
-    _member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(idnum_allocated_count());
-  }
-  if (intern) {
-    return _member_names->find_or_add_member_name(mem_name_wref);
-  } else {
-    return _member_names->add_member_name(mem_name_wref);
-  }
-}
-
 // -----------------------------------------------------------------------------------------------------
 // Printing
 
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Sat May 27 09:21:01 2017 -0400
@@ -66,7 +66,6 @@
 class jniIdMapBase;
 class JNIid;
 class JvmtiCachedClassFieldMap;
-class MemberNameTable;
 class SuperTypeClosure;
 
 // This is used in iterators below.
@@ -219,7 +218,8 @@
     _misc_is_scratch_class                    = 1 << 11, // class is the redefined scratch class
     _misc_is_shared_boot_class                = 1 << 12, // defining class loader is boot class loader
     _misc_is_shared_platform_class            = 1 << 13, // defining class loader is platform class loader
-    _misc_is_shared_app_class                 = 1 << 14  // defining class loader is app class loader
+    _misc_is_shared_app_class                 = 1 << 14, // defining class loader is app class loader
+    _misc_has_resolved_methods                = 1 << 15  // resolved methods table entries added for this class
   };
   u2 loader_type_bits() {
     return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
@@ -229,7 +229,6 @@
   u2              _major_version;        // major version number of class file
   Thread*         _init_thread;          // Pointer to current thread doing initialization (to handle recusive initialization)
   OopMapCache*    volatile _oop_map_cache;   // OopMapCache for all methods in the klass (allocated lazily)
-  MemberNameTable* _member_names;        // Member names
   JNIid*          _jni_ids;              // First JNI identifier for static fields in this class
   jmethodID*      volatile _methods_jmethod_ids;  // jmethodIDs corresponding to method_idnum, or NULL if none
   intptr_t        _dep_context;          // packed DependencyContext structure
@@ -747,6 +746,13 @@
     _misc_flags |= _misc_is_scratch_class;
   }
 
+  bool has_resolved_methods() const {
+    return (_misc_flags & _misc_has_resolved_methods) != 0;
+  }
+
+  void set_has_resolved_methods() {
+    _misc_flags |= _misc_has_resolved_methods;
+  }
 private:
 
   void set_kind(unsigned kind) {
@@ -1334,11 +1340,6 @@
   // jvm support
   jint compute_modifier_flags(TRAPS) const;
 
-  // JSR-292 support
-  MemberNameTable* member_names() { return _member_names; }
-  void set_member_names(MemberNameTable* member_names) { _member_names = member_names; }
-  oop add_member_name(Handle member_name, bool intern);
-
 public:
   // JVMTI support
   jint jvmti_class_status() const;
--- a/hotspot/src/share/vm/prims/jvm.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Sat May 27 09:21:01 2017 -0400
@@ -673,21 +673,6 @@
   bs->write_region(MemRegion((HeapWord*)new_obj_oop, size));
 
   Handle new_obj(THREAD, new_obj_oop);
-  // Special handling for MemberNames.  Since they contain Method* metadata, they
-  // must be registered so that RedefineClasses can fix metadata contained in them.
-  if (java_lang_invoke_MemberName::is_instance(new_obj()) &&
-      java_lang_invoke_MemberName::is_method(new_obj())) {
-    Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(new_obj());
-    // MemberName may be unresolved, so doesn't need registration until resolved.
-    if (method != NULL) {
-      methodHandle m(THREAD, method);
-      // This can safepoint and redefine method, so need both new_obj and method
-      // in a handle, for two different reasons.  new_obj can move, method can be
-      // deleted if nothing is using it on the stack.
-      m->method_holder()->add_member_name(new_obj, false);
-    }
-  }
-
   // Caution: this involves a java upcall, so the clone should be
   // "gc-robust" by this stage.
   if (klass->has_finalizer()) {
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Sat May 27 09:21:01 2017 -0400
@@ -43,6 +43,7 @@
 #include "oops/oop.inline.hpp"
 #include "prims/jvmtiImpl.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
+#include "prims/resolvedMethodTable.hpp"
 #include "prims/methodComparator.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/relocator.hpp"
@@ -67,6 +68,7 @@
   _class_count = class_count;
   _class_defs = class_defs;
   _class_load_kind = class_load_kind;
+  _any_class_has_resolved_methods = false;
   _res = JVMTI_ERROR_NONE;
 }
 
@@ -201,6 +203,12 @@
   MethodDataCleaner clean_weak_method_links;
   ClassLoaderDataGraph::classes_do(&clean_weak_method_links);
 
+  // JSR-292 support
+  if (_any_class_has_resolved_methods) {
+    bool trace_name_printed = false;
+    ResolvedMethodTable::adjust_method_entries(&trace_name_printed);
+  }
+
   // Disable any dependent concurrent compilations
   SystemDictionary::notice_modification();
 
@@ -3823,6 +3831,8 @@
   compute_added_deleted_matching_methods();
   update_jmethod_ids();
 
+  _any_class_has_resolved_methods = the_class->has_resolved_methods() || _any_class_has_resolved_methods;
+
   // Attach new constant pool to the original klass. The original
   // klass still refers to the old constant pool (for now).
   scratch_class->constants()->set_pool_holder(the_class);
@@ -4037,13 +4047,6 @@
   AdjustCpoolCacheAndVtable adjust_cpool_cache_and_vtable(THREAD);
   ClassLoaderDataGraph::classes_do(&adjust_cpool_cache_and_vtable);
 
-  // JSR-292 support
-  MemberNameTable* mnt = the_class->member_names();
-  if (mnt != NULL) {
-    bool trace_name_printed = false;
-    mnt->adjust_method_entries(the_class, &trace_name_printed);
-  }
-
   if (the_class->oop_map_cache() != NULL) {
     // Flush references to any obsolete methods from the oop map cache
     // so that obsolete methods are not pinned.
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp	Sat May 27 09:21:01 2017 -0400
@@ -374,6 +374,11 @@
   InstanceKlass**             _scratch_classes;
   jvmtiError                  _res;
 
+  // Set if any of the InstanceKlasses have entries in the ResolvedMethodTable
+  // to avoid walking after redefinition if the redefined classes do not
+  // have any entries.
+  bool _any_class_has_resolved_methods;
+
   // Performance measurement support. These timers do not cover all
   // the work done for JVM/TI RedefineClasses() but they do cover
   // the heavy lifting.
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Sat May 27 09:21:01 2017 -0400
@@ -122,14 +122,7 @@
   ALL_KINDS      = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE
 };
 
-Handle MethodHandles::new_MemberName(TRAPS) {
-  Handle empty;
-  InstanceKlass* k = SystemDictionary::MemberName_klass();
-  if (!k->is_initialized())  k->initialize(CHECK_(empty));
-  return Handle(THREAD, k->allocate_instance(THREAD));
-}
-
-oop MethodHandles::init_MemberName(Handle mname, Handle target) {
+oop MethodHandles::init_MemberName(Handle mname, Handle target, TRAPS) {
   // This method is used from java.lang.invoke.MemberName constructors.
   // It fills in the new MemberName from a java.lang.reflect.Member.
   Thread* thread = Thread::current();
@@ -159,7 +152,7 @@
       Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
       if (m == NULL || is_signature_polymorphic(m->intrinsic_id()))
         return NULL;            // do not resolve unless there is a concrete signature
-      CallInfo info(m, k);
+      CallInfo info(m, k, CHECK_NULL);
       return init_method_MemberName(mname, info);
     }
   } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
@@ -169,14 +162,14 @@
     if (k != NULL && k->is_instance_klass()) {
       Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
       if (m == NULL)  return NULL;
-      CallInfo info(m, k);
+      CallInfo info(m, k, CHECK_NULL);
       return init_method_MemberName(mname, info);
     }
   }
   return NULL;
 }
 
-oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, bool intern) {
+oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
   assert(info.resolved_appendix().is_null(), "only normal methods here");
   methodHandle m = info.resolved_method();
   assert(m.not_null(), "null method handle");
@@ -265,32 +258,35 @@
     flags |= CALLER_SENSITIVE;
   }
 
+  Handle resolved_method = info.resolved_method_name();
+  assert(java_lang_invoke_ResolvedMethodName::vmtarget(resolved_method()) == m(),
+         "Should not change after link resolultion");
+
   oop mname_oop = mname();
-  java_lang_invoke_MemberName::set_flags(   mname_oop, flags);
-  java_lang_invoke_MemberName::set_vmtarget(mname_oop, m());
-  java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex);   // vtable/itable index
-  java_lang_invoke_MemberName::set_clazz(   mname_oop, m_klass->java_mirror());
+  java_lang_invoke_MemberName::set_flags  (mname_oop, flags);
+  java_lang_invoke_MemberName::set_method (mname_oop, resolved_method());
+  java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex);   // vtable/itable index
+  java_lang_invoke_MemberName::set_clazz  (mname_oop, m_klass->java_mirror());
   // Note:  name and type can be lazily computed by resolve_MemberName,
   // if Java code needs them as resolved String and MethodType objects.
-  // The clazz must be eagerly stored, because it provides a GC
-  // root to help keep alive the Method*.
   // If relevant, the vtable or itable value is stored as vmindex.
   // This is done eagerly, since it is readily available without
   // constructing any new objects.
-  return m->method_holder()->add_member_name(mname, intern);
+  return mname();
 }
 
 oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool is_setter) {
   int flags = (jushort)( fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
   flags |= IS_FIELD | ((fd.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
   if (is_setter)  flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
-  Metadata* vmtarget = fd.field_holder();
   int vmindex        = fd.offset();  // determines the field uniquely when combined with static bit
+
   oop mname_oop = mname();
-  java_lang_invoke_MemberName::set_flags(mname_oop,    flags);
-  java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
-  java_lang_invoke_MemberName::set_vmindex(mname_oop,  vmindex);
-  java_lang_invoke_MemberName::set_clazz(mname_oop,    fd.field_holder()->java_mirror());
+  java_lang_invoke_MemberName::set_flags  (mname_oop, flags);
+  java_lang_invoke_MemberName::set_method (mname_oop, NULL);
+  java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex);
+  java_lang_invoke_MemberName::set_clazz  (mname_oop, fd.field_holder()->java_mirror());
+
   oop type = field_signature_type_or_null(fd.signature());
   oop name = field_name_or_null(fd.name());
   if (name != NULL)
@@ -745,6 +741,7 @@
         // Caller is responsible to prevent this from happening.
         THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty);
       }
+      result.set_resolved_method_name(CHECK_(empty));
       oop mname2 = init_method_MemberName(mname, result);
       return Handle(THREAD, mname2);
     }
@@ -764,6 +761,7 @@
         }
       }
       assert(result.is_statically_bound(), "");
+      result.set_resolved_method_name(CHECK_(empty));
       oop mname2 = init_method_MemberName(mname, result);
       return Handle(THREAD, mname2);
     }
@@ -794,11 +792,6 @@
 // which refers directly to JVM internals.
 void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
   assert(java_lang_invoke_MemberName::is_instance(mname()), "");
-  Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
-  int vmindex  = java_lang_invoke_MemberName::vmindex(mname());
-  if (vmtarget == NULL) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand");
-  }
 
   bool have_defc = (java_lang_invoke_MemberName::clazz(mname()) != NULL);
   bool have_name = (java_lang_invoke_MemberName::name(mname()) != NULL);
@@ -817,10 +810,12 @@
   case IS_METHOD:
   case IS_CONSTRUCTOR:
     {
-      assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
-      methodHandle m(THREAD, (Method*)vmtarget);
+      Method* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
+      if (vmtarget == NULL) {
+        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand");
+      }
+      methodHandle m(THREAD, vmtarget);
       DEBUG_ONLY(vmtarget = NULL);  // safety
-      if (m.is_null())  break;
       if (!have_defc) {
         InstanceKlass* defc = m->method_holder();
         java_lang_invoke_MemberName::set_clazz(mname(), defc->java_mirror());
@@ -838,17 +833,17 @@
     }
   case IS_FIELD:
     {
-      assert(vmtarget->is_klass(), "field vmtarget is Klass*");
-      if (!((Klass*) vmtarget)->is_instance_klass())  break;
-      InstanceKlass* defc = InstanceKlass::cast((Klass*) vmtarget);
-      DEBUG_ONLY(vmtarget = NULL);  // safety
+      oop clazz = java_lang_invoke_MemberName::clazz(mname());
+      if (clazz == NULL) {
+        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand (as field)");
+      }
+      InstanceKlass* defc = InstanceKlass::cast(java_lang_Class::as_Klass(clazz));
+      DEBUG_ONLY(clazz = NULL);  // safety
+      int vmindex  = java_lang_invoke_MemberName::vmindex(mname());
       bool is_static = ((flags & JVM_ACC_STATIC) != 0);
       fieldDescriptor fd; // find_field initializes fd if found
       if (!defc->find_field_from_offset(vmindex, is_static, &fd))
         break;                  // cannot expand
-      if (!have_defc) {
-        java_lang_invoke_MemberName::set_clazz(mname(), defc->java_mirror());
-      }
       if (!have_name) {
         //not java_lang_String::create_from_symbol; let's intern member names
         oop name = StringTable::intern(fd.name(), CHECK);
@@ -871,7 +866,7 @@
 int MethodHandles::find_MemberNames(Klass* k,
                                     Symbol* name, Symbol* sig,
                                     int mflags, Klass* caller,
-                                    int skip, objArrayHandle results) {
+                                    int skip, objArrayHandle results, TRAPS) {
   // %%% take caller into account!
 
   Thread* thread = Thread::current();
@@ -968,10 +963,8 @@
         Handle result(thread, results->obj_at(rfill++));
         if (!java_lang_invoke_MemberName::is_instance(result()))
           return -99;  // caller bug!
-        CallInfo info(m);
-        // Since this is going through the methods to create MemberNames, don't search
-        // for matching methods already in the table
-        oop saved = MethodHandles::init_method_MemberName(result, info, /*intern*/false);
+        CallInfo info(m, NULL, CHECK_0);
+        oop saved = MethodHandles::init_method_MemberName(result, info);
         if (saved != result())
           results->obj_at_put(rfill-1, saved);  // show saved instance to user
       } else if (++overflow >= overflow_limit) {
@@ -1033,95 +1026,6 @@
   }
 }
 
-//------------------------------------------------------------------------------
-// MemberNameTable
-//
-
-MemberNameTable::MemberNameTable(int methods_cnt)
-                  : GrowableArray<jweak>(methods_cnt, true) {
-  assert_locked_or_safepoint(MemberNameTable_lock);
-}
-
-MemberNameTable::~MemberNameTable() {
-  assert_locked_or_safepoint(MemberNameTable_lock);
-  int len = this->length();
-
-  for (int idx = 0; idx < len; idx++) {
-    jweak ref = this->at(idx);
-    JNIHandles::destroy_weak_global(ref);
-  }
-}
-
-oop MemberNameTable::add_member_name(jweak mem_name_wref) {
-  assert_locked_or_safepoint(MemberNameTable_lock);
-  this->push(mem_name_wref);
-  return JNIHandles::resolve(mem_name_wref);
-}
-
-oop MemberNameTable::find_or_add_member_name(jweak mem_name_wref) {
-  assert_locked_or_safepoint(MemberNameTable_lock);
-  oop new_mem_name = JNIHandles::resolve(mem_name_wref);
-
-  // Find matching member name in the list.
-  // This is linear because these are short lists.
-  int len = this->length();
-  int new_index = len;
-  for (int idx = 0; idx < len; idx++) {
-    oop mname = JNIHandles::resolve(this->at(idx));
-    if (mname == NULL) {
-      new_index = idx;
-      continue;
-    }
-    if (java_lang_invoke_MemberName::equals(new_mem_name, mname)) {
-      JNIHandles::destroy_weak_global(mem_name_wref);
-      return mname;
-    }
-  }
-  // Not found, push the new one, or reuse empty slot
-  this->at_put_grow(new_index, mem_name_wref);
-  return new_mem_name;
-}
-
-#if INCLUDE_JVMTI
-// It is called at safepoint only for RedefineClasses
-void MemberNameTable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
-  assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
-  // For each redefined method
-  for (int idx = 0; idx < length(); idx++) {
-    oop mem_name = JNIHandles::resolve(this->at(idx));
-    if (mem_name == NULL) {
-      continue;
-    }
-    Method* old_method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name);
-
-    if (old_method == NULL || !old_method->is_old()) {
-      continue; // skip uninteresting entries
-    }
-    if (old_method->is_deleted()) {
-      // skip entries with deleted methods
-      continue;
-    }
-    Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
-
-    assert(new_method != NULL, "method_with_idnum() should not be NULL");
-    assert(old_method != new_method, "sanity check");
-
-    java_lang_invoke_MemberName::set_vmtarget(mem_name, new_method);
-
-    if (log_is_enabled(Info, redefine, class, update)) {
-      ResourceMark rm;
-      if (!(*trace_name_printed)) {
-        log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
-        *trace_name_printed = true;
-      }
-      log_debug(redefine, class, update, constantpool)
-        ("MemberName method update: %s(%s)",
-         new_method->name()->as_C_string(), new_method->signature()->as_C_string());
-    }
-  }
-}
-#endif // INCLUDE_JVMTI
-
 //
 // Here are the native methods in java.lang.invoke.MethodHandleNatives
 // They are the private interface between this JVM and the HotSpot-specific
@@ -1201,7 +1105,7 @@
   if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
-  MethodHandles::init_MemberName(mname, target);
+  MethodHandles::init_MemberName(mname, target, CHECK);
 }
 JVM_END
 
@@ -1266,7 +1170,7 @@
 
 static jlong find_member_field_offset(oop mname, bool must_be_static, TRAPS) {
   if (mname == NULL ||
-      java_lang_invoke_MemberName::vmtarget(mname) == NULL) {
+      java_lang_invoke_MemberName::clazz(mname) == NULL) {
     THROW_MSG_0(vmSymbols::java_lang_InternalError(), "mname not resolved");
   } else {
     int flags = java_lang_invoke_MemberName::flags(mname);
@@ -1305,17 +1209,17 @@
   if (mname_jh == NULL)  return NULL;
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   intptr_t vmindex  = java_lang_invoke_MemberName::vmindex(mname());
-  Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
   objArrayHandle result = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 2, CHECK_NULL);
   jvalue vmindex_value; vmindex_value.j = (long)vmindex;
   oop x = java_lang_boxing_object::create(T_LONG, &vmindex_value, CHECK_NULL);
   result->obj_at_put(0, x);
-  x = NULL;
-  if (vmtarget == NULL) {
-    x = NULL;
-  } else if (vmtarget->is_klass()) {
-    x = ((Klass*) vmtarget)->java_mirror();
-  } else if (vmtarget->is_method()) {
+
+  int flags = java_lang_invoke_MemberName::flags(mname());
+  if ((flags & IS_FIELD) != 0) {
+    x = java_lang_invoke_MemberName::clazz(mname());
+  } else {
+    Method* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
+    assert(vmtarget != NULL && vmtarget->is_method(), "vmtarget is only method");
     x = mname();
   }
   result->obj_at_put(1, x);
@@ -1360,7 +1264,7 @@
   }
 
   int res = MethodHandles::find_MemberNames(k, name, sig, mflags,
-                                            caller, skip, results);
+                                            caller, skip, results, CHECK_0);
   // TO DO: expand at least some of the MemberNames, to avoid massive callbacks
   return res;
 }
--- a/hotspot/src/share/vm/prims/methodHandles.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp	Sat May 27 09:21:01 2017 -0400
@@ -63,14 +63,13 @@
   // working with member names
   static Handle resolve_MemberName(Handle mname, Klass* caller, TRAPS); // compute vmtarget/vmindex from name/type
   static void expand_MemberName(Handle mname, int suppress, TRAPS);  // expand defc/name/type if missing
-  static Handle new_MemberName(TRAPS);  // must be followed by init_MemberName
-  static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target
+  static oop init_MemberName(Handle mname_h, Handle target_h, TRAPS); // compute vmtarget/vmindex from target
   static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false);
-  static oop init_method_MemberName(Handle mname_h, CallInfo& info, bool intern = true);
+  static oop init_method_MemberName(Handle mname_h, CallInfo& info);
   static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true);
   static int find_MemberNames(Klass* k, Symbol* name, Symbol* sig,
                               int mflags, Klass* caller,
-                              int skip, objArrayHandle results);
+                              int skip, objArrayHandle results, TRAPS);
   // bit values for suppress argument to expand_MemberName:
   enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
 
@@ -227,22 +226,4 @@
   void generate();
 };
 
-//------------------------------------------------------------------------------
-// MemberNameTable
-//
-
-class MemberNameTable : public GrowableArray<jweak> {
- public:
-  MemberNameTable(int methods_cnt);
-  ~MemberNameTable();
-  oop add_member_name(jweak mem_name_ref);
-  oop find_or_add_member_name(jweak mem_name_ref);
-
-#if INCLUDE_JVMTI
-  // RedefineClasses() API support:
-  // If a MemberName refers to old_method then update it to refer to new_method.
-  void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
-#endif // INCLUDE_JVMTI
-};
-
 #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/prims/resolvedMethodTable.cpp	Sat May 27 09:21:01 2017 -0400
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/gcLocker.hpp"
+#include "memory/allocation.hpp"
+#include "oops/oop.inline.hpp"
+#include "oops/method.hpp"
+#include "oops/symbol.hpp"
+#include "prims/resolvedMethodTable.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "utilities/hashtable.inline.hpp"
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1SATBCardTableModRefBS.hpp"
+#endif
+
+
+ResolvedMethodTable::ResolvedMethodTable()
+  : Hashtable<oop, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
+
+oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
+  for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
+    if (p->hash() == hash) {
+      oop target = p->literal();
+      // The method is in the table as a target already
+      if (java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
+        ResourceMark rm;
+        log_debug(membername, table) ("ResolvedMethod entry found for %s index %d",
+                                       method->name_and_sig_as_C_string(), index);
+        return target;
+      }
+    }
+  }
+  return NULL;
+}
+
+unsigned int ResolvedMethodTable::compute_hash(Method* method) {
+  unsigned int name_hash = method->name()->identity_hash();
+  unsigned int signature_hash = method->signature()->identity_hash();
+  return name_hash ^ signature_hash;
+}
+
+
+oop ResolvedMethodTable::lookup(Method* method) {
+  unsigned int hash = compute_hash(method);
+  int index = hash_to_index(hash);
+  return lookup(index, hash, method);
+}
+
+// Tell the GC that this oop was looked up in the table
+static void ensure_oop_alive(oop mname) {
+  // A lookup in the ResolvedMethodTable could return an object that was previously
+  // considered dead. The SATB part of G1 needs to get notified about this
+  // potential resurrection, otherwise the marking might not find the object.
+#if INCLUDE_ALL_GCS
+  if (UseG1GC && mname != NULL) {
+    G1SATBCardTableModRefBS::enqueue(mname);
+  }
+#endif
+}
+
+oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) {
+  assert_locked_or_safepoint(ResolvedMethodTable_lock);
+
+  unsigned int hash = compute_hash(method);
+  int index = hash_to_index(hash);
+
+  // One was added while aquiring the lock
+  oop entry = lookup(index, hash, method);
+  if (entry != NULL) {
+    ensure_oop_alive(entry);
+    return entry;
+  }
+
+  ResolvedMethodEntry* p = (ResolvedMethodEntry*) Hashtable<oop, mtClass>::new_entry(hash, rmethod_name);
+  Hashtable<oop, mtClass>::add_entry(index, p);
+  ResourceMark rm;
+  log_debug(membername, table) ("ResolvedMethod entry added for %s index %d",
+                                 method->name_and_sig_as_C_string(), index);
+  return p->literal();
+}
+
+ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;
+
+oop ResolvedMethodTable::find_method(Method* method) {
+  oop entry = _the_table->lookup(method);
+  ensure_oop_alive(entry);
+  return entry;
+}
+
+oop ResolvedMethodTable::add_method(Handle resolved_method_name) {
+  MutexLocker ml(ResolvedMethodTable_lock);
+  DEBUG_ONLY(NoSafepointVerifier nsv);
+
+  // Check if method has been redefined while taking out ResolvedMethodTable_lock, if so
+  // use new method.
+  Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(resolved_method_name());
+  assert(method->is_method(), "must be method");
+  if (method->is_old()) {
+    // Replace method with redefined version
+    InstanceKlass* holder = method->method_holder();
+    method = holder->method_with_idnum(method->method_idnum());
+    java_lang_invoke_ResolvedMethodName::set_vmtarget(resolved_method_name(), method);
+  }
+  // Set flag in class to indicate this InstanceKlass has entries in the table
+  // to avoid walking table during redefinition if none of the redefined classes
+  // have any membernames in the table.
+  method->method_holder()->set_has_resolved_methods();
+
+  return _the_table->basic_add(method, resolved_method_name());
+}
+
+// Removing entries
+int ResolvedMethodTable::_oops_removed = 0;
+int ResolvedMethodTable::_oops_counted = 0;
+
+// Serially invoke removed unused oops from the table.
+// This is done late during GC.
+void ResolvedMethodTable::unlink(BoolObjectClosure* is_alive) {
+  _oops_removed = 0;
+  _oops_counted = 0;
+  for (int i = 0; i < _the_table->table_size(); ++i) {
+    ResolvedMethodEntry** p = _the_table->bucket_addr(i);
+    ResolvedMethodEntry* entry = _the_table->bucket(i);
+    while (entry != NULL) {
+      _oops_counted++;
+      if (is_alive->do_object_b(entry->literal())) {
+        p = entry->next_addr();
+      } else {
+        _oops_removed++;
+        if (log_is_enabled(Debug, membername, table)) {
+          Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->literal());
+          ResourceMark rm;
+          log_debug(membername, table) ("ResolvedMethod entry removed for %s index %d",
+                                           m->name_and_sig_as_C_string(), i);
+        }
+        *p = entry->next();
+        _the_table->free_entry(entry);
+      }
+      // get next entry
+      entry = (ResolvedMethodEntry*)HashtableEntry<oop, mtClass>::make_ptr(*p);
+    }
+  }
+  log_debug(membername, table) ("ResolvedMethod entries counted %d removed %d",
+                                _oops_counted, _oops_removed);
+}
+
+// Serially invoke "f->do_oop" on the locations of all oops in the table.
+void ResolvedMethodTable::oops_do(OopClosure* f) {
+  for (int i = 0; i < _the_table->table_size(); ++i) {
+    ResolvedMethodEntry* entry = _the_table->bucket(i);
+    while (entry != NULL) {
+      f->do_oop(entry->literal_addr());
+      entry = entry->next();
+    }
+  }
+}
+
+#ifndef PRODUCT
+void ResolvedMethodTable::print() {
+  for (int i = 0; i < table_size(); ++i) {
+    ResolvedMethodEntry* entry = bucket(i);
+    while (entry != NULL) {
+      tty->print("%d : ", i);
+      oop rmethod_name = entry->literal();
+      rmethod_name->print();
+      Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
+      m->print();
+      entry = entry->next();
+    }
+  }
+}
+#endif // PRODUCT
+
+#if INCLUDE_JVMTI
+// It is called at safepoint only for RedefineClasses
+void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
+  assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
+  // For each entry in RMT, change to new method
+  for (int i = 0; i < _the_table->table_size(); ++i) {
+    ResolvedMethodEntry* entry = _the_table->bucket(i);
+    while (entry != NULL) {
+
+      oop mem_name = entry->literal();
+      Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
+
+      if (old_method->is_old()) {
+
+        if (old_method->is_deleted()) {
+          // leave deleted method in ResolvedMethod for now (this is a bug that we don't mark
+          // these on_stack)
+          continue;
+        }
+
+        InstanceKlass* holder = old_method->method_holder();
+        Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
+        assert(holder == new_method->method_holder(), "call after swapping redefined guts");
+        assert(new_method != NULL, "method_with_idnum() should not be NULL");
+        assert(old_method != new_method, "sanity check");
+
+        java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
+
+        ResourceMark rm;
+        if (!(*trace_name_printed)) {
+          log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
+           *trace_name_printed = true;
+        }
+        log_debug(redefine, class, update, constantpool)
+          ("ResolvedMethod method update: %s(%s)",
+           new_method->name()->as_C_string(), new_method->signature()->as_C_string());
+      }
+      entry = entry->next();
+    }
+  }
+}
+#endif // INCLUDE_JVMTI
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/prims/resolvedMethodTable.hpp	Sat May 27 09:21:01 2017 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_PRIMS_RESOLVEDMETHOD_HPP
+#define SHARE_VM_PRIMS_RESOLVEDMETHOD_HPP
+
+#include "oops/symbol.hpp"
+#include "utilities/hashtable.hpp"
+
+// Hashtable to record Method* used in ResolvedMethods, via. ResolvedMethod oops.
+// This is needed for redefinition to replace Method* with redefined versions.
+
+// Entry in a ResolvedMethodTable, mapping a single oop of java_lang_invoke_ResolvedMethodName which
+// holds JVM Method* in vmtarget.
+
+class ResolvedMethodEntry : public HashtableEntry<oop, mtClass> {
+ public:
+  ResolvedMethodEntry* next() const {
+    return (ResolvedMethodEntry*)HashtableEntry<oop, mtClass>::next();
+  }
+
+  ResolvedMethodEntry** next_addr() {
+    return (ResolvedMethodEntry**)HashtableEntry<oop, mtClass>::next_addr();
+  }
+
+  void print_on(outputStream* st) const;
+};
+
+class ResolvedMethodTable : public Hashtable<oop, mtClass> {
+  enum Constants {
+    _table_size  = 1007
+  };
+
+  static int _oops_removed;
+  static int _oops_counted;
+
+  static ResolvedMethodTable* _the_table;
+private:
+  ResolvedMethodEntry* bucket(int i) {
+    return (ResolvedMethodEntry*) Hashtable<oop, mtClass>::bucket(i);
+  }
+
+  ResolvedMethodEntry** bucket_addr(int i) {
+    return (ResolvedMethodEntry**) Hashtable<oop, mtClass>::bucket_addr(i);
+  }
+
+  unsigned int compute_hash(Method* method);
+
+  // need not be locked; no state change
+  oop lookup(int index, unsigned int hash, Method* method);
+  oop lookup(Method* method);
+
+  // must be done under ResolvedMethodTable_lock
+  oop basic_add(Method* method, oop rmethod_name);
+
+public:
+  ResolvedMethodTable();
+
+  static void create_table() {
+    assert(_the_table == NULL, "One symbol table allowed.");
+    _the_table = new ResolvedMethodTable();
+  }
+
+  // Called from java_lang_invoke_ResolvedMethodName
+  static oop find_method(Method* method);
+  static oop add_method(Handle rmethod_name);
+
+#if INCLUDE_JVMTI
+  // It is called at safepoint only for RedefineClasses
+  static void adjust_method_entries(bool * trace_name_printed);
+#endif // INCLUDE_JVMTI
+
+  // Cleanup cleared entries
+  static void unlink(BoolObjectClosure* is_alive);
+  static void oops_do(OopClosure* f);
+
+#ifndef PRODUCT
+  void print();
+#endif
+  void verify();
+};
+
+#endif // SHARE_VM_PRIMS_RESOLVEDMETHOD_HPP
--- a/hotspot/src/share/vm/prims/stackwalk.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/prims/stackwalk.cpp	Sat May 27 09:21:01 2017 -0400
@@ -167,7 +167,7 @@
                                  const methodHandle& method, TRAPS) {
   if (_need_method_info) {
     Handle stackFrame(THREAD, frames_array->obj_at(index));
-    fill_stackframe(stackFrame, method);
+    fill_stackframe(stackFrame, method, CHECK);
   } else {
     frames_array->obj_at_put(index, method->method_holder()->java_mirror());
   }
@@ -270,15 +270,15 @@
 }
 
 // Fill StackFrameInfo with declaringClass and bci and initialize memberName
-void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method) {
+void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS) {
   java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror());
-  java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci());
+  java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), THREAD);
 }
 
 // Fill LiveStackFrameInfo with locals, monitors, and expressions
 void LiveFrameStream::fill_live_stackframe(Handle stackFrame,
                                            const methodHandle& method, TRAPS) {
-  fill_stackframe(stackFrame, method);
+  fill_stackframe(stackFrame, method, CHECK);
   if (_jvf != NULL) {
     StackValueCollection* locals = _jvf->locals();
     StackValueCollection* expressions = _jvf->expressions();
--- a/hotspot/src/share/vm/prims/stackwalk.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/prims/stackwalk.hpp	Sat May 27 09:21:01 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
   JavaThread*           _thread;
   jlong                 _anchor;
 protected:
-  void fill_stackframe(Handle stackFrame, const methodHandle& method);
+  void fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS);
 public:
   BaseFrameStream(JavaThread* thread) : _thread(thread), _anchor(0L) {}
 
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Sat May 27 09:21:01 2017 -0400
@@ -45,7 +45,7 @@
 Mutex*   VMStatistic_lock             = NULL;
 Mutex*   JNIGlobalHandle_lock         = NULL;
 Mutex*   JNIHandleBlockFreeList_lock  = NULL;
-Mutex*   MemberNameTable_lock         = NULL;
+Mutex*   ResolvedMethodTable_lock     = NULL;
 Mutex*   JmethodIdCreation_lock       = NULL;
 Mutex*   JfieldIdCreation_lock        = NULL;
 Monitor* JNICritical_lock             = NULL;
@@ -255,7 +255,7 @@
 
   def(Heap_lock                    , PaddedMonitor, nonleaf+1,   false, Monitor::_safepoint_check_sometimes);
   def(JfieldIdCreation_lock        , PaddedMutex  , nonleaf+1,   true,  Monitor::_safepoint_check_always);     // jfieldID, Used in VM_Operation
-  def(MemberNameTable_lock         , PaddedMutex  , nonleaf+1,   false, Monitor::_safepoint_check_always);     // Used to protect MemberNameTable
+  def(ResolvedMethodTable_lock     , PaddedMutex  , nonleaf+1,   false, Monitor::_safepoint_check_always);     // Used to protect ResolvedMethodTable
 
   def(CompiledIC_lock              , PaddedMutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // locks VtableStubs_lock, InlineCacheBuffer_lock
   def(CompileTaskAlloc_lock        , PaddedMutex  , nonleaf+2,   true,  Monitor::_safepoint_check_always);
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Sat May 27 09:21:01 2017 -0400
@@ -38,7 +38,7 @@
 extern Mutex*   VMStatistic_lock;                // a lock used to guard statistics count increment
 extern Mutex*   JNIGlobalHandle_lock;            // a lock on creating JNI global handles
 extern Mutex*   JNIHandleBlockFreeList_lock;     // a lock on the JNI handle block free list
-extern Mutex*   MemberNameTable_lock;            // a lock on the MemberNameTable updates
+extern Mutex*   ResolvedMethodTable_lock;        // a lock on the ResolvedMethodTable updates
 extern Mutex*   JmethodIdCreation_lock;          // a lock on creating JNI method identifiers
 extern Mutex*   JfieldIdCreation_lock;           // a lock on creating JNI static field identifiers
 extern Monitor* JNICritical_lock;                // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in
--- a/hotspot/src/share/vm/runtime/thread.cpp	Fri May 26 13:47:33 2017 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Sat May 27 09:21:01 2017 -0400
@@ -3493,6 +3493,7 @@
   TraceTime timer("Initialize java.lang.invoke classes", TRACETIME_LOG(Info, startuptime));
 
   initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK);
+  initialize_class(vmSymbols::java_lang_invoke_ResolvedMethodName(), CHECK);
   initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK);
   initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/MemberName/MemberNameLeak.java	Sat May 27 09:21:01 2017 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8174749
+ * @summary MemberNameTable should reuse entries
+ * @library /test/lib
+ * @run main MemberNameLeak
+ */
+
+import java.lang.invoke.*;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class MemberNameLeak {
+    static class Leak {
+      public void callMe() {
+      }
+
+      public static void main(String[] args) throws Throwable {
+        Leak leak = new Leak();
+
+        for (int i = 0; i < 10; i++) {
+          MethodHandles.Lookup lookup = MethodHandles.lookup();
+          MethodType mt = MethodType.fromMethodDescriptorString("()V", Leak.class.getClassLoader());
+          // findSpecial leaks some native mem
+          MethodHandle mh = lookup.findSpecial(Leak.class, "callMe", mt, Leak.class);
+          mh.invokeExact(leak);
+        }
+
+        System.gc();  // make mh unused
+      }
+    }
+
+    public static void test(String gc) throws Throwable {
+       // Run this Leak class with logging
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+                                      "-Xlog:membername+table=trace",
+                                      gc, Leak.class.getName());
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("ResolvedMethod entry added for MemberNameLeak$Leak.callMe()V");
+        output.shouldContain("ResolvedMethod entry found for MemberNameLeak$Leak.callMe()V");
+        output.shouldContain("ResolvedMethod entry removed for MemberNameLeak$Leak.callMe()V");
+        output.shouldHaveExitValue(0);
+    }
+
+    public static void main(java.lang.String[] unused) throws Throwable {
+        test("-XX:+UseG1GC");
+        test("-XX:+UseParallelGC");
+        test("-XX:+UseSerialGC");
+        test("-XX:+UseConcMarkSweepGC");
+    }
+}