--- old/src/share/vm/ci/ciMethod.cpp 2016-06-02 12:26:07.302263850 +0200 +++ new/src/share/vm/ci/ciMethod.cpp 2016-06-02 12:26:07.086263857 +0200 @@ -789,7 +789,7 @@ Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); - LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access); + LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, NULL, check_access); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. @@ -843,7 +843,7 @@ Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); - LinkInfo link_info(h_recv, h_name, h_signature, caller_klass); + LinkInfo link_info(h_recv, h_name, h_signature, caller_klass, NULL); vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, link_info); if (vtable_index == Method::nonvirtual_vtable_index) { // A statically bound method. Return "no such index". --- old/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantPool.java 2016-06-02 12:26:07.418263846 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantPool.java 2016-06-02 12:26:07.138263855 +0200 @@ -48,16 +48,18 @@ /** * Looks up a reference to a field. If {@code opcode} is non-negative, then resolution checks - * specific to the bytecode it denotes are performed if the field is already resolved. Should + * specific to the bytecode it denotes are performed if the field is already resolved. Checks + * for some bytecodes require the method that contains the bytecode to be specified. Should * any of these checks fail, an unresolved field reference is returned. * * @param cpi the constant pool index * @param opcode the opcode of the instruction for which the lookup is being performed or * {@code -1} + * @param method the method for which the lookup is being performed * @return a reference to the field at {@code cpi} in this pool * @throws ClassFormatError if the entry at {@code cpi} is not a field */ - JavaField lookupField(int cpi, int opcode); + JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode); /** * Looks up a reference to a method. If {@code opcode} is non-negative, then resolution checks --- old/src/share/vm/ci/ciStreams.cpp 2016-06-02 12:26:07.342263849 +0200 +++ new/src/share/vm/ci/ciStreams.cpp 2016-06-02 12:26:07.070263857 +0200 @@ -278,7 +278,7 @@ // or put_static, get the referenced field. ciField* ciBytecodeStream::get_field(bool& will_link) { ciField* f = CURRENT_ENV->get_field_by_index(_holder, get_field_index()); - will_link = f->will_link(_holder, _bc); + will_link = f->will_link(_holder, _method, _bc); return f; } --- old/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java 2016-06-02 12:26:07.378263847 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java 2016-06-02 12:26:07.042263858 +0200 @@ -587,7 +587,7 @@ } @Override - public JavaField lookupField(int cpi, int opcode) { + public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) { final int index = rawIndexToConstantPoolIndex(cpi, opcode); final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index); final int nameIndex = getNameRefIndexAt(nameAndTypeIndex); @@ -603,7 +603,7 @@ long[] info = new long[2]; HotSpotResolvedObjectTypeImpl resolvedHolder; try { - resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (byte) opcode, info); + resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info); } catch (Throwable t) { /* * If there was an exception resolving the field we give up and return an unresolved --- old/src/share/vm/ci/ciField.hpp 2016-06-02 12:26:07.426263846 +0200 +++ new/src/share/vm/ci/ciField.hpp 2016-06-02 12:26:07.050263858 +0200 @@ -158,6 +158,7 @@ // in the same compilation, will_link will need to be checked // at each point of access. bool will_link(ciInstanceKlass* accessing_klass, + ciMethod* accessing_method, Bytecodes::Code bc); // Java access flags --- old/src/share/vm/c1/c1_Runtime1.cpp 2016-06-02 12:26:07.474263844 +0200 +++ new/src/share/vm/c1/c1_Runtime1.cpp 2016-06-02 12:26:07.098263856 +0200 @@ -762,7 +762,7 @@ // We must load class, initialize class and resolvethe field fieldDescriptor result; // initialize class if needed constantPoolHandle constants(THREAD, caller->constants()); - LinkResolver::resolve_field_access(result, constants, field_access.index(), Bytecodes::java_code(code), CHECK_NULL); + LinkResolver::resolve_field_access(result, constants, field_access.index(), caller, Bytecodes::java_code(code), CHECK_NULL); return result.field_holder(); } @@ -879,7 +879,7 @@ fieldDescriptor result; // initialize class if needed Bytecodes::Code code = field_access.code(); constantPoolHandle constants(THREAD, caller_method->constants()); - LinkResolver::resolve_field_access(result, constants, field_access.index(), Bytecodes::java_code(code), CHECK); + LinkResolver::resolve_field_access(result, constants, field_access.index(), caller_method, Bytecodes::java_code(code), CHECK); patch_field_offset = result.offset(); // If we're patching a field which is volatile then at compile it --- old/src/share/vm/interpreter/linkResolver.cpp 2016-06-02 12:26:07.458263845 +0200 +++ new/src/share/vm/interpreter/linkResolver.cpp 2016-06-02 12:26:07.102263856 +0200 @@ -223,7 +223,7 @@ //------------------------------------------------------------------------------------------------------------------------ // Implementation of LinkInfo -LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { +LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, methodHandle current_method, TRAPS) { // resolve klass Klass* result = pool->klass_ref_at(index, CHECK); _resolved_klass = KlassHandle(THREAD, result); @@ -232,6 +232,7 @@ _name = pool->name_ref_at(index); _signature = pool->signature_ref_at(index); _current_klass = KlassHandle(THREAD, pool->pool_holder()); + _current_method = current_method; // Coming from the constant pool always checks access _check_access = true; @@ -572,11 +573,11 @@ Symbol* method_name = vmSymbols::invoke_name(); Symbol* method_signature = pool->signature_ref_at(index); KlassHandle current_klass(THREAD, pool->pool_holder()); - LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass); + LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass, NULL); return resolve_method(link_info, /*require_methodref*/false, THREAD); } - LinkInfo link_info(pool, index, CHECK_NULL); + LinkInfo link_info(pool, index, NULL, CHECK_NULL); resolved_klass = link_info.resolved_klass(); if (pool->has_preresolution() @@ -857,8 +858,8 @@ } } -void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS) { - LinkInfo link_info(pool, index, CHECK); +void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, const methodHandle& method, Bytecodes::Code byte, TRAPS) { + LinkInfo link_info(pool, index, method, CHECK); resolve_field(fd, link_info, byte, true, CHECK); } @@ -907,9 +908,20 @@ THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); } - // Final fields can only be accessed from its own class. - if (is_put && fd.access_flags().is_final() && sel_klass() != current_klass()) { - THROW(vmSymbols::java_lang_IllegalAccessError()); + // A final field can be modified only + // (1) by methods declared in the class declaring the field and + // (2) by the method (in case of a static field) + // or by the method (in case of an instance field). + if (is_put && fd.access_flags().is_final()) { + methodHandle m = link_info.current_method(); + assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes"); + Symbol* method_name = m->name(); + if (sel_klass() != current_klass() || + (byte == Bytecodes::_putstatic && fd.is_static() && method_name != vmSymbols::class_initializer_name()) || + ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) && !fd.is_static() && method_name != vmSymbols::object_initializer_name()) + ) { + THROW(vmSymbols::java_lang_IllegalAccessError()); + } } // initialize resolved_klass if necessary @@ -956,7 +968,7 @@ resolved_klass->initialize(CHECK); // Use updated LinkInfo (to reresolve with resolved_klass as method_holder?) LinkInfo new_info(resolved_klass, link_info.name(), link_info.signature(), - link_info.current_klass(), link_info.check_access()); + link_info.current_klass(), NULL, link_info.check_access()); resolved_method = linktime_resolve_static_method(new_info, CHECK); } @@ -1482,7 +1494,7 @@ KlassHandle defc = attached_method->method_holder(); Symbol* name = attached_method->name(); Symbol* type = attached_method->signature(); - LinkInfo link_info(defc, name, type, KlassHandle(), /*check_access=*/false); + LinkInfo link_info(defc, name, type, KlassHandle(), NULL, /*check_access=*/false); switch(byte) { case Bytecodes::_invokevirtual: resolve_virtual_call(result, recv, recv->klass(), link_info, @@ -1504,13 +1516,13 @@ } void LinkResolver::resolve_invokestatic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { - LinkInfo link_info(pool, index, CHECK); + LinkInfo link_info(pool, index, NULL, CHECK); resolve_static_call(result, link_info, /*initialize_class*/true, CHECK); } void LinkResolver::resolve_invokespecial(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { - LinkInfo link_info(pool, index, CHECK); + LinkInfo link_info(pool, index, NULL, CHECK); resolve_special_call(result, link_info, CHECK); } @@ -1519,14 +1531,14 @@ const constantPoolHandle& pool, int index, TRAPS) { - LinkInfo link_info(pool, index, CHECK); + LinkInfo link_info(pool, index, NULL, CHECK); KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); } void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) { - LinkInfo link_info(pool, index, CHECK); + LinkInfo link_info(pool, index, NULL, CHECK); KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); } @@ -1534,7 +1546,7 @@ void LinkResolver::resolve_invokehandle(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { // This guy is reached from InterpreterRuntime::resolve_invokehandle. - LinkInfo link_info(pool, index, CHECK); + LinkInfo link_info(pool, index, NULL, CHECK); if (TraceMethodHandles) { ResourceMark rm(THREAD); tty->print_cr("resolve_invokehandle %s %s", link_info.name()->as_C_string(), --- old/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java 2016-06-02 12:26:07.458263845 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java 2016-06-02 12:26:07.070263857 +0200 @@ -267,8 +267,9 @@ native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, int cpi) throws LinkageError; /** - * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry at index {@code cpi} in - * {@code constantPool}. The values returned in {@code info} are: + * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index {@code cpi} in + * {@code constantPool}. For some opcodes, checks are performed that require the {@code method} + * that contains {@code opcode} to be specified. The values returned in {@code info} are: * *
      *     [(int) flags,   // only valid if field is resolved
@@ -281,7 +282,7 @@
      * @param info an array in which the details of the field are returned
      * @return the type defining the field if resolution is successful, 0 otherwise
      */
-    native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, byte opcode, long[] info);
+    native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, HotSpotResolvedJavaMethodImpl method, byte opcode, long[] info);
 
     /**
      * Converts {@code cpci} from an index into the cache for {@code constantPool} to an index
--- old/src/share/vm/interpreter/interpreterRuntime.cpp	2016-06-02 12:26:07.470263844 +0200
+++ new/src/share/vm/interpreter/interpreterRuntime.cpp	2016-06-02 12:26:07.074263857 +0200
@@ -558,6 +558,7 @@
   // resolve field
   fieldDescriptor info;
   constantPoolHandle pool(thread, method(thread)->constants());
+  methodHandle m(thread, method(thread));
   bool is_put    = (bytecode == Bytecodes::_putfield  || bytecode == Bytecodes::_nofast_putfield ||
                     bytecode == Bytecodes::_putstatic);
   bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic);
@@ -565,7 +566,7 @@
   {
     JvmtiHideSingleStepping jhss(thread);
     LinkResolver::resolve_field_access(info, pool, get_index_u2_cpcache(thread, bytecode),
-                                       bytecode, CHECK);
+                                       m, bytecode, CHECK);
   } // end JvmtiHideSingleStepping
 
   // check if link resolution caused cpCache to be updated
--- old/src/share/vm/ci/ciField.cpp	2016-06-02 12:26:07.498263844 +0200
+++ new/src/share/vm/ci/ciField.cpp	2016-06-02 12:26:07.126263856 +0200
@@ -341,6 +341,7 @@
 // Can a specific access to this field be made without causing
 // link errors?
 bool ciField::will_link(ciInstanceKlass* accessing_klass,
+                        ciMethod* accessing_method,
                         Bytecodes::Code bc) {
   VM_ENTRY_MARK;
   assert(bc == Bytecodes::_getstatic || bc == Bytecodes::_putstatic ||
@@ -374,7 +375,7 @@
 
   LinkInfo link_info(_holder->get_instanceKlass(),
                      _name->get_symbol(), _signature->get_symbol(),
-                     accessing_klass->get_Klass());
+                     accessing_klass->get_Klass(), accessing_method->get_Method());
   fieldDescriptor result;
   LinkResolver::resolve_field(result, link_info, bc, false, KILL_COMPILE_ON_FATAL_(false));
 
--- old/src/share/vm/ci/ciEnv.cpp	2016-06-02 12:26:07.502263843 +0200
+++ new/src/share/vm/ci/ciEnv.cpp	2016-06-02 12:26:07.158263854 +0200
@@ -710,7 +710,7 @@
   KlassHandle h_holder(THREAD, holder);
   LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
   methodHandle dest_method;
-  LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
+  LinkInfo link_info(h_holder, name, sig, h_accessor, NULL, /*check_access*/true);
   switch (bc) {
   case Bytecodes::_invokestatic:
     dest_method =
--- old/src/share/vm/c1/c1_GraphBuilder.cpp	2016-06-02 12:26:07.514263843 +0200
+++ new/src/share/vm/c1/c1_GraphBuilder.cpp	2016-06-02 12:26:07.218263853 +0200
@@ -1600,7 +1600,7 @@
   ValueType* type = as_ValueType(field_type);
   // call will_link again to determine if the field is valid.
   const bool needs_patching = !holder->is_loaded() ||
-                              !field->will_link(method()->holder(), code) ||
+                              !field->will_link(method()->holder(), method(), code) ||
                               PatchALot;
 
   ValueStack* state_before = NULL;
--- old/src/share/vm/interpreter/linkResolver.hpp	2016-06-02 12:26:07.778263834 +0200
+++ new/src/share/vm/interpreter/linkResolver.hpp	2016-06-02 12:26:07.706263837 +0200
@@ -131,27 +131,33 @@
 //   resolved_klass = specified class (i.e., static receiver class)
 //   current_klass  = sending method holder (i.e., class containing the method
 //                    containing the call being resolved)
+//   current_method = sending method (relevant for field resolution)
 class LinkInfo : public StackObj {
-  Symbol*     _name;            // extracted from JVM_CONSTANT_NameAndType
-  Symbol*     _signature;
-  KlassHandle _resolved_klass;  // class that the constant pool entry points to
-  KlassHandle _current_klass;   // class that owns the constant pool
-  bool        _check_access;
+  Symbol*      _name;            // extracted from JVM_CONSTANT_NameAndType
+  Symbol*      _signature;
+  KlassHandle  _resolved_klass;  // class that the constant pool entry points to
+  KlassHandle  _current_klass;   // class that owns the constant pool
+  methodHandle _current_method;  // sending method
+  bool         _check_access;
  public:
-  LinkInfo(const constantPoolHandle& pool, int index, TRAPS);
+  LinkInfo(const constantPoolHandle& pool, int index, methodHandle current_method, TRAPS);
   // Condensed information from other call sites within the vm.
-  LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
-           KlassHandle current_klass, bool check_access = true) :
+  LinkInfo(KlassHandle resolved_klass,
+           Symbol* name, Symbol* signature, // field or method signature
+           KlassHandle current_klass, methodHandle current_method,
+           bool check_access = true) :
     _resolved_klass(resolved_klass),
-    _name(name), _signature(signature), _current_klass(current_klass),
+    _name(name), _signature(signature),
+    _current_klass(current_klass), _current_method(current_method),
     _check_access(check_access) {}
 
   // accessors
-  Symbol* name() const               { return _name; }
-  Symbol* signature() const          { return _signature; }
-  KlassHandle resolved_klass() const { return _resolved_klass; }
-  KlassHandle current_klass() const  { return _current_klass; }
-  bool check_access() const          { return _check_access; }
+  Symbol* name() const                { return _name; }
+  Symbol* signature() const           { return _signature; }
+  KlassHandle resolved_klass() const  { return _resolved_klass; }
+  KlassHandle current_klass() const   { return _current_klass; }
+  methodHandle current_method() const { return _current_method; }
+  bool check_access() const           { return _check_access; }
   char* method_string() const;
 
   void         print()  PRODUCT_RETURN;
@@ -251,7 +257,9 @@
 
   static void resolve_field_access(fieldDescriptor& result,
                                    const constantPoolHandle& pool,
-                                   int index, Bytecodes::Code byte, TRAPS);
+                                   int index,
+                                   const methodHandle& method,
+                                   Bytecodes::Code byte, TRAPS);
   static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info,
                             Bytecodes::Code access_kind,
                             bool initialize_class, TRAPS);
--- old/src/share/vm/prims/methodHandles.cpp	2016-06-02 12:26:09.478263780 +0200
+++ new/src/share/vm/prims/methodHandles.cpp	2016-06-02 12:26:09.202263789 +0200
@@ -718,7 +718,7 @@
   case IS_METHOD:
     {
       CallInfo result;
-      LinkInfo link_info(defc, name, type, caller, caller.not_null());
+      LinkInfo link_info(defc, name, type, caller, NULL, caller.not_null());
       {
         assert(!HAS_PENDING_EXCEPTION, "");
         if (ref_kind == JVM_REF_invokeStatic) {
@@ -755,7 +755,7 @@
   case IS_CONSTRUCTOR:
     {
       CallInfo result;
-      LinkInfo link_info(defc, name, type, caller, caller.not_null());
+      LinkInfo link_info(defc, name, type, caller, NULL, caller.not_null());
       {
         assert(!HAS_PENDING_EXCEPTION, "");
         if (name == vmSymbols::object_initializer_name()) {
@@ -776,7 +776,7 @@
       fieldDescriptor result; // find_field initializes fd if found
       {
         assert(!HAS_PENDING_EXCEPTION, "");
-        LinkInfo link_info(defc, name, type, caller, /*check_access*/false);
+        LinkInfo link_info(defc, name, type, caller, NULL, /*check_access*/false);
         LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
         if (HAS_PENDING_EXCEPTION) {
           return empty;
--- old/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java	2016-06-02 12:26:09.490263779 +0200
+++ new/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java	2016-06-02 12:26:09.214263788 +0200
@@ -34,6 +34,7 @@
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
  *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.LookupMethodInPoolTest
--- old/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	2016-06-02 12:26:09.490263779 +0200
+++ new/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	2016-06-02 12:26:09.194263789 +0200
@@ -124,8 +124,8 @@
     }
 
     public static HotSpotResolvedObjectType resolveFieldInPool(
-            ConstantPool constantPool, int cpi, byte opcode, long[] info) {
-        return CTVM.resolveFieldInPool((HotSpotConstantPool) constantPool, cpi, opcode, info);
+            ConstantPool constantPool, int cpi, ResolvedJavaMethod method, byte opcode, long[] info) {
+        return CTVM.resolveFieldInPool((HotSpotConstantPool) constantPool, cpi, (HotSpotResolvedJavaMethodImpl) method, opcode, info);
     }
 
     public static int constantPoolRemapInstructionOperandFromCache(
--- old/src/share/vm/jvmci/jvmciCompilerToVM.cpp	2016-06-02 12:26:09.562263777 +0200
+++ new/src/share/vm/jvmci/jvmciCompilerToVM.cpp	2016-06-02 12:26:09.226263788 +0200
@@ -621,12 +621,12 @@
   return cp->remap_instruction_operand_from_cache(index);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode, jlongArray info_handle))
+C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jlongArray info_handle))
   ResourceMark rm;
   constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
   Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
   fieldDescriptor fd;
-  LinkInfo link_info(cp, index, CHECK_0);
+  LinkInfo link_info(cp, index, (jvmci_method != NULL) ? CompilerToVM::asMethod(jvmci_method) : NULL, CHECK_0);
   LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_0);
   typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
   assert(info != NULL && info->length() == 2, "must be");
@@ -662,7 +662,7 @@
   Symbol* h_signature = method->signature();
 
   bool check_access = true;
-  LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access);
+  LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, NULL, check_access);
   methodHandle m;
   // Only do exact lookup if receiver klass has been linked.  Otherwise,
   // the vtable has not been setup, and the LinkResolver will fail.
@@ -1441,7 +1441,7 @@
   {CC "resolveConstantInPool",                        CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(resolveConstantInPool)},
   {CC "resolvePossiblyCachedConstantInPool",          CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(resolvePossiblyCachedConstantInPool)},
   {CC "resolveTypeInPool",                            CC "(" HS_CONSTANT_POOL "I)" HS_RESOLVED_KLASS,                                       FN_PTR(resolveTypeInPool)},
-  {CC "resolveFieldInPool",                           CC "(" HS_CONSTANT_POOL "IB[J)" HS_RESOLVED_KLASS,                                    FN_PTR(resolveFieldInPool)},
+  {CC "resolveFieldInPool",                           CC "(" HS_CONSTANT_POOL "I" HS_RESOLVED_METHOD "B[J)" HS_RESOLVED_KLASS,              FN_PTR(resolveFieldInPool)},
   {CC "resolveInvokeDynamicInPool",                   CC "(" HS_CONSTANT_POOL "I)V",                                                        FN_PTR(resolveInvokeDynamicInPool)},
   {CC "resolveInvokeHandleInPool",                    CC "(" HS_CONSTANT_POOL "I)V",                                                        FN_PTR(resolveInvokeHandleInPool)},
   {CC "resolveMethod",                                CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(resolveMethod)},
--- old/src/share/vm/runtime/reflection.cpp	2016-06-02 12:26:09.546263777 +0200
+++ new/src/share/vm/runtime/reflection.cpp	2016-06-02 12:26:09.234263788 +0200
@@ -998,7 +998,7 @@
   Symbol*  signature  = method->signature();
   Symbol*  name       = method->name();
   LinkResolver::resolve_interface_call(info, receiver, recv_klass,
-                                       LinkInfo(klass, name, signature, KlassHandle(), false),
+                                       LinkInfo(klass, name, signature, KlassHandle(), NULL, false),
                                        true,
                                        CHECK_(methodHandle()));
   return info.selected_method();
--- old/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java	2016-06-02 12:26:09.590263776 +0200
+++ new/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java	2016-06-02 12:26:09.210263788 +0200
@@ -34,6 +34,7 @@
  *          java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java	2016-06-02 12:26:09.606263776 +0200
+++ new/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java	2016-06-02 12:26:09.210263788 +0200
@@ -31,6 +31,10 @@
 import compiler.jvmci.compilerToVM.ConstantPoolTestCase.TestedCPEntry;
 import java.util.HashMap;
 import java.util.Map;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import sun.hotspot.WhiteBox;
@@ -44,6 +48,7 @@
 public class ConstantPoolTestsHelper {
 
     public static final int NO_CP_CACHE_PRESENT = Integer.MAX_VALUE;
+    private static final MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
 
     public enum DummyClasses {
         DUMMY_CLASS(MultipleImplementer2.class, CP_MAP_FOR_CLASS),
@@ -76,6 +81,45 @@
         }
     }
 
+    /**
+     * Obtain a resolved Java method declared by a given type. 
+     * 
+     * @param type the declaring type
+     * @param the method's name 
+     *  
+     * Currently, the lookup is based only on the method's name
+     * but not on the method's signature (i.e., the first method
+     * with a matching name declared on {@code type} is returned).
+     */
+    private static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) {
+        if (methodName.equals("")) {
+            return type.getClassInitializer();
+        }
+
+        if (methodName.equals("")) {
+            ResolvedJavaMethod[] initializers = type.getDeclaredConstructors();
+            if (initializers.length >= 0) {
+                return initializers[0];
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+            if (method.getName().equals(methodName)) {
+                return method;
+            }
+        }
+
+        throw new IllegalArgumentException();
+    }
+
+    private static ResolvedJavaType getType(Class clazz) {
+        ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
+        type.initialize();
+        return type;
+    }
+
     private static final Map CP_MAP_FOR_CLASS = new HashMap<>();
     static {
         CP_MAP_FOR_CLASS.put(CONSTANT_CLASS,
@@ -141,6 +185,7 @@
                     new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
                                       "objectField",
                                       "Ljava/lang/Object;",
+                                      new ResolvedJavaMethod[] { getMethod(getType(MultipleImplementer2.class), ""), null },
                                       new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
                                       Opcodes.ACC_FINAL),
                     new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementer2",
@@ -296,6 +341,7 @@
                     new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
                                       "objectField",
                                       "Ljava/lang/Object;",
+                                      new ResolvedJavaMethod[] { getMethod(getType(MultipleAbstractImplementer.class), ""), null },
                                       new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
                                       Opcodes.ACC_FINAL),
                     new TestedCPEntry("compiler/jvmci/common/testcases/MultipleAbstractImplementer",
@@ -401,6 +447,7 @@
                     new TestedCPEntry("compiler/jvmci/common/testcases/MultipleImplementersInterface",
                                       "OBJECT_CONSTANT",
                                       "Ljava/lang/Object;",
+                                      new ResolvedJavaMethod[] { getMethod(getType(MultipleImplementersInterface.class), ""), null },
                                       new byte[] {(byte) Opcodes.PUTSTATIC, (byte) Opcodes.GETSTATIC},
                                       Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC),
                 }
--- old/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java	2016-06-02 12:26:09.570263777 +0200
+++ new/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java	2016-06-02 12:26:09.194263789 +0200
@@ -33,6 +33,7 @@
  *          java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/src/share/vm/jvmci/jvmciEnv.cpp	2016-06-02 12:26:09.614263775 +0200
+++ new/src/share/vm/jvmci/jvmciEnv.cpp	2016-06-02 12:26:09.234263788 +0200
@@ -290,7 +290,7 @@
   JVMCI_EXCEPTION_CONTEXT;
   LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
   methodHandle dest_method;
-  LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
+  LinkInfo link_info(h_holder, name, sig, h_accessor, NULL, /*check_access*/true);
   switch (bc) {
   case Bytecodes::_invokestatic:
     dest_method =
--- old/src/share/vm/opto/parse3.cpp	2016-06-02 12:26:09.618263775 +0200
+++ new/src/share/vm/opto/parse3.cpp	2016-06-02 12:26:09.210263788 +0200
@@ -109,7 +109,7 @@
     return;
   }
 
-  assert(field->will_link(method()->holder(), bc()), "getfield: typeflow responsibility");
+  assert(field->will_link(method()->holder(), method(), bc()), "getfield: typeflow responsibility");
 
   // Note:  We do not check for an unloaded field type here any more.
 
--- old/src/share/vm/runtime/javaCalls.cpp	2016-06-02 12:26:09.614263775 +0200
+++ new/src/share/vm/runtime/javaCalls.cpp	2016-06-02 12:26:09.198263789 +0200
@@ -183,7 +183,7 @@
   CallInfo callinfo;
   Handle receiver = args->receiver();
   KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass());
-  LinkInfo link_info(spec_klass, name, signature, KlassHandle(), /*check_access*/false);
+  LinkInfo link_info(spec_klass, name, signature, KlassHandle(), NULL, /*check_access*/false);
   LinkResolver::resolve_virtual_call(
           callinfo, receiver, recvrKlass, link_info, true, CHECK);
   methodHandle method = callinfo.selected_method();
@@ -220,7 +220,7 @@
 
 void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
-  LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+  LinkInfo link_info(klass, name, signature, KlassHandle(), NULL, /*check_access*/false);
   LinkResolver::resolve_special_call(callinfo, link_info, CHECK);
   methodHandle method = callinfo.selected_method();
   assert(method.not_null(), "should have thrown exception");
@@ -255,7 +255,7 @@
 
 void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
-  LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+  LinkInfo link_info(klass, name, signature, KlassHandle(), NULL, /*check_access*/false);
   LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK);
   methodHandle method = callinfo.selected_method();
   assert(method.not_null(), "should have thrown exception");
--- old/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java	2016-06-02 12:26:09.606263776 +0200
+++ new/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java	2016-06-02 12:26:09.202263789 +0200
@@ -27,6 +27,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 import sun.hotspot.WhiteBox;
 import jdk.internal.reflect.ConstantPool;
 import jdk.internal.reflect.ConstantPool.Tag;
@@ -184,13 +185,24 @@
         public final String klass;
         public final String name;
         public final String type;
+        public final ResolvedJavaMethod[] methods;
         public final byte[] opcodes;
         public final long accFlags;
 
         public TestedCPEntry(String klass, String name, String type, byte[] opcodes, long accFlags) {
+                this(klass, name, type, null, opcodes, accFlags);
+        }
+
+        public TestedCPEntry(String klass, String name, String type, ResolvedJavaMethod[] methods, byte[] opcodes, long accFlags) {
             this.klass = klass;
             this.name = name;
             this.type = type;
+            if (methods != null) {
+                this.methods = new ResolvedJavaMethod[methods.length];
+                System.arraycopy(methods, 0, this.methods, 0, methods.length);
+            } else {
+                this.methods = null; 
+            }            
             if (opcodes != null) {
                 this.opcodes = new byte[opcodes.length];
                 System.arraycopy(opcodes, 0, this.opcodes, 0, opcodes.length);
--- old/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java	2016-06-02 12:26:09.886263767 +0200
+++ new/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java	2016-06-02 12:26:09.814263769 +0200
@@ -33,6 +33,7 @@
  *          java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java	2016-06-02 12:26:11.250263723 +0200
+++ new/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java	2016-06-02 12:26:11.102263727 +0200
@@ -32,6 +32,7 @@
  *          java.base/jdk.internal.reflect
  *          java.base/jdk.internal.org.objectweb.asm
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java	2016-06-02 12:26:11.262263722 +0200
+++ new/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java	2016-06-02 12:26:11.118263727 +0200
@@ -33,6 +33,7 @@
  *          java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java	2016-06-02 12:26:11.266263722 +0200
+++ new/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java	2016-06-02 12:26:11.098263727 +0200
@@ -33,6 +33,7 @@
  *          java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java	2016-06-02 12:26:11.242263723 +0200
+++ new/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java	2016-06-02 12:26:11.102263727 +0200
@@ -33,6 +33,7 @@
  *          java.base/jdk.internal.reflect
  *          java.base/jdk.internal.org.objectweb.asm
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java	2016-06-02 12:26:11.350263719 +0200
+++ new/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java	2016-06-02 12:26:11.190263725 +0200
@@ -33,6 +33,7 @@
  *          java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
--- old/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java	2016-06-02 12:26:11.374263719 +0200
+++ new/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java	2016-06-02 12:26:11.258263722 +0200
@@ -34,6 +34,7 @@
  *          java.base/jdk.internal.org.objectweb.asm.tree
  *          jdk.vm.ci/jdk.vm.ci.hotspot
  *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.ResolveFieldInPoolTest
@@ -107,6 +108,7 @@
             HotSpotResolvedObjectType fieldToVerify
                     = CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM,
                                                            index,
+                                                           entry.methods == null ? null : entry.methods[j],
                                                            entry.opcodes[j],
                                                            info);
             String msg = String.format("Object returned by resolveFieldInPool method"