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.arch != "aarch64" 28 * @library / /testlibrary /../../test/lib 29 * @compile ../common/CompilerToVMHelper.java 30 * @build compiler.jvmci.compilerToVM.ResolveMethodTest 31 * @run main ClassFileInstaller 32 * jdk.vm.ci.hotspot.CompilerToVMHelper 33 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions 34 * -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveMethodTest 35 */ 36 37 package compiler.jvmci.compilerToVM; 38 39 import compiler.jvmci.common.testcases.AbstractClass; 40 import compiler.jvmci.common.testcases.AbstractClassExtender; 41 import compiler.jvmci.common.testcases.MultipleImplementer1; 42 import compiler.jvmci.common.testcases.MultipleImplementer2; 43 import compiler.jvmci.common.testcases.MultipleImplementersInterface; 44 import compiler.jvmci.common.testcases.SingleImplementer; 45 import compiler.jvmci.common.testcases.SingleImplementerInterface; 46 import compiler.jvmci.common.testcases.SingleSubclass; 47 import compiler.jvmci.common.testcases.SingleSubclassedClass; 48 import compiler.jvmci.common.CTVMUtilities; 49 import java.util.HashSet; 50 import java.util.Set; 51 import jdk.vm.ci.hotspot.CompilerToVMHelper; 52 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl; 53 import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl; 54 import jdk.test.lib.Asserts; 55 import jdk.test.lib.Utils; 56 import sun.misc.Unsafe; 57 58 public class ResolveMethodTest { 59 private static final Unsafe UNSAFE = Utils.getUnsafe(); 60 61 public static void main(String args[]) { 62 ResolveMethodTest test = new ResolveMethodTest(); 63 // positive cases 64 try { 65 for (TestCase tcase: createTestCases()) { 66 test.runTest(tcase); 67 } 68 } catch (NoSuchMethodException e) { 69 throw new Error("TEST BUG: can't find requested method", e); 70 } 71 } 72 73 private static Set<TestCase> createTestCases() { 74 Set<TestCase> result = new HashSet<>(); 75 // a usual class public method 76 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 77 "usualMethod", ResolveMethodTest.class, true)); 78 // an array method 79 result.add(new TestCase(int[].class, Object.class, "toString", 80 ResolveMethodTest.class, true)); 81 // a method from base class, which was overriden in tested one 82 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 83 "overridenMethod", ResolveMethodTest.class, true)); 84 // a method from base class, which was not overriden in tested one 85 result.add(new TestCase(SingleSubclass.class, 86 SingleSubclassedClass.class, "inheritedMethod", 87 ResolveMethodTest.class, true)); 88 /* a method from base class, which was overriden in tested one with 89 base class as holder */ 90 result.add(new TestCase(SingleSubclass.class, 91 SingleSubclassedClass.class, "overridenMethod", 92 ResolveMethodTest.class, true)); 93 // an interface method 94 result.add(new TestCase(SingleImplementer.class, 95 SingleImplementerInterface.class, "interfaceMethod", 96 ResolveMethodTest.class, true)); 97 // an interface default method overriden in implementer 98 result.add(new TestCase(MultipleImplementer1.class, 99 MultipleImplementersInterface.class, "defaultMethod", 100 ResolveMethodTest.class, true)); 101 // an interface default method not overriden in implementer 102 result.add(new TestCase(MultipleImplementer2.class, 103 MultipleImplementersInterface.class, "defaultMethod", 104 ResolveMethodTest.class, true)); 105 // an abstract method 106 result.add(new TestCase(AbstractClassExtender.class, AbstractClass.class, 107 "abstractMethod", ResolveMethodTest.class, true)); 108 // private method with right accessor 109 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 110 "privateMethod", SingleSubclass.class, true)); 111 // package-private method with right accessor 112 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 113 "defaultAccessMethod", SingleSubclass.class, true)); 114 115 // negative cases 116 117 // private method of another class 118 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 119 "privateMethod", ResolveMethodTest.class, false)); 120 // package-private method from another package 121 result.add(new TestCase(SingleSubclass.class, SingleSubclass.class, 122 "defaultAccessMethod", ResolveMethodTest.class, false)); 123 return result; 124 } 125 126 private void runTest(TestCase tcase) throws NoSuchMethodException { 127 System.out.println(tcase); 128 HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities 129 .getResolvedMethod(tcase.holder, 130 tcase.holder.getDeclaredMethod(tcase.methodName)); 131 HotSpotResolvedObjectTypeImpl holderMetaspace = CompilerToVMHelper 132 .lookupType(Utils.toJVMTypeSignature(tcase.holder), 133 getClass(), /* resolve = */ true); 134 HotSpotResolvedObjectTypeImpl callerMetaspace = CompilerToVMHelper 135 .lookupType(Utils.toJVMTypeSignature(tcase.caller), 136 getClass(), /* resolve = */ true); 137 HotSpotResolvedJavaMethodImpl resolvedMetaspaceMethod 138 = CompilerToVMHelper.resolveMethod(holderMetaspace, 139 metaspaceMethod, callerMetaspace); 140 if (tcase.isPositive) { 141 Asserts.assertNotNull(resolvedMetaspaceMethod, 142 "Unexpected null resolved method value for " 143 + tcase.methodName); 144 Asserts.assertEQ(metaspaceMethod.getName(), tcase.methodName, 145 "Reflection and c2vm method names doesn't match"); 146 } else { 147 Asserts.assertNull(resolvedMetaspaceMethod, 148 "Method unexpectedly resolved"); 149 } 150 } 151 152 private static class TestCase { 153 public final Class<?> receiver; 154 public final Class<?> holder; 155 public final Class<?> caller; 156 public final String methodName; 157 public final boolean isPositive; 158 159 public TestCase(Class<?> recv, Class<?> holder, String methodName, 160 Class<?> caller, boolean isPositive) { 161 this.receiver = recv; 162 this.holder = holder; 163 this.caller = caller; 164 this.methodName = methodName; 165 this.isPositive = isPositive; 166 } 167 168 @Override 169 public String toString() { 170 return String.format("CASE: receiver=%s, holder=%s, method=%s," 171 + "caller=%s, isPositive=%s%n", receiver.getName(), 172 holder.getName(), methodName, caller.getName(), isPositive); 173 } 174 } 175 }