# HG changeset patch # User Gilles Duboscq # Date 1365783456 -7200 # Node ID c46b5c34066023cc76ed9ccb81ea6c0f577f98ab # Parent 1946c86f88429459e8b5c37d335c073ebe7c8d0c# Parent 5ab06146e9850de0853c9421efe40787d3663119 Merge diff -r 5ab06146e985 -r c46b5c340660 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Apr 12 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Apr 12 18:17:36 2013 +0200 @@ -405,6 +405,7 @@ } long start = System.currentTimeMillis(); PhasePlan phasePlan = new PhasePlan(); + StructuredGraph graphCopy = graph.copy(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase()); @@ -414,7 +415,7 @@ if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } - return addMethod(method, compResult); + return addMethod(method, compResult, graphCopy); } }); @@ -424,12 +425,12 @@ return installedCode; } - protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) { + protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) { return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable() { @Override public InstalledCode call() throws Exception { - InstalledCode installedCode = runtime.addMethod(method, compResult); + InstalledCode installedCode = runtime.addMethod(method, compResult, graph); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } diff -r 5ab06146e985 -r c46b5c340660 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 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Fri Apr 12 18:17:36 2013 +0200 @@ -22,65 +22,77 @@ */ 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 org.junit.*; + import com.oracle.graal.api.code.*; 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 = 100000; + 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 { - - 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)); + @Test + public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException { + 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)); - 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)); + argsToBind = new Object[]{fooCode}; - System.out.println(wrapperCode.executeVarargs(fooCode.getnmethod(), fooJavaMethod.getMetaspaceMethod(), null, null, null)); + final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class); + final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod); + final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod)); - long nmethod = fooCode.getnmethod(); - long metaspacemethod = fooJavaMethod.getMetaspaceMethod(); + Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode)); - System.out.println("Without replaced InstalledCode.execute:" + bench(nmethod, metaspacemethod)); - - 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 static Long bench(long nmethod, long metaspacemethod) throws InvalidInstalledCodeException { - long start = System.currentTimeMillis(); - - for (int i = 0; i < ITERATIONS; i++) { - HotSpotInstalledCode.executeHelper(nmethod, metaspacemethod, null, null, null); + public static Integer benchmark(HotSpotInstalledCode code) throws InvalidInstalledCodeException { + int val = 0; + for (int j = 0; j < 100; j++) { + for (int i = 0; i < ITERATIONS; i++) { + val = (Integer) code.execute(null, null, null); + } } - - long end = System.currentTimeMillis(); - return (end - start); + return val; } - public static Object foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { + 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 5ab06146e985 -r c46b5c340660 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri Apr 12 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri Apr 12 18:17:36 2013 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -167,7 +168,7 @@ } } - installMethod(result); + installMethod(result, null); } catch (BailoutException bailout) { Debug.metric("Bailouts").increment(); if (GraalOptions.ExitVMOnBailout) { @@ -197,12 +198,12 @@ MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize())); } - private void installMethod(final CompilationResult compResult) { + private void installMethod(final CompilationResult compResult, final Graph graph) { Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() { @Override public void run() { - HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult); + HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, graph, entryBCI, compResult); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } diff -r 5ab06146e985 -r c46b5c340660 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 Apr 12 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 12 18:17:36 2013 +0200 @@ -170,5 +170,12 @@ return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod); } + /** + * Direct call to the given nativeMethod with three object arguments and an object return value. + * This method does not have an implementation on the C++ side, but its entry points (from + * interpreter and from compiled code) are directly pointing to a manually generated assembly + * stub that does the necessary argument shuffling and a tail call via an indirect jump to the + * verified entry point of the given native method. + */ private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod); } diff -r 5ab06146e985 -r c46b5c340660 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 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 12 18:17:36 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; /** @@ -39,12 +40,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 +54,14 @@ return isDefault; } - public long getnmethod() { + public long getMethodAddress() { return nmethod; } + public Graph getGraph() { + return graph; + } + @Override public ResolvedJavaMethod getMethod() { return method; @@ -114,9 +120,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 5ab06146e985 -r c46b5c340660 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Apr 12 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Apr 12 18:17:36 2013 +0200 @@ -766,16 +766,21 @@ return graalRuntime.getCompilerToVM().getJavaField(reflectionField); } - public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) { - HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, true); + public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, Graph graph, int entryBCI, CompilationResult compResult) { + HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, graph, true); graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), installedCode, method.getSpeculationLog()); return installedCode; } @Override public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + return addMethod(method, compResult, null); + } + + @Override + public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) { HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false); + HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, graph, false); CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, null); if (result != CodeInstallResult.OK) { return null; @@ -894,7 +899,7 @@ public String disassemble(InstalledCode code) { if (code.isValid()) { - long nmethod = ((HotSpotInstalledCode) code).getnmethod(); + long nmethod = ((HotSpotInstalledCode) code).getMethodAddress(); return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod); } return null; diff -r 5ab06146e985 -r c46b5c340660 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 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Fri Apr 12 18:17: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,57 @@ @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()); + StructuredGraph graph = (StructuredGraph) hsCode.getGraph(); + if (graph != null) { + 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 +111,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 5ab06146e985 -r c46b5c340660 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 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java Fri Apr 12 18:17:36 2013 +0200 @@ -27,20 +27,18 @@ 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 5ab06146e985 -r c46b5c340660 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 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Fri Apr 12 18:17: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 5ab06146e985 -r c46b5c340660 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Apr 12 14:15:59 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Apr 12 18:17:36 2013 +0200 @@ -816,6 +816,8 @@ buf.append(" ").append(name); } else if (value == UNUSED_PARAMETER) { buf.append(" ").append(name); + } else if (value == CONSTANT_PARAMETER) { + buf.append(" ").append(name); } else if (value instanceof LocalNode) { LocalNode local = (LocalNode) value; buf.append(local.kind().getJavaName()).append(' ').append(name); diff -r 5ab06146e985 -r c46b5c340660 src/cpu/sparc/vm/interpreter_sparc.cpp --- a/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -381,7 +381,9 @@ case Interpreter::zerolocals_synchronized: synchronized = true; break; case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; +#ifdef GRAAL case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break; +#endif case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; diff -r 5ab06146e985 -r c46b5c340660 src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -1917,7 +1917,6 @@ BasicType* in_sig_bt, VMRegPair* in_regs, BasicType ret_type) { - assert (method->intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "not yet ported"); if (method->is_method_handle_intrinsic()) { vmIntrinsics::ID iid = method->intrinsic_id(); intptr_t start = (intptr_t)__ pc(); diff -r 5ab06146e985 -r c46b5c340660 src/cpu/x86/vm/interpreterGenerator_x86.hpp --- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp Fri Apr 12 18:17:36 2013 +0200 @@ -36,7 +36,9 @@ address generate_normal_entry(bool synchronized); address generate_native_entry(bool synchronized); +#ifdef GRAAL address generate_execute_compiled_method_entry(); +#endif address generate_abstract_entry(void); address generate_math_entry(AbstractInterpreter::MethodKind kind); address generate_empty_entry(void); diff -r 5ab06146e985 -r c46b5c340660 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -1670,10 +1670,16 @@ verify_oop_args(masm, method, sig_bt, regs); vmIntrinsics::ID iid = method->intrinsic_id(); +#ifdef GRAAL if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + // We are called from compiled code here. The three object arguments + // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The + // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail + // call to its verified entry point. __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); return; } +#endif // Now write the args into the outgoing interpreter space bool has_receiver = false; diff -r 5ab06146e985 -r c46b5c340660 src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -873,6 +873,8 @@ return generate_accessor_entry(); } +#ifdef GRAAL + // Interpreter stub for calling a compiled method with 3 object arguments address InterpreterGenerator::generate_execute_compiled_method_entry() { address entry_point = __ pc(); @@ -891,14 +893,27 @@ // as far as the placement of the call instruction __ push(rax); + // Move first object argument from interpreter calling convention to compiled + // code calling convention. __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5)); + + // Move second object argument. __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4)); + + // Move third object argument. __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3)); + + // Load the raw pointer to the nmethod. __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize)); + + // Perform a tail call to the verified entry point of the nmethod. __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); + return entry_point; } +#endif + // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the // native method than the typical interpreter frame setup. @@ -1586,7 +1601,9 @@ switch (kind) { case Interpreter::zerolocals : break; case Interpreter::zerolocals_synchronized: synchronized = true; break; +#ifdef GRAAL case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break; +#endif case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; diff -r 5ab06146e985 -r c46b5c340660 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/share/vm/code/nmethod.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -1307,9 +1307,12 @@ } #ifdef GRAAL - if (_graal_installed_code != NULL) { - _graal_installed_code = NULL; - } + // The method can only be unloaded after the pointer to the installed code + // Java wrapper is no longer alive. Here we need to clear out this weak + // reference to the dead object. + if (_graal_installed_code != NULL) { + _graal_installed_code = NULL; + } #endif // Make the class unloaded - i.e., change state and notify sweeper @@ -1396,14 +1399,14 @@ // The caller can be calling the method statically or through an inline // cache call. if (!is_osr_method() && !is_not_entrant()) { + address stub = SharedRuntime::get_handle_wrong_method_stub(); +#ifdef GRAAL if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) { // This was manually installed machine code. Patch entry with stub that throws an exception. - NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), - SharedRuntime::get_deoptimized_installed_code_stub()); - } else { - NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), - SharedRuntime::get_handle_wrong_method_stub()); + stub = SharedRuntime::get_deoptimized_installed_code_stub(); } +#endif + NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub); } if (is_in_use()) { diff -r 5ab06146e985 -r c46b5c340660 src/share/vm/interpreter/abstractInterpreter.hpp --- a/src/share/vm/interpreter/abstractInterpreter.hpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/share/vm/interpreter/abstractInterpreter.hpp Fri Apr 12 18:17:36 2013 +0200 @@ -85,7 +85,9 @@ zerolocals_synchronized, // method needs locals initialization & is synchronized native, // native method native_synchronized, // native method & is synchronized +#ifdef GRAAL execute_compiled_method, // direct call to compiled method address +#endif empty, // empty method (code: _return) accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return) abstract, // abstract method (throws an AbstractMethodException) diff -r 5ab06146e985 -r c46b5c340660 src/share/vm/interpreter/interpreter.cpp --- a/src/share/vm/interpreter/interpreter.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/share/vm/interpreter/interpreter.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -188,9 +188,13 @@ // Method handle primitive? if (m->is_method_handle_intrinsic()) { vmIntrinsics::ID id = m->intrinsic_id(); +#ifdef GRAAL if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + // Special method kind for directly executing the verified entry point + // of a given nmethod. return AbstractInterpreter::execute_compiled_method; } +#endif assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic"); MethodKind kind = (MethodKind)( method_handle_invoke_FIRST + ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) ); @@ -290,7 +294,9 @@ case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break; case native : tty->print("native" ); break; case native_synchronized : tty->print("native_synchronized" ); break; +#ifdef GRAAL case execute_compiled_method: tty->print("execute_compiled_method"); break; +#endif case empty : tty->print("empty" ); break; case accessor : tty->print("accessor" ); break; case abstract : tty->print("abstract" ); break; diff -r 5ab06146e985 -r c46b5c340660 src/share/vm/interpreter/templateInterpreter.cpp --- a/src/share/vm/interpreter/templateInterpreter.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/share/vm/interpreter/templateInterpreter.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -360,7 +360,9 @@ method_entry(zerolocals) method_entry(zerolocals_synchronized) method_entry(empty) +#ifdef GRAAL method_entry(execute_compiled_method) +#endif method_entry(accessor) method_entry(abstract) method_entry(java_lang_math_sin ) diff -r 5ab06146e985 -r c46b5c340660 src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/share/vm/oops/method.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -850,10 +850,15 @@ (void) make_adapters(h_method, CHECK); // ONLY USE the h_method now as make_adapter may have blocked + +#ifdef GRAAL + // Check for special intrinsic that executes a compiled method. if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + // Actively install the stub for calling the intrinsic from compiled code. CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier, methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK); } +#endif } address Method::make_adapters(methodHandle mh, TRAPS) { diff -r 5ab06146e985 -r c46b5c340660 src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Fri Apr 12 14:15:59 2013 +0200 +++ b/src/share/vm/prims/unsafe.cpp Fri Apr 12 18:17:36 2013 +0200 @@ -116,7 +116,9 @@ inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { jlong byte_offset = field_offset_to_byte_offset(field_offset); // Don't allow unsafe to be used to read or write the header word of oops - assert(p == NULL || field_offset >= oopDesc::header_size(), "offset must be outside of header"); + // unless running GRAAL which wants to read the misc word for example when + // interpreting computeHashCode(). + assert(p == NULL || field_offset >= oopDesc::header_size() || GRAAL, "offset must be outside of header"); #ifdef ASSERT if (p != NULL) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");