--- old/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java 2016-06-02 10:38:19.094472352 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java 2016-06-02 10:38:18.850472360 +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/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantPool.java 2016-06-02 10:38:19.246472347 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantPool.java 2016-06-02 10:38:18.866472360 +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/ciMethod.cpp 2016-06-02 10:38:19.178472350 +0200 +++ new/src/share/vm/ci/ciMethod.cpp 2016-06-02 10:38:18.846472360 +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/share/vm/ci/ciStreams.cpp 2016-06-02 10:38:19.206472349 +0200 +++ new/src/share/vm/ci/ciStreams.cpp 2016-06-02 10:38:18.898472359 +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/share/vm/ci/ciField.cpp 2016-06-02 10:38:19.198472349 +0200 +++ new/src/share/vm/ci/ciField.cpp 2016-06-02 10:38:18.854472360 +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/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java 2016-06-02 10:38:19.226472348 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java 2016-06-02 10:38:18.866472360 +0200 @@ -281,7 +281,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/ci/ciField.hpp 2016-06-02 10:38:19.234472348 +0200 +++ new/src/share/vm/ci/ciField.hpp 2016-06-02 10:38:18.870472360 +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/interpreter/linkResolver.cpp 2016-06-02 10:38:19.238472348 +0200 +++ new/src/share/vm/interpreter/linkResolver.cpp 2016-06-02 10:38:18.866472360 +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/share/vm/ci/ciEnv.cpp 2016-06-02 10:38:19.258472347 +0200 +++ new/src/share/vm/ci/ciEnv.cpp 2016-06-02 10:38:18.890472359 +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/interpreter/interpreterRuntime.cpp 2016-06-02 10:38:19.278472346 +0200 +++ new/src/share/vm/interpreter/interpreterRuntime.cpp 2016-06-02 10:38:19.002472355 +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/c1/c1_Runtime1.cpp 2016-06-02 10:38:19.298472346 +0200 +++ new/src/share/vm/c1/c1_Runtime1.cpp 2016-06-02 10:38:18.922472358 +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/c1/c1_GraphBuilder.cpp 2016-06-02 10:38:19.326472345 +0200 +++ new/src/share/vm/c1/c1_GraphBuilder.cpp 2016-06-02 10:38:18.990472356 +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 10:38:19.578472337 +0200 +++ new/src/share/vm/interpreter/linkResolver.hpp 2016-06-02 10:38:19.506472339 +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/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java 2016-06-02 10:38:21.210472284 +0200 +++ new/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java 2016-06-02 10:38:20.978472292 +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/jvmciEnv.cpp 2016-06-02 10:38:21.274472282 +0200 +++ new/src/share/vm/jvmci/jvmciEnv.cpp 2016-06-02 10:38:20.962472292 +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/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java 2016-06-02 10:38:21.342472280 +0200 +++ new/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java 2016-06-02 10:38:21.134472287 +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/src/share/vm/jvmci/jvmciCompilerToVM.cpp 2016-06-02 10:38:21.322472280 +0200 +++ new/src/share/vm/jvmci/jvmciCompilerToVM.cpp 2016-06-02 10:38:21.034472290 +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/javaCalls.cpp 2016-06-02 10:38:21.382472279 +0200 +++ new/src/share/vm/runtime/javaCalls.cpp 2016-06-02 10:38:21.038472290 +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/LookupKlassInPoolTest.java 2016-06-02 10:38:21.438472277 +0200 +++ new/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java 2016-06-02 10:38:21.102472288 +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/src/share/vm/prims/methodHandles.cpp 2016-06-02 10:38:21.378472279 +0200 +++ new/src/share/vm/prims/methodHandles.cpp 2016-06-02 10:38:20.974472292 +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/src/share/vm/runtime/reflection.cpp 2016-06-02 10:38:21.410472278 +0200 +++ new/src/share/vm/runtime/reflection.cpp 2016-06-02 10:38:21.178472285 +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/ConstantPoolTestCase.java 2016-06-02 10:38:21.446472276 +0200 +++ new/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java 2016-06-02 10:38:21.054472289 +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/src/share/vm/opto/parse3.cpp 2016-06-02 10:38:21.470472276 +0200 +++ new/src/share/vm/opto/parse3.cpp 2016-06-02 10:38:21.222472284 +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/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java 2016-06-02 10:38:21.486472275 +0200 +++ new/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java 2016-06-02 10:38:21.250472283 +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/ConstantPoolTestsHelper.java 2016-06-02 10:38:21.510472274 +0200 +++ new/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java 2016-06-02 10:38:21.178472285 +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/LookupNameAndTypeRefIndexInPoolTest.java 2016-06-02 10:38:21.746472267 +0200 +++ new/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java 2016-06-02 10:38:21.674472269 +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/ResolvePossiblyCachedConstantInPoolTest.java 2016-06-02 10:38:23.110472223 +0200 +++ new/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java 2016-06-02 10:38:22.966472227 +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 10:38:23.106472223 +0200 +++ new/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java 2016-06-02 10:38:22.962472228 +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 10:38:23.138472222 +0200 +++ new/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java 2016-06-02 10:38:22.978472227 +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 10:38:23.166472221 +0200 +++ new/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java 2016-06-02 10:38:22.982472227 +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 10:38:23.230472219 +0200 +++ new/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java 2016-06-02 10:38:23.102472223 +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/ResolveFieldInPoolTest.java 2016-06-02 10:38:23.242472219 +0200 +++ new/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java 2016-06-02 10:38:23.118472223 +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"