# HG changeset patch # User Josef Eisl # Date 1414606052 -3600 # Node ID 660875e586f0e853c73c932ee8faeb0741bab3f7 # Parent 839f97696479ca12974150e20b0c0679c4864ac0 Add ResolvedJavaType.resolveMethod() (get the like-time resolved method). diff -r 839f97696479 -r 660875e586f0 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/ResolvedJavaTypeResolveMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/ResolvedJavaTypeResolveMethodTest.java Wed Oct 29 19:07:32 2014 +0100 @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.api.meta.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; + +public class ResolvedJavaTypeResolveMethodTest { + public final MetaAccessProvider metaAccess; + + public ResolvedJavaTypeResolveMethodTest() { + Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); + metaAccess = providers.getMetaAccess(); + } + + protected abstract static class A { + @SuppressWarnings("unused") + private void priv() { + } + + public void v1() { + } + + public void v2() { + } + + public abstract void abs(); + } + + protected static class B extends A implements I { + public void i() { + } + + @Override + public void v2() { + } + + @Override + public void abs() { + + } + } + + protected static class C extends B { + public void d() { + } + } + + protected abstract static class D extends A { + + } + + protected static class E extends D { + @Override + public void abs() { + } + } + + protected interface I { + void i(); + + default void d() { + } + } + + @Test + public void testDefaultMethod() { + ResolvedJavaType i = getType(I.class); + ResolvedJavaType b = getType(B.class); + ResolvedJavaType c = getType(C.class); + ResolvedJavaMethod di = getMethod(i, "d"); + ResolvedJavaMethod dc = getMethod(c, "d"); + + assertEquals(di, i.resolveMethod(di, c, true)); + assertEquals(di, b.resolveMethod(di, c, true)); + assertEquals(dc, c.resolveMethod(di, c, true)); + } + + @Test + public void testPrivateMethod() { + ResolvedJavaType a = getType(A.class); + ResolvedJavaType b = getType(B.class); + ResolvedJavaType c = getType(C.class); + ResolvedJavaMethod priv = getMethod(a, "priv"); + + assertNull(a.resolveMethod(priv, c, true)); + assertNull(b.resolveMethod(priv, c, true)); + } + + @Test + public void testAbstractMethod() { + ResolvedJavaType a = getType(A.class); + ResolvedJavaType b = getType(B.class); + ResolvedJavaType c = getType(C.class); + ResolvedJavaType d = getType(D.class); + ResolvedJavaType e = getType(E.class); + ResolvedJavaMethod absa = getMethod(a, "abs"); + ResolvedJavaMethod absb = getMethod(b, "abs"); + ResolvedJavaMethod abse = getMethod(e, "abs"); + + assertEquals(absa, a.resolveMethod(absa, c, true)); + assertEquals(absa, d.resolveMethod(absa, c, true)); + + assertEquals(absb, b.resolveMethod(absa, c, true)); + assertEquals(absb, b.resolveMethod(absb, c, true)); + assertEquals(absb, c.resolveMethod(absa, c, true)); + assertEquals(absb, c.resolveMethod(absb, c, true)); + assertEquals(abse, e.resolveMethod(absa, c, true)); + assertNull(e.resolveMethod(absb, c, true)); + assertEquals(abse, e.resolveMethod(abse, c, true)); + } + + @Test + public void testVirtualMethod() { + ResolvedJavaType a = getType(A.class); + ResolvedJavaType b = getType(B.class); + ResolvedJavaType c = getType(C.class); + ResolvedJavaMethod v1a = getMethod(a, "v1"); + ResolvedJavaMethod v2a = getMethod(a, "v2"); + ResolvedJavaMethod v2b = getMethod(b, "v2"); + + assertEquals(v1a, a.resolveMethod(v1a, c, true)); + assertEquals(v1a, b.resolveMethod(v1a, c, true)); + assertEquals(v1a, c.resolveMethod(v1a, c, true)); + assertEquals(v2a, a.resolveMethod(v2a, c, true)); + assertEquals(v2b, b.resolveMethod(v2a, c, true)); + assertEquals(v2b, b.resolveMethod(v2b, c, true)); + assertEquals(v2b, c.resolveMethod(v2a, c, true)); + assertEquals(v2b, c.resolveMethod(v2b, c, true)); + + } + + static ResolvedJavaMethod getMethod(ResolvedJavaType type, String methodName) { + for (ResolvedJavaMethod method : type.getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + return method; + } + } + throw new IllegalArgumentException(); + } + + protected ResolvedJavaType getType(Class clazz) { + ResolvedJavaType type = metaAccess.lookupJavaType(clazz); + type.initialize(); + return type; + } +} diff -r 839f97696479 -r 660875e586f0 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Wed Oct 29 18:54:32 2014 +0100 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Wed Oct 29 19:07:32 2014 +0100 @@ -534,6 +534,39 @@ } @Test + public void resolveMethodTest() { + ResolvedJavaType context = metaAccess.lookupJavaType(TestResolvedJavaType.class); + for (Class c : classes) { + if (c.isInterface() || c.isPrimitive()) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + for (Method m : c.getDeclaredMethods()) { + if (JAVA_VERSION <= 1.7D || (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers()))) { + ResolvedJavaMethod resolved = metaAccess.lookupJavaMethod(m); + ResolvedJavaMethod impl = type.resolveMethod(resolved, context, true); + ResolvedJavaMethod expected = resolved.isDefault() || resolved.isAbstract() ? resolved : null; + assertEquals(m.toString(), expected, impl); + } else { + // As of JDK 8, interfaces can have static and private methods + } + } + } else { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + VTable vtable = getVTable(c); + for (Method impl : vtable.methods.values()) { + Set decls = findDeclarations(impl, c); + for (Method decl : decls) { + ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl); + if (m.isPublic()) { + ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl); + checkResolveMethod(type, context, m, i); + } + } + } + } + } + } + + @Test public void resolveConcreteMethodTest() { ResolvedJavaType context = metaAccess.lookupJavaType(TestResolvedJavaType.class); for (Class c : classes) { diff -r 839f97696479 -r 660875e586f0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Wed Oct 29 18:54:32 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Wed Oct 29 19:07:32 2014 +0100 @@ -230,6 +230,21 @@ /** * Resolves the method implementation for virtual dispatches on objects of this dynamic type. + * This resolution process only searches "up" the class hierarchy of this type. + * + * @param method the method to select the implementation of + * @param callerType the caller or context type used to perform access checks + * @param includeAbstract whether abstract methods should be returned. If it is {@code false} + * this method behaves like {@link #resolveConcreteMethod}. This is just a temporary + * parameter to highlight the changed semantics of this method. TODO (je) remove this + * flag. + * @return the link-time resolved method (might be abstract) or {@code null} if it can not be + * linked + */ + ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType, boolean includeAbstract); + + /** + * Resolves the method implementation for virtual dispatches on objects of this dynamic type. * This resolution process only searches "up" the class hierarchy of this type. A broader search * that also walks "down" the hierarchy is implemented by * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}. diff -r 839f97696479 -r 660875e586f0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Oct 29 18:54:32 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Oct 29 19:07:32 2014 +0100 @@ -380,22 +380,18 @@ @Override public ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { - ResolvedJavaMethod resolvedMethod = resolveMethodInternal(method, callerType); + ResolvedJavaMethod resolvedMethod = resolveMethod(method, callerType, true); if (resolvedMethod == null || resolvedMethod.isAbstract()) { return null; } return resolvedMethod; } - /** - * Resolve the method against the current type and return the method found, including any - * abstract methods. - * - * @param method - * @param callerType - * @return the method found - */ - private ResolvedJavaMethod resolveMethodInternal(ResolvedJavaMethod method, ResolvedJavaType callerType) { + @Override + public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType, boolean includeAbstract) { + if (!includeAbstract) { + return resolveConcreteMethod(method, callerType); + } assert !callerType.isArray(); if (!method.isAbstract() && method.getDeclaringClass().equals(this) && method.isPublic()) { return method; @@ -522,7 +518,7 @@ * The holder may be a subtype of the decaredHolder so make sure to resolve the method to * the correct method for the subtype. */ - HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) resolveMethodInternal(hmethod, this); + HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) resolveMethod(hmethod, this, true); if (resolvedMethod == null) { // The type isn't known to implement the method. return null; diff -r 839f97696479 -r 660875e586f0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Wed Oct 29 18:54:32 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Wed Oct 29 19:07:32 2014 +0100 @@ -184,6 +184,11 @@ } @Override + public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType, boolean includeAbstract) { + return null; + } + + @Override public String toString() { return "HotSpotResolvedPrimitiveType<" + kind + ">"; }