# HG changeset patch # User Gilles Duboscq # Date 1397821815 -7200 # Node ID c583759bbcfd2b50e466d4ee2c3275985bc5b817 # Parent 1e3f19292a3207cdece3b7a937dfad5c177f2cc7 ResolvedJavaType.resolveMethod now takes a callerType that is used to check access rules. Make it work for default methods. diff -r 1e3f19292a32 -r c583759bbcfd 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 Fri Apr 18 13:50:15 2014 +0200 @@ -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 static abstract 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 static abstract 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)); + assertEquals(di, b.resolveMethod(di, c)); + assertEquals(dc, c.resolveMethod(di, c)); + } + + @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)); + assertNull(b.resolveMethod(priv, c)); + } + + @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"); + + assertNull(a.resolveMethod(absa, c)); + assertNull(d.resolveMethod(absa, c)); + + assertEquals(absb, b.resolveMethod(absa, c)); + assertEquals(absb, b.resolveMethod(absb, c)); + assertEquals(absb, c.resolveMethod(absa, c)); + assertEquals(absb, c.resolveMethod(absb, c)); + assertEquals(abse, e.resolveMethod(absa, c)); + assertNull(e.resolveMethod(absb, c)); + assertEquals(abse, e.resolveMethod(abse, c)); + } + + @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)); + assertEquals(v1a, b.resolveMethod(v1a, c)); + assertEquals(v1a, c.resolveMethod(v1a, c)); + assertEquals(v2a, a.resolveMethod(v2a, c)); + assertEquals(v2b, b.resolveMethod(v2a, c)); + assertEquals(v2b, b.resolveMethod(v2b, c)); + assertEquals(v2b, c.resolveMethod(v2a, c)); + assertEquals(v2b, c.resolveMethod(v2b, c)); + + } + + private 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 1e3f19292a32 -r c583759bbcfd 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 Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Fri Apr 18 13:50:15 2014 +0200 @@ -431,20 +431,21 @@ return declarations; } - private static void checkResolveMethod(ResolvedJavaType type, ResolvedJavaMethod decl, ResolvedJavaMethod expected) { - ResolvedJavaMethod impl = type.resolveMethod(decl); + private static void checkResolveMethod(ResolvedJavaType type, ResolvedJavaType context, ResolvedJavaMethod decl, ResolvedJavaMethod expected) { + ResolvedJavaMethod impl = type.resolveMethod(decl, context); assertEquals(expected, impl); } @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); + ResolvedJavaMethod impl = type.resolveMethod(resolved, context); ResolvedJavaMethod expected = resolved.isDefault() ? resolved : null; assertEquals(m.toString(), expected, impl); } else { @@ -458,12 +459,14 @@ Set decls = findDeclarations(impl, c); for (Method decl : decls) { ResolvedJavaMethod m = metaAccess.lookupJavaMethod(decl); - ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl); - checkResolveMethod(type, m, i); + if (m.isPublic()) { + ResolvedJavaMethod i = metaAccess.lookupJavaMethod(impl); + checkResolveMethod(type, context, m, i); + } } } for (Method m : c.getDeclaredMethods()) { - ResolvedJavaMethod impl = type.resolveMethod(metaAccess.lookupJavaMethod(m)); + ResolvedJavaMethod impl = type.resolveMethod(metaAccess.lookupJavaMethod(m), context); ResolvedJavaMethod expected = isAbstract(m.getModifiers()) ? null : impl; assertEquals(type + " " + m.toString(), expected, impl); } diff -r 1e3f19292a32 -r c583759bbcfd 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 Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Apr 18 13:50:15 2014 +0200 @@ -214,7 +214,7 @@ * @return the concrete method that would be selected at runtime, or {@code null} if there is no * concrete implementation of {@code method} in this type or any of its superclasses */ - ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method); + ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType); /** * Given a {@link ResolvedJavaMethod} A, returns a concrete {@link ResolvedJavaMethod} B that is diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 18 13:50:15 2014 +0200 @@ -248,7 +248,7 @@ void initializeConfiguration(HotSpotVMConfig config); - long resolveMethod(long metaspaceKlass, String name, String signature); + long resolveMethod(long metaspaceKlassExactReceiver, long metaspaceMethod, long metaspaceKlassCaller); long getClassInitializer(long metaspaceKlass); diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 18 13:50:15 2014 +0200 @@ -99,7 +99,7 @@ public native void initializeConfiguration(HotSpotVMConfig config); @Override - public native long resolveMethod(long metaspaceKlass, String name, String signature); + public native long resolveMethod(long metaspaceKlassExactReceiver, long metaspaceMethod, long metaspaceKlassCaller); @Override public native boolean hasFinalizableSubclass(long metaspaceKlass); diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 18 13:50:15 2014 +0200 @@ -604,7 +604,9 @@ @Override public boolean isInVirtualMethodTable() { - return getVtableIndex() >= 0; + // TODO (gd) this should probably take a ResolvedJavaType as argument so that we can take + // advantage of miranda & default methods. + return !holder.isInterface() && getVtableIndex() >= 0; } /** @@ -613,7 +615,7 @@ * @return virtual table index */ private int getVtableIndex() { - assert !holder.isInterface(); + assert !holder.isInterface() : this; HotSpotVMConfig config = runtime().getConfig(); int result = unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset); assert result >= config.nonvirtualVtableIndex : "must be linked"; diff -r 1e3f19292a32 -r c583759bbcfd 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 Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Apr 18 13:50:15 2014 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + import java.lang.annotation.*; import java.lang.reflect.*; import java.net.*; @@ -354,13 +355,17 @@ } @Override - public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { - assert method instanceof HotSpotMethod; - if (!method.isAbstract() && method.getDeclaringClass().equals(this)) { + public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { + assert !callerType.isArray(); + if (!method.isAbstract() && method.getDeclaringClass().equals(this) && method.isPublic()) { return method; } - - final long resolvedMetaspaceMethod = runtime().getCompilerToVM().resolveMethod(metaspaceKlass(), method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); + if (!method.getDeclaringClass().isAssignableFrom(this)) { + return null; + } + HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method; + HotSpotResolvedObjectType hotSpotCallerType = (HotSpotResolvedObjectType) callerType; + final long resolvedMetaspaceMethod = runtime().getCompilerToVM().resolveMethod(metaspaceKlass(), hotSpotMethod.getMetaspaceMethod(), hotSpotCallerType.metaspaceKlass()); if (resolvedMetaspaceMethod == 0) { return null; } diff -r 1e3f19292a32 -r c583759bbcfd 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 Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Fri Apr 18 13:50:15 2014 +0200 @@ -163,7 +163,7 @@ } @Override - public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { + public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { return null; } diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Fri Apr 18 13:50:15 2014 +0200 @@ -144,7 +144,7 @@ ResolvedJavaType type = StampTool.typeOrNull(receiver); if (type != null) { // either the holder class is exact, or the receiver object has an exact type - ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod); + ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod, invoke().getContextType()); if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver))) { invokeKind = InvokeKind.Special; targetMethod = resolvedMethod; diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Fri Apr 18 13:50:15 2014 +0200 @@ -815,7 +815,7 @@ if (receiver != null && (callTarget.invokeKind() == InvokeKind.Interface || callTarget.invokeKind() == InvokeKind.Virtual)) { ResolvedJavaType type = state.getNodeType(receiver); if (!Objects.equals(type, StampTool.typeOrNull(receiver))) { - ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod()); + ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod(), invoke.getContextType()); if (method != null) { if (method.canBeStaticallyBound() || type.isFinal()) { callTarget.setInvokeKind(InvokeKind.Special); diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Fri Apr 18 13:50:15 2014 +0200 @@ -594,7 +594,7 @@ if (type == null) { return; } - ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod()); + ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod(), invoke.getContextType()); if (method == null) { return; } diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Fri Apr 18 13:50:15 2014 +0200 @@ -276,6 +276,7 @@ // Don't inline if receiver is known to be null return null; } + ResolvedJavaType contextType = invoke.getContextType(); if (receiverStamp.type() != null) { // the invoke target might be more specific than the holder (happens after inlining: // parameters lose their declared type...) @@ -284,7 +285,7 @@ holder = receiverType; if (receiverStamp.isExactType()) { assert targetMethod.getDeclaringClass().isAssignableFrom(holder) : holder + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod; - ResolvedJavaMethod resolvedMethod = holder.resolveMethod(targetMethod); + ResolvedJavaMethod resolvedMethod = holder.resolveMethod(targetMethod, contextType); if (resolvedMethod != null) { return getExactInlineInfo(data, invoke, replacements, optimisticOpts, resolvedMethod); } @@ -294,7 +295,7 @@ if (holder.isArray()) { // arrays can be treated as Objects - ResolvedJavaMethod resolvedMethod = holder.resolveMethod(targetMethod); + ResolvedJavaMethod resolvedMethod = holder.resolveMethod(targetMethod, contextType); if (resolvedMethod != null) { return getExactInlineInfo(data, invoke, replacements, optimisticOpts, resolvedMethod); } @@ -303,7 +304,7 @@ if (assumptions.useOptimisticAssumptions()) { ResolvedJavaType uniqueSubtype = holder.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { - ResolvedJavaMethod resolvedMethod = uniqueSubtype.resolveMethod(targetMethod); + ResolvedJavaMethod resolvedMethod = uniqueSubtype.resolveMethod(targetMethod, contextType); if (resolvedMethod != null) { return getAssumptionInlineInfo(data, invoke, replacements, optimisticOpts, resolvedMethod, new Assumptions.ConcreteSubtype(holder, uniqueSubtype)); } @@ -351,7 +352,7 @@ if (ptypes == null || ptypes.length <= 0) { return logNotInlinedMethodAndReturnNull(invoke, data.inliningDepth(), targetMethod, "no types in profile"); } - + ResolvedJavaType contextType = invoke.getContextType(); double notRecordedTypeProbability = typeProfile.getNotRecordedProbability(); if (ptypes.length == 1 && notRecordedTypeProbability == 0) { if (!optimisticOpts.inlineMonomorphicCalls()) { @@ -360,7 +361,7 @@ ResolvedJavaType type = ptypes[0].getType(); assert type.isArray() || !type.isAbstract(); - ResolvedJavaMethod concrete = type.resolveMethod(targetMethod); + ResolvedJavaMethod concrete = type.resolveMethod(targetMethod, contextType); if (!checkTargetConditions(data, replacements, invoke, concrete, optimisticOpts)) { return null; } @@ -382,7 +383,7 @@ ArrayList concreteMethods = new ArrayList<>(); ArrayList concreteMethodsProbabilities = new ArrayList<>(); for (int i = 0; i < ptypes.length; i++) { - ResolvedJavaMethod concrete = ptypes[i].getType().resolveMethod(targetMethod); + ResolvedJavaMethod concrete = ptypes[i].getType().resolveMethod(targetMethod, contextType); if (concrete == null) { return logNotInlinedMethodAndReturnNull(invoke, data.inliningDepth(), targetMethod, "could not resolve method"); } @@ -426,7 +427,7 @@ ArrayList usedTypes = new ArrayList<>(); ArrayList typesToConcretes = new ArrayList<>(); for (ProfiledType type : ptypes) { - ResolvedJavaMethod concrete = type.getType().resolveMethod(targetMethod); + ResolvedJavaMethod concrete = type.getType().resolveMethod(targetMethod, contextType); int index = concreteMethods.indexOf(concrete); if (index == -1) { notRecordedTypeProbability += type.getProbability(); diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Fri Apr 18 13:50:15 2014 +0200 @@ -504,13 +504,14 @@ if (methodCallTarget.invokeKind() == InvokeKind.Interface) { ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod(); ResolvedJavaType leastCommonType = getLeastCommonType(); + ResolvedJavaType contextType = invoke.getContextType(); // check if we have a common base type that implements the interface -> in that case // we have a vtable entry for the interface method and can use a less expensive // virtual call if (!leastCommonType.isInterface() && targetMethod.getDeclaringClass().isAssignableFrom(leastCommonType)) { - ResolvedJavaMethod baseClassTargetMethod = leastCommonType.resolveMethod(targetMethod); + ResolvedJavaMethod baseClassTargetMethod = leastCommonType.resolveMethod(targetMethod, contextType); if (baseClassTargetMethod != null) { - devirtualizeWithTypeSwitch(graph, InvokeKind.Virtual, leastCommonType.resolveMethod(targetMethod), metaAccess); + devirtualizeWithTypeSwitch(graph, InvokeKind.Virtual, leastCommonType.resolveMethod(targetMethod, contextType), metaAccess); } } } diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri Apr 18 13:50:15 2014 +0200 @@ -178,15 +178,15 @@ return; } + Invoke invoke = callTargetNode.invoke(); if (!callTargetNode.isStatic()) { assert callTargetNode.receiver().getKind() == wordKind : "changeToWord() missed the receiver"; - targetMethod = wordImplType.resolveMethod(targetMethod); + targetMethod = wordImplType.resolveMethod(targetMethod, invoke.getContextType()); } Operation operation = targetMethod.getAnnotation(Word.Operation.class); assert operation != null : targetMethod; NodeInputList arguments = callTargetNode.arguments(); - Invoke invoke = callTargetNode.invoke(); switch (operation.opcode()) { case NODE_CLASS: diff -r 1e3f19292a32 -r c583759bbcfd graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri May 16 19:59:52 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Apr 18 13:50:15 2014 +0200 @@ -113,7 +113,7 @@ if (!isStatic) { ValueNode receiver = arguments.get(argc); if (receiver == node && isWord(node)) { - ResolvedJavaMethod resolvedMethod = wordAccess.wordImplType.resolveMethod(method); + ResolvedJavaMethod resolvedMethod = wordAccess.wordImplType.resolveMethod(method, invoke.getContextType()); verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); Operation operation = resolvedMethod.getAnnotation(Word.Operation.class); verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); diff -r 1e3f19292a32 -r c583759bbcfd src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri May 16 19:59:52 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 18 13:50:15 2014 +0200 @@ -468,11 +468,69 @@ return (jlong) (address) result.field_holder(); C2V_END -C2V_VMENTRY(jlong, resolveMethod, (JNIEnv *, jobject, jlong metaspace_klass, jstring name, jstring signature)) - Klass* klass = (Klass*) metaspace_klass; - Symbol* name_symbol = java_lang_String::as_symbol(JNIHandles::resolve(name), THREAD); - Symbol* signature_symbol = java_lang_String::as_symbol(JNIHandles::resolve(signature), THREAD); - return (jlong) (address) klass->lookup_method(name_symbol, signature_symbol); +C2V_VMENTRY(jlong, resolveMethod, (JNIEnv *, jobject, jlong metaspace_klass_receiver, jlong metaspace_method, jlong metaspace_klass_caller)) + Klass* recv_klass = (Klass*) metaspace_klass_receiver; + Klass* caller_klass = (Klass*) metaspace_klass_caller; + Method* method = (Method*) metaspace_method; + + if (recv_klass->oop_is_array() || (InstanceKlass::cast(recv_klass)->is_linked())) { + Klass* holder_klass = method->method_holder(); + Symbol* method_name = method->name(); + Symbol* method_signature = method->signature(); + + + if (holder_klass->is_interface()) { + // do link-time resolution to check all access rules. + methodHandle resolved_method; + LinkResolver::linktime_resolve_interface_method(resolved_method, holder_klass, method_name, method_signature, caller_klass, true, CHECK_AND_CLEAR_0); + if (resolved_method->is_private()) { + return (jlong) NULL; + } + assert(recv_klass->is_subtype_of(holder_klass), ""); + // do actual lookup + methodHandle sel_method; + LinkResolver::lookup_instance_method_in_klasses(sel_method, recv_klass, + resolved_method->name(), + resolved_method->signature(), CHECK_AND_CLEAR_0); + return (jlong) (address) sel_method(); + } else { + // do link-time resolution to check all access rules. + methodHandle resolved_method; + LinkResolver::linktime_resolve_virtual_method(resolved_method, holder_klass, method_name, method_signature, caller_klass, true, CHECK_AND_CLEAR_0); + // do actual lookup (see LinkResolver::runtime_resolve_virtual_method) + int vtable_index = Method::invalid_vtable_index; + Method* selected_method; + + if (resolved_method->method_holder()->is_interface()) { // miranda method + vtable_index = LinkResolver::vtable_index_of_interface_method(holder_klass, resolved_method); + assert(vtable_index >= 0 , "we should have valid vtable index at this point"); + + InstanceKlass* inst = InstanceKlass::cast(recv_klass); + selected_method = inst->method_at_vtable(vtable_index); + } else { + // at this point we are sure that resolved_method is virtual and not + // a miranda method; therefore, it must have a valid vtable index. + assert(!resolved_method->has_itable_index(), ""); + vtable_index = resolved_method->vtable_index(); + // We could get a negative vtable_index for final methods, + // because as an optimization they are they are never put in the vtable, + // unless they override an existing method. + // If we do get a negative, it means the resolved method is the the selected + // method, and it can never be changed by an override. + if (vtable_index == Method::nonvirtual_vtable_index) { + assert(resolved_method->can_be_statically_bound(), "cannot override this method"); + selected_method = resolved_method(); + } else { + // recv_klass might be an arrayKlassOop but all vtables start at + // the same place. The cast is to avoid virtual call and assertion. + InstanceKlass* inst = (InstanceKlass*)recv_klass; + selected_method = inst->method_at_vtable(vtable_index); + } + } + return (jlong) (address) selected_method; + } + } + return (jlong) NULL; C2V_END C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jlong metaspace_klass)) @@ -1058,58 +1116,58 @@ #define METASPACE_SYMBOL "J" JNINativeMethod CompilerToVM_methods[] = { - {CC"initializeBytecode", CC"("METASPACE_METHOD"[B)[B", FN_PTR(initializeBytecode)}, - {CC"exceptionTableStart", CC"("METASPACE_METHOD")J", FN_PTR(exceptionTableStart)}, - {CC"exceptionTableLength", CC"("METASPACE_METHOD")I", FN_PTR(exceptionTableLength)}, - {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, - {CC"findUniqueConcreteMethod", CC"("METASPACE_METHOD")"METASPACE_METHOD, FN_PTR(findUniqueConcreteMethod)}, - {CC"getKlassImplementor", CC"("METASPACE_KLASS")"METASPACE_KLASS, FN_PTR(getKlassImplementor)}, - {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, - {CC"methodIsIgnoredBySecurityStackWalk", CC"("METASPACE_METHOD")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)}, - {CC"doNotInlineOrCompile", CC"("METASPACE_METHOD")V", FN_PTR(doNotInlineOrCompile)}, - {CC"canInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(canInlineMethod)}, - {CC"shouldInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(shouldInlineMethod)}, - {CC"lookupType", CC"("STRING CLASS"Z)"METASPACE_KLASS, FN_PTR(lookupType)}, - {CC"resolveConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolveConstantInPool)}, - {CC"resolvePossiblyCachedConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolvePossiblyCachedConstantInPool)}, - {CC"lookupNameRefInPool", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_SYMBOL, FN_PTR(lookupNameRefInPool)}, - {CC"lookupNameAndTypeRefIndexInPool", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(lookupNameAndTypeRefIndexInPool)}, - {CC"lookupSignatureRefInPool", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_SYMBOL, FN_PTR(lookupSignatureRefInPool)}, - {CC"lookupKlassRefIndexInPool", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(lookupKlassRefIndexInPool)}, - {CC"constantPoolKlassAt", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS, FN_PTR(constantPoolKlassAt)}, - {CC"lookupKlassInPool", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS, FN_PTR(lookupKlassInPool)}, - {CC"lookupAppendixInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(lookupAppendixInPool)}, - {CC"lookupMethodInPool", CC"("METASPACE_CONSTANT_POOL"IB)"METASPACE_METHOD, FN_PTR(lookupMethodInPool)}, - {CC"constantPoolRemapInstructionOperandFromCache", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(constantPoolRemapInstructionOperandFromCache)}, - {CC"resolveField", CC"("METASPACE_CONSTANT_POOL"IB[J)"METASPACE_KLASS, FN_PTR(resolveField)}, - {CC"resolveInvokeDynamic", CC"("METASPACE_CONSTANT_POOL"I)V", FN_PTR(resolveInvokeDynamic)}, - {CC"resolveMethod", CC"("METASPACE_KLASS STRING STRING")"METASPACE_METHOD, FN_PTR(resolveMethod)}, - {CC"getClassInitializer", CC"("METASPACE_KLASS")"METASPACE_METHOD, FN_PTR(getClassInitializer)}, - {CC"hasFinalizableSubclass", CC"("METASPACE_KLASS")Z", FN_PTR(hasFinalizableSubclass)}, - {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, - {CC"getMetaspaceMethod", CC"("CLASS"I)"METASPACE_METHOD, FN_PTR(getMetaspaceMethod)}, - {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, - {CC"installCode0", CC"("HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode0)}, - {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)}, - {CC"printCompilationStatistics", CC"(ZZ)V", FN_PTR(printCompilationStatistics)}, - {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)}, - {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, - {CC"executeCompiledMethodVarargs", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, - {CC"getLineNumberTable", CC"("METASPACE_METHOD")[J", FN_PTR(getLineNumberTable)}, - {CC"getLocalVariableTableStart", CC"("METASPACE_METHOD")J", FN_PTR(getLocalVariableTableStart)}, - {CC"getLocalVariableTableLength", CC"("METASPACE_METHOD")I", FN_PTR(getLocalVariableTableLength)}, - {CC"reprofile", CC"("METASPACE_METHOD")V", FN_PTR(reprofile)}, - {CC"invalidateInstalledCode", CC"("INSTALLED_CODE")V", FN_PTR(invalidateInstalledCode)}, - {CC"getJavaMirror", CC"("METASPACE_KLASS")"CLASS, FN_PTR(getJavaMirror)}, - {CC"readUnsafeKlassPointer", CC"("OBJECT")J", FN_PTR(readUnsafeKlassPointer)}, - {CC"collectCounters", CC"()[J", FN_PTR(collectCounters)}, - {CC"getGPUs", CC"()"STRING, FN_PTR(getGPUs)}, - {CC"allocateCompileId", CC"("METASPACE_METHOD"I)I", FN_PTR(allocateCompileId)}, - {CC"isMature", CC"("METASPACE_METHOD_DATA")Z", FN_PTR(isMature)}, - {CC"hasCompiledCodeForOSR", CC"("METASPACE_METHOD"II)Z", FN_PTR(hasCompiledCodeForOSR)}, - {CC"getTimeStamp", CC"()J", FN_PTR(getTimeStamp)}, - {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "[JI)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, - {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)}, + {CC"initializeBytecode", CC"("METASPACE_METHOD"[B)[B", FN_PTR(initializeBytecode)}, + {CC"exceptionTableStart", CC"("METASPACE_METHOD")J", FN_PTR(exceptionTableStart)}, + {CC"exceptionTableLength", CC"("METASPACE_METHOD")I", FN_PTR(exceptionTableLength)}, + {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, + {CC"findUniqueConcreteMethod", CC"("METASPACE_METHOD")"METASPACE_METHOD, FN_PTR(findUniqueConcreteMethod)}, + {CC"getKlassImplementor", CC"("METASPACE_KLASS")"METASPACE_KLASS, FN_PTR(getKlassImplementor)}, + {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, + {CC"methodIsIgnoredBySecurityStackWalk", CC"("METASPACE_METHOD")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)}, + {CC"doNotInlineOrCompile", CC"("METASPACE_METHOD")V", FN_PTR(doNotInlineOrCompile)}, + {CC"canInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(canInlineMethod)}, + {CC"shouldInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(shouldInlineMethod)}, + {CC"lookupType", CC"("STRING CLASS"Z)"METASPACE_KLASS, FN_PTR(lookupType)}, + {CC"resolveConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolveConstantInPool)}, + {CC"resolvePossiblyCachedConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolvePossiblyCachedConstantInPool)}, + {CC"lookupNameRefInPool", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_SYMBOL, FN_PTR(lookupNameRefInPool)}, + {CC"lookupNameAndTypeRefIndexInPool", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(lookupNameAndTypeRefIndexInPool)}, + {CC"lookupSignatureRefInPool", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_SYMBOL, FN_PTR(lookupSignatureRefInPool)}, + {CC"lookupKlassRefIndexInPool", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(lookupKlassRefIndexInPool)}, + {CC"constantPoolKlassAt", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS, FN_PTR(constantPoolKlassAt)}, + {CC"lookupKlassInPool", CC"("METASPACE_CONSTANT_POOL"I)"METASPACE_KLASS, FN_PTR(lookupKlassInPool)}, + {CC"lookupAppendixInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(lookupAppendixInPool)}, + {CC"lookupMethodInPool", CC"("METASPACE_CONSTANT_POOL"IB)"METASPACE_METHOD, FN_PTR(lookupMethodInPool)}, + {CC"constantPoolRemapInstructionOperandFromCache", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(constantPoolRemapInstructionOperandFromCache)}, + {CC"resolveField", CC"("METASPACE_CONSTANT_POOL"IB[J)"METASPACE_KLASS, FN_PTR(resolveField)}, + {CC"resolveInvokeDynamic", CC"("METASPACE_CONSTANT_POOL"I)V", FN_PTR(resolveInvokeDynamic)}, + {CC"resolveMethod", CC"("METASPACE_KLASS METASPACE_METHOD METASPACE_KLASS")"METASPACE_METHOD, FN_PTR(resolveMethod)}, + {CC"getClassInitializer", CC"("METASPACE_KLASS")"METASPACE_METHOD, FN_PTR(getClassInitializer)}, + {CC"hasFinalizableSubclass", CC"("METASPACE_KLASS")Z", FN_PTR(hasFinalizableSubclass)}, + {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, + {CC"getMetaspaceMethod", CC"("CLASS"I)"METASPACE_METHOD, FN_PTR(getMetaspaceMethod)}, + {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, + {CC"installCode0", CC"("HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode0)}, + {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)}, + {CC"printCompilationStatistics", CC"(ZZ)V", FN_PTR(printCompilationStatistics)}, + {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)}, + {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, + {CC"executeCompiledMethodVarargs", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"getLineNumberTable", CC"("METASPACE_METHOD")[J", FN_PTR(getLineNumberTable)}, + {CC"getLocalVariableTableStart", CC"("METASPACE_METHOD")J", FN_PTR(getLocalVariableTableStart)}, + {CC"getLocalVariableTableLength", CC"("METASPACE_METHOD")I", FN_PTR(getLocalVariableTableLength)}, + {CC"reprofile", CC"("METASPACE_METHOD")V", FN_PTR(reprofile)}, + {CC"invalidateInstalledCode", CC"("INSTALLED_CODE")V", FN_PTR(invalidateInstalledCode)}, + {CC"getJavaMirror", CC"("METASPACE_KLASS")"CLASS, FN_PTR(getJavaMirror)}, + {CC"readUnsafeKlassPointer", CC"("OBJECT")J", FN_PTR(readUnsafeKlassPointer)}, + {CC"collectCounters", CC"()[J", FN_PTR(collectCounters)}, + {CC"getGPUs", CC"()"STRING, FN_PTR(getGPUs)}, + {CC"allocateCompileId", CC"("METASPACE_METHOD"I)I", FN_PTR(allocateCompileId)}, + {CC"isMature", CC"("METASPACE_METHOD_DATA")Z", FN_PTR(isMature)}, + {CC"hasCompiledCodeForOSR", CC"("METASPACE_METHOD"II)Z", FN_PTR(hasCompiledCodeForOSR)}, + {CC"getTimeStamp", CC"()J", FN_PTR(getTimeStamp)}, + {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "[JI)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, + {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)}, }; int CompilerToVM_methods_count() { diff -r 1e3f19292a32 -r c583759bbcfd src/share/vm/interpreter/linkResolver.hpp --- a/src/share/vm/interpreter/linkResolver.hpp Fri May 16 19:59:52 2014 +0200 +++ b/src/share/vm/interpreter/linkResolver.hpp Fri Apr 18 13:50:15 2014 +0200 @@ -125,7 +125,13 @@ private: static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS); +#ifdef GRAAL + public: +#endif static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); +#ifdef GRAAL + private: +#endif static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS); @@ -139,8 +145,14 @@ static void linktime_resolve_static_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); static void linktime_resolve_special_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); +#ifdef GRAAL + public: +#endif static void linktime_resolve_virtual_method (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS); static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); +#ifdef GRAAL + private: +#endif static void runtime_resolve_special_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS); static void runtime_resolve_virtual_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);