# HG changeset patch # User Matthias Grimmer # Date 1365773436 -7200 # Node ID 640996823a81b450f04361fa87fe4c15369e95e4 # Parent 8802f66cba62ff2feea6ff396046f592a3b54481 InstalledCode intrinsification fixes diff -r 8802f66cba62 -r 640996823a81 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Fri Apr 12 13:44:44 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Fri Apr 12 15:30:36 2013 +0200 @@ -22,65 +22,103 @@ */ package com.oracle.graal.hotspot.test; +import static com.oracle.graal.api.meta.MetaUtil.*; +import static java.lang.reflect.Modifier.*; + import java.lang.reflect.*; -import com.oracle.graal.api.code.*; +import org.junit.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.*; public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { - private static final int ITERATIONS = 100000000; + private static final int ITERATIONS = 10000; + private final MetaAccessProvider metaAccessProvider; + Object[] argsToBind; - // TODO this is not a test, move it somewhere else - // CheckStyle: stop system..print check - public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException { + public static void main(String[] args) throws NoSuchMethodException, SecurityException { + InstalledCodeExecuteHelperTest main = new InstalledCodeExecuteHelperTest(); + main.testWithTime(); + } - final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class); - final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod); - HotSpotInstalledCode benchCode = (HotSpotInstalledCode) getCode(benchJavaMethod, parse(benchrMethod)); + public InstalledCodeExecuteHelperTest() { + this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class); + } - final Method wrapperMethod = InstalledCodeExecuteHelperTest.class.getMethod("executeWrapper", long.class, long.class, Object.class, Object.class, Object.class); - final ResolvedJavaMethod wrapperJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(wrapperMethod); - HotSpotInstalledCode wrapperCode = (HotSpotInstalledCode) getCode(wrapperJavaMethod, parse(wrapperMethod)); - + @Ignore + @Test + public void test1() throws NoSuchMethodException, SecurityException { final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class); - final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(fooMethod); - HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); + final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod); + final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); - System.out.println(wrapperCode.executeVarargs(fooCode.getnmethod(), fooJavaMethod.getMetaspaceMethod(), null, null, null)); + argsToBind = new Object[]{fooCode}; - long nmethod = fooCode.getnmethod(); - long metaspacemethod = fooJavaMethod.getMetaspaceMethod(); + final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class); + final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod); + final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod)); - System.out.println("Without replaced InstalledCode.execute:" + bench(nmethod, metaspacemethod)); + Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode)); - System.out.println("WITH replaced InstalledCode.execute:" + benchCode.executeVarargs(nmethod, metaspacemethod)); + Assert.assertEquals(Integer.valueOf(42), installedBenchmarkCode.executeVarargs(argsToBind[0])); } - // CheckStyle: resume system..print check + public void testWithTime() throws NoSuchMethodException, SecurityException { + final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class); + final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod); + final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); - public static Long bench(long nmethod, long metaspacemethod) throws InvalidInstalledCodeException { - long start = System.currentTimeMillis(); + argsToBind = new Object[]{fooCode}; + + final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class); + final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod); + final HotSpotInstalledCode installedBenchmarkCodeotInstalledCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod)); - for (int i = 0; i < ITERATIONS; i++) { - HotSpotInstalledCode.executeHelper(nmethod, metaspacemethod, null, null, null); - } + long start = System.currentTimeMillis(); + benchmark(fooCode); + long end = System.currentTimeMillis(); + @SuppressWarnings("unused") + long time = (end - start); - long end = System.currentTimeMillis(); - return (end - start); + start = System.currentTimeMillis(); + installedBenchmarkCodeotInstalledCode.executeVarargs(argsToBind[0]); + end = System.currentTimeMillis(); + time = (end - start); } - public static Object foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { + public static Integer benchmark(HotSpotInstalledCode code) { + int val = 0; + for (int i = 0; i < ITERATIONS; i++) { + val = (Integer) code.execute(null, null, null); + } + return val; + } + + public static Integer foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { return 42; } - public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { - return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3); + @Override + protected StructuredGraph parse(Method m) { + StructuredGraph graph = super.parse(m); + if (argsToBind != null) { + Object receiver = isStatic(m.getModifiers()) ? null : this; + Object[] args = argsWithReceiver(receiver, argsToBind); + JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m)); + assert parameterTypes.length == args.length; + for (int i = 0; i < argsToBind.length; i++) { + LocalNode local = graph.getLocal(i); + Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]); + ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph); + local.replaceAtUsages(replacement); + } + } + return graph; } - } diff -r 8802f66cba62 -r 640996823a81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 12 13:44:44 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 12 15:30:36 2013 +0200 @@ -39,12 +39,13 @@ private final HotSpotResolvedJavaMethod method; private final boolean isDefault; - private final long nmethod; // This field is set by the runtime upon code installation. + private final Graph graph; + long nmethod; long start; - public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) { - this.nmethod = 0; + public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) { this.method = method; + this.graph = graph; this.isDefault = isDefault; } @@ -52,10 +53,14 @@ return isDefault; } - public long getnmethod() { + public long getMethodAddress() { return nmethod; } + public Graph getGraph() { + return graph; + } + @Override public ResolvedJavaMethod getMethod() { return method; @@ -114,9 +119,4 @@ public byte[] getCode() { return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod); } - - @SuppressWarnings("unused") - public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod); - } } diff -r 8802f66cba62 -r 640996823a81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Fri Apr 12 13:44:44 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Fri Apr 12 15:30:36 2013 +0200 @@ -24,22 +24,24 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.word.*; +import com.oracle.graal.phases.common.*; public class HotSpotInstalledCodeExecuteNode extends AbstractCallNode implements Lowerable { - @Input private final ValueNode targetAddress; - @Input private final ValueNode metaspaceObject; + @Input private final ValueNode code; private final Class[] signature; - public HotSpotInstalledCodeExecuteNode(Kind kind, ValueNode targetAddress, ValueNode metaspaceObject, Class[] signature, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + public HotSpotInstalledCodeExecuteNode(Kind kind, Class[] signature, ValueNode code, ValueNode arg1, ValueNode arg2, ValueNode arg3) { super(StampFactory.forKind(kind), new ValueNode[]{arg1, arg2, arg3}); - this.targetAddress = targetAddress; - this.metaspaceObject = metaspaceObject; + this.code = code; this.signature = signature; } @@ -50,30 +52,54 @@ @Override public void lower(LoweringTool tool) { - replaceWithInvoke(tool); + if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotInstalledCode) { + HotSpotInstalledCode hsCode = (HotSpotInstalledCode) code.asConstant().asObject(); + InvokeNode invoke = replaceWithInvoke(tool.getRuntime()); + InliningUtil.inline(invoke, (StructuredGraph) hsCode.getGraph(), false); + } else { + replaceWithInvoke(tool.getRuntime()); + } } - private InvokeNode replaceWithInvoke(LoweringTool tool) { - InvokeNode invoke = createInvoke(tool); - ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke); - return invoke; - } - - protected InvokeNode createInvoke(LoweringTool tool) { + protected InvokeNode replaceWithInvoke(MetaAccessProvider tool) { ResolvedJavaMethod method = null; + ResolvedJavaField methodField = null; + ResolvedJavaField metaspaceMethodField = null; + ResolvedJavaField nmethodField = null; try { - method = tool.getRuntime().lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); - } catch (NoSuchMethodException | SecurityException e) { - throw new IllegalStateException(); + method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); + methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method")); + nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod")); + metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod")); + } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) { + throw new IllegalStateException(e); } ResolvedJavaType[] signatureTypes = new ResolvedJavaType[signature.length]; for (int i = 0; i < signature.length; i++) { - signatureTypes[i] = tool.getRuntime().lookupJavaType(signature[i]); + signatureTypes[i] = tool.lookupJavaType(signature[i]); } - HotSpotIndirectCallTargetNode callTarget = graph().add( - new HotSpotIndirectCallTargetNode(metaspaceObject, targetAddress, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall)); - InvokeNode invoke = graph().add(new InvokeNode(callTarget, 0)); + final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset(); + + StructuredGraph g = (StructuredGraph) graph(); + + LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField)); + UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), HotSpotGraalRuntime.getInstance().getTarget().wordKind)); + + LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField)); + LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField)); + + HotSpotIndirectCallTargetNode callTarget = g.add(new HotSpotIndirectCallTargetNode(loadmetaspaceMethod, load, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall)); + + InvokeNode invoke = g.add(new InvokeNode(callTarget, 0)); + invoke.setStateAfter(stateAfter()); + g.replaceFixedWithFixed(this, invoke); + + g.addBeforeFixed(invoke, loadmetaspaceMethod); + g.addBeforeFixed(loadmetaspaceMethod, loadMethod); + g.addBeforeFixed(invoke, load); + g.addBeforeFixed(load, loadnmethod); + return invoke; } @@ -82,6 +108,6 @@ } @NodeIntrinsic - public static native T call(@ConstantNodeParameter Kind kind, Word targetAddress, long metaspaceObject, @ConstantNodeParameter Class[] signature, Object arg1, Object arg2, Object arg3); + public static native T call(@ConstantNodeParameter Kind kind, @ConstantNodeParameter Class[] signature, Object code, Object arg1, Object arg2, Object arg3); } diff -r 8802f66cba62 -r 640996823a81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java Fri Apr 12 13:44:44 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java Fri Apr 12 15:30:36 2013 +0200 @@ -22,25 +22,28 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.graph.UnsafeAccess.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.word.*; @ClassSubstitution(HotSpotInstalledCode.class) public class HotSpotInstalledCodeSubstitutions { - @MethodSubstitution - public static Object executeHelper(long nmethod, long metaspaceMethod, final Object arg1, final Object arg2, final Object arg3) { - final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset(); - final Word callTarget = Word.unsigned(nmethod).readWord(verifiedEntryPointOffset); - return HotSpotInstalledCodeExecuteNode.call(Kind.Object, callTarget, metaspaceMethod, getSignature(), arg1, arg2, arg3); + @MethodSubstitution(isStatic = false) + public static Object execute(HotSpotInstalledCode code, final Object arg1, final Object arg2, final Object arg3) { + return HotSpotInstalledCodeExecuteNode.call(Kind.Object, getSignature(), code, arg1, arg2, arg3); } @Fold private static Class[] getSignature() { return new Class[]{Object.class, Object.class, Object.class}; } + + + } diff -r 8802f66cba62 -r 640996823a81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Fri Apr 12 13:44:44 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Fri Apr 12 15:30:36 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.spi; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; /** @@ -30,5 +31,17 @@ */ public interface GraalCodeCacheProvider extends CodeCacheProvider { + /** + * Adds the given compilation result as an implementation of the given method without making it + * the default implementation. The graph might be inlined later on. + * + * @param method a method to which the executable code is begin added + * @param compResult the compilation result to be added + * @param graph the graph that represents the method + * @return a reference to the compiled and ready-to-run code or null if the code installation + * failed + */ + InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph); + void lower(Node n, LoweringTool tool); } diff -r 8802f66cba62 -r 640996823a81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalInstalledCode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalInstalledCode.java Fri Apr 12 15:30:36 2013 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011, 2011, 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.nodes.spi; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; + +/** + * Graal-specific extensions for the installed code interface. + */ +public interface GraalInstalledCode extends InstalledCode { + + Graph getGraph(); +}