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