# HG changeset patch # User jcm # Date 1486403808 28800 # Node ID f0e4bcc4d9f3644715baaf52f94e909cb38565c3 # Parent def72508767d0dbbdf6bbf549118c1c64e790bd4 8170455: C2: Access to [].clone from interfaces fails Summary: passed holder klass to LR for proper resolution. Reviewed-by: vlivanov diff -r def72508767d -r f0e4bcc4d9f3 hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Mon Feb 06 08:32:08 2017 +0100 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Mon Feb 06 09:56:48 2017 -0800 @@ -704,16 +704,17 @@ // // Perform an appropriate method lookup based on accessor, holder, // name, signature, and bytecode. -Method* ciEnv::lookup_method(InstanceKlass* accessor, - InstanceKlass* holder, - Symbol* name, - Symbol* sig, - Bytecodes::Code bc, - constantTag tag) { - EXCEPTION_CONTEXT; - KlassHandle h_accessor(THREAD, accessor); - KlassHandle h_holder(THREAD, holder); - LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL)); +Method* ciEnv::lookup_method(ciInstanceKlass* accessor, + ciKlass* holder, + Symbol* name, + Symbol* sig, + Bytecodes::Code bc, + constantTag tag) { + // Accessibility checks are performed in ciEnv::get_method_by_index_impl. + assert(check_klass_accessibility(accessor, holder->get_Klass()), "holder not accessible"); + + KlassHandle h_accessor(accessor->get_instanceKlass()); + KlassHandle h_holder(holder->get_Klass()); methodHandle dest_method; LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag); switch (bc) { @@ -772,7 +773,6 @@ const int holder_index = cpool->klass_ref_index_at(index); bool holder_is_accessible; ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); - ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder); // Get the method's name and signature. Symbol* name_sym = cpool->name_ref_at(index); @@ -800,10 +800,9 @@ } if (holder_is_accessible) { // Our declared holder is loaded. - InstanceKlass* lookup = declared_holder->get_instanceKlass(); constantTag tag = cpool->tag_ref_at(index); assert(accessor->get_instanceKlass() == cpool->pool_holder(), "not the pool holder?"); - Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc, tag); + Method* m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag); if (m != NULL && (bc == Bytecodes::_invokestatic ? m->method_holder()->is_not_initialized() @@ -826,7 +825,7 @@ // lookup. ciSymbol* name = get_symbol(name_sym); ciSymbol* signature = get_symbol(sig_sym); - return get_unloaded_method(declared_holder, name, signature, accessor); + return get_unloaded_method(holder, name, signature, accessor); } } diff -r def72508767d -r f0e4bcc4d9f3 hotspot/src/share/vm/ci/ciEnv.hpp --- a/hotspot/src/share/vm/ci/ciEnv.hpp Mon Feb 06 08:32:08 2017 +0100 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Mon Feb 06 09:56:48 2017 -0800 @@ -153,12 +153,12 @@ // Helper methods bool check_klass_accessibility(ciKlass* accessing_klass, Klass* resolved_klass); - Method* lookup_method(InstanceKlass* accessor, - InstanceKlass* holder, - Symbol* name, - Symbol* sig, - Bytecodes::Code bc, - constantTag tag); + Method* lookup_method(ciInstanceKlass* accessor, + ciKlass* holder, + Symbol* name, + Symbol* sig, + Bytecodes::Code bc, + constantTag tag); // Get a ciObject from the object factory. Ensures uniqueness // of ciObjects. @@ -227,11 +227,12 @@ // Get a ciMethod representing either an unfound method or // a method with an unloaded holder. Ensures uniqueness of // the result. - ciMethod* get_unloaded_method(ciInstanceKlass* holder, + ciMethod* get_unloaded_method(ciKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor) { - return _factory->get_unloaded_method(holder, name, signature, accessor); + ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder); + return _factory->get_unloaded_method(declared_holder, name, signature, accessor); } // Get a ciKlass representing an unloaded klass. diff -r def72508767d -r f0e4bcc4d9f3 hotspot/src/share/vm/jvmci/jvmciEnv.cpp --- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Mon Feb 06 08:32:08 2017 +0100 +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Mon Feb 06 09:56:48 2017 -0800 @@ -283,13 +283,14 @@ // Perform an appropriate method lookup based on accessor, holder, // name, signature, and bytecode. methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor, - instanceKlassHandle h_holder, + KlassHandle h_holder, Symbol* name, Symbol* sig, Bytecodes::Code bc, constantTag tag) { - JVMCI_EXCEPTION_CONTEXT; - LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL)); + // Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl(). + assert(check_klass_accessibility(h_accessor, h_holder), "holder not accessible"); + methodHandle dest_method; LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag); switch (bc) { @@ -363,9 +364,8 @@ } if (holder_is_accessible) { // Our declared holder is loaded. - instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder); constantTag tag = cpool->tag_ref_at(index); - methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc, tag); + methodHandle m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag); if (!m.is_null() && (bc == Bytecodes::_invokestatic ? InstanceKlass::cast(m->method_holder())->is_not_initialized() diff -r def72508767d -r f0e4bcc4d9f3 hotspot/src/share/vm/jvmci/jvmciEnv.hpp --- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp Mon Feb 06 08:32:08 2017 +0100 +++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp Mon Feb 06 09:56:48 2017 -0800 @@ -127,7 +127,7 @@ // Helper methods static bool check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass); static methodHandle lookup_method(instanceKlassHandle accessor, - instanceKlassHandle holder, + KlassHandle holder, Symbol* name, Symbol* sig, Bytecodes::Code bc, diff -r def72508767d -r f0e4bcc4d9f3 hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java Mon Feb 06 09:56:48 2017 -0800 @@ -0,0 +1,117 @@ +/* + * 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 8170455 + * @summary C2: Access to [].clone from interfaces fails. + * @library /test/lib / + * + * @requires vm.flavor == "server" & !vm.emulatedClient + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xcomp -Xbatch -Xbootclasspath/a:. -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=compileonly,*TestDefaultMethodArrayCloneDeoptC2Interface::test + * compiler.arraycopy.TestDefaultMethodArrayCloneDeoptC2 + */ + +package compiler.arraycopy; + +import sun.hotspot.WhiteBox; +import java.lang.reflect.Method; +import compiler.whitebox.CompilerWhiteBoxTest; + + + +interface TestDefaultMethodArrayCloneDeoptC2Interface { + default int[] test(int[] arr) { + return arr.clone(); + } + + default TDMACDC2InterfaceTypeTest[] test(TDMACDC2InterfaceTypeTest[] arr) { + return arr.clone(); + } + + default TDMACDC2ClassTypeTest[] test(TDMACDC2ClassTypeTest[] arr) { + return arr.clone(); + } +} + +public class TestDefaultMethodArrayCloneDeoptC2 implements TestDefaultMethodArrayCloneDeoptC2Interface { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + public static TestDefaultMethodArrayCloneDeoptC2 a = new TestDefaultMethodArrayCloneDeoptC2(); + + public static void main(String[] args) throws Exception { + testPrimitiveArr(); + testIntfArr(); + testClassArr(); + } + + public static void testPrimitiveArr() throws Exception { + Method m = TestDefaultMethodArrayCloneDeoptC2Interface.class.getMethod("test", int[].class); + a.test(new int[1]); // Compiled + a.test(new int[1]); + if (!WB.isMethodCompiled(m)) { + WB.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + } + a.test(new int[1]); + if (!WB.isMethodCompiled(m)) { + throw new Exception("Method should be compiled"); + } + } + + public static void testIntfArr() throws Exception { + Method m = TestDefaultMethodArrayCloneDeoptC2Interface.class.getMethod("test", TDMACDC2InterfaceTypeTest[].class); + a.test(new TDMACDC2InterfaceTypeTest[1]); // Compiled, Decompile unloaded + a.test(new TDMACDC2InterfaceTypeTest[1]); // Compiled + a.test(new TDMACDC2InterfaceTypeTest[1]); + if (!WB.isMethodCompiled(m)) { + WB.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + } + a.test(new TDMACDC2InterfaceTypeTest[1]); + if (!WB.isMethodCompiled(m)) { + throw new Exception("Method should be compiled"); + } + } + + public static void testClassArr() throws Exception { + Method m = TestDefaultMethodArrayCloneDeoptC2Interface.class.getMethod("test", TDMACDC2ClassTypeTest[].class); + a.test(new TDMACDC2ClassTypeTest[1]); // Compiled, Decompile unloaded + a.test(new TDMACDC2ClassTypeTest[1]); // Compiled + a.test(new TDMACDC2ClassTypeTest[1]); + if (!WB.isMethodCompiled(m)) { + WB.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + } + a.test(new TDMACDC2ClassTypeTest[1]); + if (!WB.isMethodCompiled(m)) { + throw new Exception("Method should be compiled"); + } + } +} + +interface TDMACDC2InterfaceTypeTest { +} + +class TDMACDC2ClassTypeTest { +} +