1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8136421 27 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") 28 * @library / /testlibrary /test/lib 29 * @library ../common/patches 30 * @modules java.base/jdk.internal.org.objectweb.asm 31 * java.base/jdk.internal.org.objectweb.asm.tree 32 * jdk.vm.ci/jdk.vm.ci.hotspot 33 * jdk.vm.ci/jdk.vm.ci.code 34 * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper 35 * @build compiler.jvmci.compilerToVM.ResolveMethodTest 36 * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 37 * compiler.jvmci.compilerToVM.ResolveMethodTest 38 */ 39 40 package compiler.jvmci.compilerToVM; 41 42 import compiler.jvmci.common.testcases.AbstractClass; 43 import compiler.jvmci.common.testcases.AbstractClassExtender; 44 import compiler.jvmci.common.testcases.MultipleImplementer1; 45 import compiler.jvmci.common.testcases.MultipleImplementer2; 46 import compiler.jvmci.common.testcases.MultipleImplementersInterface; 47 import compiler.jvmci.common.testcases.SingleImplementer; 48 import compiler.jvmci.common.testcases.SingleImplementerInterface; 49 import compiler.jvmci.common.testcases.SingleSubclass; 50 import compiler.jvmci.common.testcases.SingleSubclassedClass; 51 import compiler.jvmci.common.CTVMUtilities; 52 import java.util.HashSet; 53 import java.util.Set; 54 import jdk.vm.ci.hotspot.CompilerToVMHelper; 55 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 56 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; 57 import jdk.test.lib.Asserts; 58 import jdk.test.lib.Utils; 59 import sun.misc.Unsafe; 60 61 public class ResolveMethodTest { 62 private static final Unsafe UNSAFE = Utils.getUnsafe(); 63 64 public static void main(String args[]) { 65 ResolveMethodTest test = new ResolveMethodTest(); 66 // positive cases 67 try { 68 for (TestCase tcase: createTestCases()) { 69 test.runTest(tcase); 70 } 71 } catch (NoSuchMethodException e) { 72 throw new Error("TEST BUG: can't find requested method", e); 73 } 74 } 75 76 private static Set<TestCase> createTestCases() { 77 Set<TestCase> result = new HashSet<>(); 78 // a usual class public method 79 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 80 "usualMethod", ResolveMethodTest.class, true)); 81 // an array method 82 result.add(new TestCase(int[].class, Object.class, "toString", 83 ResolveMethodTest.class, true)); 84 // a method from base class, which was overriden in tested one 85 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 86 "overridenMethod", ResolveMethodTest.class, true)); 87 // a method from base class, which was not overriden in tested one 88 result.add(new TestCase(SingleSubclass.class, 89 SingleSubclassedClass.class, "inheritedMethod", 90 ResolveMethodTest.class, true)); 91 /* a method from base class, which was overriden in tested one with 92 base class as holder */ 93 result.add(new TestCase(SingleSubclass.class, 94 SingleSubclassedClass.class, "overridenMethod", 95 ResolveMethodTest.class, true)); 96 // an interface method 97 result.add(new TestCase(SingleImplementer.class, 98 SingleImplementerInterface.class, "interfaceMethod", 99 ResolveMethodTest.class, true)); 100 // an interface default method overriden in implementer 101 result.add(new TestCase(MultipleImplementer1.class, 102 MultipleImplementersInterface.class, "defaultMethod", 103 ResolveMethodTest.class, true)); 104 // an interface default method not overriden in implementer 105 result.add(new TestCase(MultipleImplementer2.class, 106 MultipleImplementersInterface.class, "defaultMethod", 107 ResolveMethodTest.class, true)); 108 // an abstract method 109 result.add(new TestCase(AbstractClassExtender.class, AbstractClass.class, 110 "abstractMethod", ResolveMethodTest.class, true)); 111 // private method with right accessor 112 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 113 "privateMethod", SingleSubclass.class, true)); 114 // package-private method with right accessor 115 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 116 "defaultAccessMethod", SingleSubclass.class, true)); 117 118 // negative cases 119 120 // private method of another class 121 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 122 "privateMethod", ResolveMethodTest.class, false)); 123 // package-private method from another package 124 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 125 "defaultAccessMethod", ResolveMethodTest.class, false)); 126 return result; 127 } 128 129 private void runTest(TestCase tcase) throws NoSuchMethodException { 130 System.out.println(tcase); 131 HotSpotResolvedJavaMethod metaspaceMethod = CTVMUtilities 132 .getResolvedMethod(tcase.holder, 133 tcase.holder.getDeclaredMethod(tcase.methodName)); 134 HotSpotResolvedObjectType holderMetaspace = CompilerToVMHelper 135 .lookupType(Utils.toJVMTypeSignature(tcase.holder), 136 getClass(), /* resolve = */ true); 137 HotSpotResolvedObjectType callerMetaspace = CompilerToVMHelper 138 .lookupType(Utils.toJVMTypeSignature(tcase.caller), 139 getClass(), /* resolve = */ true); 140 HotSpotResolvedObjectType receiverMetaspace = CompilerToVMHelper 141 .lookupType(Utils.toJVMTypeSignature(tcase.receiver), 142 getClass(), /* resolve = */ true); 143 144 // Can only resolve methods on a linked class so force initialization 145 receiverMetaspace.initialize(); 146 HotSpotResolvedJavaMethod resolvedMetaspaceMethod 147 = CompilerToVMHelper.resolveMethod(receiverMetaspace, 148 metaspaceMethod, callerMetaspace); 149 if (tcase.isPositive) { 150 Asserts.assertNotNull(resolvedMetaspaceMethod, 151 "Unexpected null resolved method value for " 152 + tcase.methodName); 153 Asserts.assertEQ(metaspaceMethod.getName(), tcase.methodName, 154 "Reflection and c2vm method names doesn't match"); 155 } else { 156 Asserts.assertNull(resolvedMetaspaceMethod, 157 "Method unexpectedly resolved"); 158 } 159 } 160 161 private static class TestCase { 162 public final Class<?> receiver; 163 public final Class<?> holder; 164 public final Class<?> caller; 165 public final String methodName; 166 public final boolean isPositive; 167 168 public TestCase(Class<?> recv, Class<?> holder, String methodName, 169 Class<?> caller, boolean isPositive) { 170 this.receiver = recv; 171 this.holder = holder; 172 this.caller = caller; 173 this.methodName = methodName; 174 this.isPositive = isPositive; 175 } 176 177 @Override 178 public String toString() { 179 return String.format("CASE: receiver=%s, holder=%s, method=%s," 180 + "caller=%s, isPositive=%s%n", receiver.getName(), 181 holder.getName(), methodName, caller.getName(), isPositive); 182 } 183 } 184 }