# HG changeset patch # User Thomas Wuerthinger # Date 1372016655 -7200 # Node ID 0097fb11c16fa133d0434acc6ff34ae6f4e349ea # Parent 3e6f538829ce25efaf077543735136439b9e714e Add basic version of Graal's Truffle runtime. diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/InlinePrinterProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/InlinePrinterProcessor.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013, 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.truffle.printer; + +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.truffle.printer.method.*; + +public final class InlinePrinterProcessor { + + private static final String IDENT = " "; + private static InlinePrinterProcessor instance; + + private final List inlineTree = new ArrayList<>(); + + public static void initialize() { + if (instance == null) { + instance = new InlinePrinterProcessor(); + } else { + throw new IllegalStateException(); + } + } + + public static void addInlining(MethodHolder methodHolder) { + instance.addExecuteInline(methodHolder); + } + + public static void printTree() { + instance.print(); + } + + public static void reset() { + instance = null; + } + + private void addExecuteInline(MethodHolder executeMethod) { + if (inlineTree.isEmpty()) { + inlineTree.add(new TruffleMethodNode(null, executeMethod)); + } else { + TruffleMethodNode newNode = null; + for (TruffleMethodNode node : inlineTree) { + newNode = node.addTruffleExecuteMethodNode(executeMethod); + if (newNode != null) { + break; + } + } + if (newNode == null) { + throw new AssertionError("Not able to add " + executeMethod.getMethod().toString() + " to the inlineing tree"); + } + inlineTree.add(newNode); + } + } + + private TruffleMethodNode getInlineTree() { + TruffleMethodNode root = inlineTree.get(0); + while (root.getParent() != null) { + root = root.getParent(); + } + + // asserting: + for (TruffleMethodNode node : inlineTree) { + TruffleMethodNode nodeRoot = node; + while (nodeRoot.getParent() != null) { + nodeRoot = nodeRoot.getParent(); + } + if (root != nodeRoot) { + throw new AssertionError("Different roots found"); + } + } + + return root; + } + + private void print() { + String curIndent = ""; + TruffleMethodNode root = getInlineTree(); + String name = root.getJavaMethod().getDeclaringClass().getName(); + TTY.print(name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf(';')) + "::" + root.getJavaMethod().getName()); + TTY.println(); + recursivePrint(curIndent, root); + } + + private void recursivePrint(String curIdent, TruffleMethodNode node) { + Map> inlinings = node.getInlinings(); + for (int l : inlinings.keySet()) { + for (TruffleMethodNode n : inlinings.get(l)) { + TTY.print(curIdent); + TTY.print("L" + l + " "); + String name = n.getJavaMethod().getDeclaringClass().getName(); + TTY.print(name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf(';')) + "::" + n.getJavaMethod().getName()); + TTY.println(); + recursivePrint(curIdent + IDENT, n); + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/CallStackElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/CallStackElement.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, 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.truffle.printer.method; + +import com.oracle.graal.api.meta.*; + +public class CallStackElement { + + private final int lineOfInvoke; + private final ResolvedJavaMethod callerMethod; + + public CallStackElement(ResolvedJavaMethod callerMethod, int lineOfInvoke) { + this.lineOfInvoke = lineOfInvoke; + this.callerMethod = callerMethod; + } + + public int getLineOfInvoke() { + return lineOfInvoke; + } + + @Override + public boolean equals(Object o) { + if (o instanceof CallStackElement) { + CallStackElement i = (CallStackElement) o; + if (i.getCallerMethod() == this.getCallerMethod()/* + * && i.lineOfInvoke == + * this.lineOfInvoke + */) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + public ResolvedJavaMethod getCallerMethod() { + return callerMethod; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/MethodHolder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/MethodHolder.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, 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.truffle.printer.method; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +public final class MethodHolder { + + private final List callStack; + private final ResolvedJavaMethod method; + + public static MethodHolder getNewTruffleExecuteMethod(MethodCallTargetNode targetNode) { + return new MethodHolder(getCallStack(targetNode), targetNode.targetMethod()); + } + + private MethodHolder(List callStack, ResolvedJavaMethod callee) { + this.callStack = callStack; + this.method = callee; + } + + public List getCallStack() { + return callStack; + } + + public ResolvedJavaMethod getMethod() { + return method; + } + + private static List getCallStack(MethodCallTargetNode targetNode) { + List callStack = new ArrayList<>(); + FrameState state = targetNode.invoke().stateAfter(); + while (state != null) { + ResolvedJavaMethod method = state.method(); + LineNumberTable table = method.getLineNumberTable(); + int lineNr = table.getLineNumber(state.bci - 1); + callStack.add(new CallStackElement(method, lineNr)); + state = state.outerFrameState(); + } + return callStack; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/TruffleMethodNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/TruffleMethodNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013, 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.truffle.printer.method; + +import java.util.*; + +import com.oracle.graal.api.meta.*; + +public final class TruffleMethodNode { + + private final TruffleMethodNode parent; + private final MethodHolder truffleExecuteMethod; + private final Map> inlinings; + + public TruffleMethodNode(TruffleMethodNode parent, MethodHolder truffleExecuteMethod) { + this.parent = parent; + this.truffleExecuteMethod = truffleExecuteMethod; + this.inlinings = new HashMap<>(); + } + + public TruffleMethodNode getParent() { + return parent; + } + + public ResolvedJavaMethod getJavaMethod() { + return truffleExecuteMethod.getMethod(); + } + + public Map> getInlinings() { + return inlinings; + } + + public void putInlineList(int lineOfInvoke, List list) { + inlinings.put(lineOfInvoke, list); + } + + public List getInliningsAtLine(int line) { + return inlinings.get(line); + } + + public MethodHolder getTruffleExecuteMethod() { + return truffleExecuteMethod; + } + + public TruffleMethodNode addTruffleExecuteMethodNode(MethodHolder newMethod) { + int lineOfInvoke = newMethod.getCallStack().get(0).getLineOfInvoke(); + + if (!callStackMatch(newMethod.getCallStack())) { + return null; + } else { + TruffleMethodNode node = new TruffleMethodNode(this, newMethod); + if (getInliningsAtLine(lineOfInvoke) == null) { + List list = new ArrayList<>(); + list.add(node); + putInlineList(lineOfInvoke, list); + } else { + getInliningsAtLine(lineOfInvoke).add(node); + } + return node; + } + } + + private boolean callStackMatch(List callStack) { + List curCallStack = truffleExecuteMethod.getCallStack(); + if (curCallStack.size() == callStack.size() - 1) { + if (curCallStack.size() >= 1) { + if (curCallStack.get(0).getCallerMethod() != callStack.get(1).getCallerMethod()) { + return false; + } + } + for (int i = 1; i < curCallStack.size(); i++) { + if (!curCallStack.get(i).equals(callStack.get(i + 1))) { + return false; + } + } + } else { + return false; + } + return true; + } + +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, 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.truffle.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.truffle.test.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class AssumptionPartialEvaluationTest extends PartialEvaluationTest { + + public static Object constant42() { + return 42; + } + + @Test + public void constantValue() { + FrameDescriptor fd = new FrameDescriptor(); + Assumption assumption = Truffle.getRuntime().createAssumption(); + AbstractTestNode result = new ConstantWithAssumptionTestNode(assumption, 42); + RootTestNode rootNode = new RootTestNode("constantValue", result); + InstalledCode installedCode = assertPartialEvalEquals("constant42", rootNode, fd); + Assert.assertTrue(installedCode.isValid()); + try { + assertEquals(42, installedCode.execute(null, null, null)); + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code must not have been invalidated."); + } + Assert.assertTrue(installedCode.isValid()); + try { + assumption.check(); + } catch (InvalidAssumptionException e) { + Assert.fail("Assumption must not have been invalidated."); + } + assumption.invalidate(); + try { + assumption.check(); + Assert.fail("Assumption must have been invalidated."); + } catch (InvalidAssumptionException e) { + } + Assert.assertFalse(installedCode.isValid()); + + try { + installedCode.execute(null, null, null); + Assert.fail("Code must have been invalidated."); + } catch (InvalidInstalledCodeException e) { + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013, 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.truffle.test; + +import org.junit.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.substitutions.*; +import com.oracle.truffle.api.*; + +public class ExactMathTest extends GraalCompilerTest { + + private static boolean substitutionsInstalled; + + public ExactMathTest() { + if (!substitutionsInstalled) { + Graal.getRequiredCapability(Replacements.class).registerSubstitutions(ExactMathSubstitutions.class); + substitutionsInstalled = true; + } + } + + @Test + public void testAdd() { + test("add", 1, 2); + test("add", Integer.MAX_VALUE, 2); + } + + @Test + public void testMul() { + test("mul", 1, 2); + test("mul", Integer.MAX_VALUE, 2); + } + + @Test + public void testSub() { + test("sub", 1, 2); + test("sub", Integer.MIN_VALUE, 2); + } + + @Test + public void testLongAdd() { + test("longAdd", (long) Integer.MAX_VALUE, 2L); + test("longAdd", Long.MAX_VALUE, 2L); + } + + @Test + public void testLongMul() { + test("longMul", (long) Integer.MAX_VALUE, 2L); + test("longMul", (long) Integer.MIN_VALUE, 2L); + test("longMul", Long.MAX_VALUE, 2L); + } + + @Test + public void testLongSub() { + test("longSub", (long) Integer.MIN_VALUE, 2L); + test("longSub", Long.MIN_VALUE, 2L); + } + + public static int add(int a, int b) { + return ExactMath.addExact(a, b); + } + + public static int mul(int a, int b) { + return ExactMath.multiplyExact(a, b); + } + + public static int sub(int a, int b) { + return ExactMath.subtractExact(a, b); + } + + public static long longAdd(long a, long b) { + return ExactMath.addExact(a, b); + } + + public static long longMul(long a, long b) { + return ExactMath.multiplyExact(a, b); + } + + public static long longSub(long a, long b) { + return ExactMath.subtractExact(a, b); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013, 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.truffle.test; + +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.util.*; +import java.util.concurrent.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.*; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.Lowerable.LoweringType; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.printer.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.printer.*; +import com.oracle.graal.virtual.phases.ea.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class PartialEvaluationTest extends GraalCompilerTest { + + private static final long UNROLL_LIMIT = 100; + private final PartialEvaluator nodeCompiler; + + public PartialEvaluationTest() { + // Make sure Truffle runtime is initialized. + Assert.assertTrue(Truffle.getRuntime() instanceof GraalTruffleRuntime); + this.nodeCompiler = new PartialEvaluator(runtime, runtime); + + DebugEnvironment.initialize(System.out); + } + + protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, FrameDescriptor descriptor) { + return assertPartialEvalEquals(methodName, root, descriptor, Arguments.EMPTY_ARGUMENTS); + } + + protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, FrameDescriptor descriptor, Arguments arguments) { + Assumptions assumptions = new Assumptions(true); + StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true); + InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions); + StructuredGraph expected = parseForComparison(methodName); + removeFrameStates(actual); + Assert.assertEquals(getCanonicalGraphString(expected, true), getCanonicalGraphString(actual, true)); + return result; + } + + protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor) { + assertPartialEvalNoInvokes(root, descriptor, Arguments.EMPTY_ARGUMENTS); + } + + protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor, Arguments arguments) { + Assumptions assumptions = new Assumptions(true); + StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true); + removeFrameStates(actual); + for (MethodCallTargetNode node : actual.getNodes(MethodCallTargetNode.class)) { + Assert.fail("Found invalid method call target node: " + node); + } + } + + protected StructuredGraph partialEval(RootNode root, FrameDescriptor descriptor, Arguments arguments, final Assumptions assumptions, final boolean canonicalizeReads) { + final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root, descriptor); + + // Executed AST so that all classes are loaded and initialized. + do { + compilable.call(null, arguments); + compilable.call(null, arguments); + compilable.call(null, arguments); + } while (compilable.inline()); + + StructuredGraph graph = Debug.scope("Truffle", new DebugDumpScope("Truffle: " + compilable), new Callable() { + + @Override + public StructuredGraph call() { + StructuredGraph resultGraph = nodeCompiler.createGraph(compilable, assumptions); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(canonicalizeReads); + HighTierContext context = new HighTierContext(runtime, assumptions, replacements); + + if (resultGraph.hasLoops()) { + boolean unrolled; + do { + unrolled = false; + LoopsData loopsData = new LoopsData(resultGraph); + loopsData.detectedCountedLoops(); + for (LoopEx ex : innerLoopsFirst(loopsData.countedLoops())) { + if (ex.counted().isConstantMaxTripCount()) { + long constant = ex.counted().constantMaxTripCount(); + if (constant <= UNROLL_LIMIT) { + LoopTransformations.fullUnroll(ex, runtime, assumptions, canonicalizeReads); + Debug.dump(resultGraph, "After loop unrolling %d times", constant); + + canonicalizer.apply(resultGraph, context); + unrolled = true; + break; + } + } + } + } while (unrolled); + } + + new DeadCodeEliminationPhase().apply(resultGraph); + new PartialEscapePhase(true, canonicalizer).apply(resultGraph, context); + + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.printTree(); + } + + return resultGraph; + } + + private List innerLoopsFirst(Collection loops) { + ArrayList sortedLoops = new ArrayList<>(loops); + Collections.sort(sortedLoops, new Comparator() { + + @Override + public int compare(LoopEx o1, LoopEx o2) { + return o2.lirLoop().depth - o1.lirLoop().depth; + } + }); + return sortedLoops; + } + }); + + return graph; + } + + protected void removeFrameStates(StructuredGraph graph) { + for (FrameState frameState : graph.getNodes(FrameState.class)) { + frameState.replaceAtUsages(null); + frameState.safeDelete(); + } + new CanonicalizerPhase.Instance(runtime, new Assumptions(false), true).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + } + + protected StructuredGraph parseForComparison(final String methodName) { + + StructuredGraph graphResult = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName), new Callable() { + + public StructuredGraph call() { + Assumptions assumptions = new Assumptions(false); + StructuredGraph graph = parse(methodName); + CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(runtime, assumptions, true); + canonicalizerPhase.apply(graph); + + // Additional inlining. + final PhasePlan plan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), TruffleCompilerImpl.Optimizations); + plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase); + plan.addPhase(PhasePosition.AFTER_PARSING, new DeadCodeEliminationPhase()); + + new ConvertDeoptimizeToGuardPhase().apply(graph); + canonicalizerPhase.apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + InliningPhase inliningPhase = new InliningPhase(runtime, null, replacements, assumptions, null, plan, OptimisticOptimizations.NONE); + inliningPhase.apply(graph); + removeFrameStates(graph); + + new ConvertDeoptimizeToGuardPhase().apply(graph); + canonicalizerPhase.apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, new PhaseContext(runtime, assumptions, replacements)); + canonicalizerPhase.apply(graph); + new DeadCodeEliminationPhase().apply(graph); + return graph; + } + }); + return graphResult; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013, 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.truffle.test; + +import org.junit.*; + +import com.oracle.graal.truffle.test.nodes.*; +import com.oracle.truffle.api.frame.*; + +public class SimplePartialEvaluationTest extends PartialEvaluationTest { + + public static Object constant42() { + return 42; + } + + @Test + public void constantValue() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + assertPartialEvalEquals("constant42", new RootTestNode("constantValue", result), fd); + } + + @Test + public void addConstants() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new AddTestNode(new ConstantTestNode(40), new ConstantTestNode(2)); + assertPartialEvalEquals("constant42", new RootTestNode("addConstants", result), fd); + } + + @Test + public void sequenceConstants() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new ConstantTestNode(40), new ConstantTestNode(42)}); + assertPartialEvalEquals("constant42", new RootTestNode("sequenceConstants", result), fd); + } + + @Test + public void localVariable() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(42)), new LoadLocalTestNode("x", fd)}); + assertPartialEvalEquals("constant42", new RootTestNode("localVariable", result), fd); + } + + @Test + public void longSequenceConstants() { + FrameDescriptor fd = new FrameDescriptor(); + int length = 40; + AbstractTestNode[] children = new AbstractTestNode[length]; + for (int i = 0; i < children.length; ++i) { + children[i] = new ConstantTestNode(42); + } + + AbstractTestNode result = new BlockTestNode(children); + assertPartialEvalEquals("constant42", new RootTestNode("longSequenceConstants", result), fd); + } + + @Test + public void longAddConstants() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(2); + for (int i = 0; i < 20; ++i) { + result = new AddTestNode(result, new ConstantTestNode(2)); + } + assertPartialEvalEquals("constant42", new RootTestNode("longAddConstants", result), fd); + } + + @Test + public void mixLocalAndAdd() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(40)), + new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(2))), new LoadLocalTestNode("x", fd)}); + assertPartialEvalEquals("constant42", new RootTestNode("mixLocalAndAdd", result), fd); + } + + @Test + public void loop() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)), + new LoopTestNode(21, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(2))))}); + assertPartialEvalEquals("constant42", new RootTestNode("loop", result), fd); + } + + @Test + public void longLoop() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)), + new LoopTestNode(42, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(1))))}); + assertPartialEvalNoInvokes(new RootTestNode("loop", result), fd); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013, 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.truffle.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.truffle.*; +import com.oracle.truffle.api.*; + +public class TruffleRuntimeTest { + + @Test + public void testGraalCapabilities() { + assertNotNull(Graal.getRuntime().getCapability(MetaAccessProvider.class)); + } + + @Test + public void testRuntimeAvailable() { + assertNotNull(Truffle.getRuntime()); + } + + @Test + public void testRuntimeIsGraalRuntime() { + TruffleRuntime runtime = Truffle.getRuntime(); + assertEquals(GraalTruffleRuntime.class, runtime.getClass()); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public abstract class AbstractTestNode extends Node { + + public abstract int execute(VirtualFrame frame); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class AddTestNode extends AbstractTestNode { + + @Child private AbstractTestNode left; + @Child private AbstractTestNode right; + + public AddTestNode(AbstractTestNode left, AbstractTestNode right) { + this.left = adoptChild(left); + this.right = adoptChild(right); + } + + @Override + public int execute(VirtualFrame frame) { + return left.execute(frame) + right.execute(frame); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class BlockTestNode extends AbstractTestNode { + + @Children private final AbstractTestNode[] statements; + + public BlockTestNode(AbstractTestNode[] statements) { + this.statements = adoptChildren(statements); + } + + @ExplodeLoop + @Override + public int execute(VirtualFrame frame) { + int result = 0; + for (AbstractTestNode statement : statements) { + result = statement.execute(frame); + } + return result; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class ConstantTestNode extends AbstractTestNode { + + private final int value; + + public ConstantTestNode(int value) { + this.value = value; + } + + @Override + public int execute(VirtualFrame frame) { + return value; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class ConstantWithAssumptionTestNode extends AbstractTestNode { + + private final int value; + private final Assumption assumption; + + public ConstantWithAssumptionTestNode(Assumption assumption, int value) { + this.value = value; + this.assumption = assumption; + } + + @Override + public int execute(VirtualFrame frame) { + try { + assumption.check(); + return value; + } catch (InvalidAssumptionException e) { + return this.replace(new ConstantTestNode(value + 1)).execute(frame); + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoadLocalTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoadLocalTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class LoadLocalTestNode extends AbstractTestNode { + + private final FrameSlot slot; + + public LoadLocalTestNode(String name, FrameDescriptor frameDescriptor) { + slot = frameDescriptor.findOrAddFrameSlot(name); + } + + @Override + public int execute(VirtualFrame frame) { + try { + return frame.getInt(slot); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException(e); + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class LoopTestNode extends AbstractTestNode { + + private final int numberOfIterations; + @Child private AbstractTestNode child; + + public LoopTestNode(int numberOfIterations, AbstractTestNode child) { + this.numberOfIterations = numberOfIterations; + this.child = adoptChild(child); + } + + @Override + public int execute(VirtualFrame frame) { + int lastValue = 0; + for (int i = 0; i < numberOfIterations; ++i) { + lastValue = child.execute(frame); + } + return lastValue; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class RootTestNode extends RootNode { + + private final String name; + @Child AbstractTestNode node; + + public RootTestNode(String name, AbstractTestNode node) { + this.name = name; + this.node = node; + } + + @Override + public Object execute(VirtualFrame frame) { + return node.execute(frame); + } + + @Override + public String toString() { + return name; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class StoreLocalTestNode extends AbstractTestNode { + + private final FrameSlot slot; + + @Child private AbstractTestNode valueNode; + + public StoreLocalTestNode(String name, FrameDescriptor frameDescriptor, AbstractTestNode valueNode) { + this.slot = frameDescriptor.findOrAddFrameSlot(name); + this.valueNode = valueNode; + } + + @Override + public int execute(VirtualFrame frame) { + int value = valueNode.execute(frame); + try { + frame.setInt(slot, value); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException(e); + } + return value; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/TestNodeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/TestNodeFactory.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013, 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.truffle.test.nodes; + +public class TestNodeFactory { + + public AbstractTestNode createConstant(int value) { + return new ConstantTestNode(value); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import java.util.*; + +import sun.misc.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * More efficient implementation of the Truffle frame that has no safety checks for frame accesses + * and therefore is much faster. Should not be used during debugging as potential misuses of the + * frame object would show up very late and would be hard to identify. + */ +public final class FrameWithoutBoxing implements VirtualFrame, MaterializedFrame, PackedFrame { + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + private final FrameDescriptor descriptor; + private final PackedFrame caller; + private final Arguments arguments; + private Object[] locals; + private long[] primitiveLocals; + private byte[] tags; + + public FrameWithoutBoxing(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { + this.descriptor = descriptor; + this.caller = caller; + this.arguments = arguments; + this.locals = new Object[descriptor.getSize()]; + this.primitiveLocals = new long[descriptor.getSize()]; + this.tags = new byte[descriptor.getSize()]; + } + + @SuppressWarnings("unchecked") + @Override + public T getArguments(Class clazz) { + return (T) unsafeCast(arguments, clazz); + } + + private static Object unsafeCast(Object value, @SuppressWarnings("unused") Class clazz) { + return value; + } + + @Override + public PackedFrame getCaller() { + return caller; + } + + @Override + public PackedFrame pack() { + return this; + } + + @Override + public MaterializedFrame materialize() { + return this; + } + + @Override + public VirtualFrame unpack() { + return this; + } + + @Override + public Object getObject(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Object); + return getObjectUnsafe(slot); + } + + private Object getObjectUnsafe(FrameSlot slot) { + return unsafe.getObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET); + } + + @Override + public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Object); + setObjectUnsafe(slot, value); + } + + private void setObjectUnsafe(FrameSlot slot, Object value) { + unsafe.putObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, value); + } + + @Override + public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Boolean); + return getBooleanUnsafe(slot); + } + + private boolean getBooleanUnsafe(FrameSlot slot) { + return unsafe.getBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Boolean); + setBooleanUnsafe(slot, value); + } + + private void setBooleanUnsafe(FrameSlot slot, boolean value) { + unsafe.putBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public float getFloat(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Float); + return getFloatUnsafe(slot); + } + + private float getFloatUnsafe(FrameSlot slot) { + return unsafe.getFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Float); + setFloatUnsafe(slot, value); + } + + private void setFloatUnsafe(FrameSlot slot, float value) { + unsafe.putFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public long getLong(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Long); + return getLongUnsafe(slot); + } + + private long getLongUnsafe(FrameSlot slot) { + return unsafe.getLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Long); + setLongUnsafe(slot, value); + } + + private void setLongUnsafe(FrameSlot slot, long value) { + unsafe.putLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public int getInt(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Int); + return getIntUnsafe(slot); + } + + private int getIntUnsafe(FrameSlot slot) { + return unsafe.getInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Int); + setIntUnsafe(slot, value); + } + + private void setIntUnsafe(FrameSlot slot, int value) { + unsafe.putInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public double getDouble(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Double); + return getDoubleUnsafe(slot); + } + + private double getDoubleUnsafe(FrameSlot slot) { + return unsafe.getDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Double); + setDoubleUnsafe(slot, value); + } + + private void setDoubleUnsafe(FrameSlot slot, double value) { + unsafe.putDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public FrameDescriptor getFrameDescriptor() { + return this.descriptor; + } + + private void verifySet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { + FrameSlotKind slotKind = slot.getKind(); + if (slotKind != accessKind) { + if (slotKind == FrameSlotKind.Illegal) { + slot.setKind(accessKind); + } else { + throw new FrameSlotTypeException(); + } + } + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { + resize(); + } + tags[slotIndex] = (byte) accessKind.ordinal(); + } + + private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { + FrameSlotKind slotKind = slot.getKind(); + if (slotKind != accessKind) { + if (slotKind == FrameSlotKind.Illegal && accessKind == FrameSlotKind.Object) { + slot.setKind(FrameSlotKind.Object); + this.setObject(slot, descriptor.getTypeConversion().getDefaultValue()); + } else { + throw new FrameSlotTypeException(); + } + } + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { + resize(); + } + if (tags[slotIndex] != accessKind.ordinal()) { + descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot)); + if (tags[slotIndex] != accessKind.ordinal()) { + throw new FrameSlotTypeException(); + } + } + } + + @Override + public Object getValue(FrameSlot slot) { + int index = slot.getIndex(); + if (index >= tags.length) { + assert index >= 0 && index < descriptor.getSize(); + return descriptor.getTypeConversion().getDefaultValue(); + } + byte tag = tags[index]; + if (tag == FrameSlotKind.Illegal.ordinal()) { + return descriptor.getTypeConversion().getDefaultValue(); + } else if (tag == FrameSlotKind.Boolean.ordinal()) { + return getBooleanUnsafe(slot); + } else if (tag == FrameSlotKind.Int.ordinal()) { + return getIntUnsafe(slot); + } else if (tag == FrameSlotKind.Double.ordinal()) { + return getDoubleUnsafe(slot); + } else if (tag == FrameSlotKind.Long.ordinal()) { + return getLongUnsafe(slot); + } else if (tag == FrameSlotKind.Float.ordinal()) { + return getFloatUnsafe(slot); + } else { + return getObjectUnsafe(slot); + } + } + + private void resize() { + int newSize = descriptor.getSize(); + if (newSize > tags.length) { + locals = Arrays.copyOf(locals, newSize); + primitiveLocals = Arrays.copyOf(primitiveLocals, newSize); + tags = Arrays.copyOf(tags, newSize); + } + } + + @Override + public boolean isInitialized(FrameSlot slot) { + return !(this.tags[slot.getIndex()] == FrameSlotKind.Illegal.ordinal()); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.util.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.substitutions.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Implementation of the Truffle runtime when running on top of Graal. + */ +public final class GraalTruffleRuntime implements TruffleRuntime { + + public static GraalTruffleRuntime makeInstance() { + return new GraalTruffleRuntime(); + } + + private TruffleCompiler truffleCompiler; + private ArrayList includes; + private ArrayList excludes; + + private GraalTruffleRuntime() { + Replacements replacements = Graal.getRequiredCapability(Replacements.class); + replacements.registerSubstitutions(CompilerAssertsSubstitutions.class); + replacements.registerSubstitutions(CompilerDirectivesSubstitutions.class); + replacements.registerSubstitutions(ExactMathSubstitutions.class); + replacements.registerSubstitutions(UnexpectedResultExceptionSubstitutions.class); + replacements.registerSubstitutions(SlowPathExceptionSubstitutions.class); + replacements.registerSubstitutions(FrameWithoutBoxingSubstitutions.class); + replacements.registerSubstitutions(OptimizedAssumptionSubstitutions.class); + replacements.registerSubstitutions(OptimizedCallTargetSubstitutions.class); + replacements.registerSubstitutions(DefaultCallTargetSubstitutions.class); + } + + public String getName() { + return "Graal Truffle Runtime"; + } + + public CallTarget createCallTarget(RootNode rootNode) { + return createCallTarget(rootNode, new FrameDescriptor()); + } + + @Override + public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) { + if (!acceptForCompilation(rootNode)) { + return new DefaultCallTarget(rootNode, frameDescriptor); + } + if (truffleCompiler == null) { + truffleCompiler = new TruffleCompilerImpl(); + } + return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue(), TruffleInliningReprofileCount.getValue(), + TruffleInvalidationReprofileCount.getValue()); + } + + @Override + public MaterializedFrame createMaterializedFrame(Arguments arguments) { + return createMaterializedFrame(arguments); + } + + @Override + public MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor) { + return new FrameWithoutBoxing(frameDescriptor, null, arguments); + } + + @Override + public Assumption createAssumption() { + return createAssumption(null); + } + + @Override + public Assumption createAssumption(String name) { + return new OptimizedAssumption(name); + } + + private boolean acceptForCompilation(RootNode rootNode) { + if (TruffleCompileOnly.getValue() != null) { + if (includes == null) { + parseCompileOnly(); + } + + String name = rootNode.toString(); + boolean included = includes.isEmpty(); + for (int i = 0; !included && i < includes.size(); i++) { + if (name.contains(includes.get(i))) { + included = true; + } + } + if (!included) { + return false; + } + for (String exclude : excludes) { + if (name.contains(exclude)) { + return false; + } + } + } + return true; + } + + private void parseCompileOnly() { + includes = new ArrayList<>(); + excludes = new ArrayList<>(); + + String[] items = TruffleCompileOnly.getValue().split(","); + for (String item : items) { + if (item.startsWith("~")) { + excludes.add(item.substring(1)); + } else { + includes.add(item); + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import java.lang.ref.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.nodes.*; + +public final class OptimizedAssumption extends AbstractAssumption { + + List> dependentInstalledCode; + + public OptimizedAssumption(String name) { + super(name); + } + + @Override + public void check() throws InvalidAssumptionException { + if (!isValid) { + throw new InvalidAssumptionException(); + } + } + + @Override + public synchronized void invalidate() { + if (isValid) { + if (dependentInstalledCode != null) { + for (WeakReference installedCodeReference : dependentInstalledCode) { + InstalledCode installedCode = installedCodeReference.get(); + if (installedCode != null) { + installedCode.invalidate(); + } + } + dependentInstalledCode = null; + } + isValid = false; + } + } + + public synchronized void registerInstalledCode(InstalledCode installedCode) { + if (isValid) { + if (dependentInstalledCode == null) { + dependentInstalledCode = new ArrayList<>(); + } + dependentInstalledCode.add(new WeakReference<>(installedCode)); + } else { + installedCode.invalidate(); + } + } + + @Override + public boolean isValid() { + return isValid; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Call target that is optimized by Graal upon surpassing a specific invocation threshold. + */ +public final class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, FrameFactory { + + private static final PrintStream OUT = TTY.out().out(); + + private final int inliningReprofileCount; + private final int invalidationReprofileCount; + + protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold, int inliningReprofileCount, int invalidationReprofileCount) { + super(rootNode, descriptor); + this.compiler = compiler; + this.invokeCounter = compilationThreshold >> 7; + this.loopAndInvokeCounter = compilationThreshold; + this.originalInvokeCounter = compilationThreshold; + this.rootNode.setCallTarget(this); + this.inliningReprofileCount = inliningReprofileCount; + this.invalidationReprofileCount = invalidationReprofileCount; + } + + private InstalledCode compiledMethod; + private final TruffleCompiler compiler; + private int invokeCounter; + private int originalInvokeCounter; + private int loopAndInvokeCounter; + private boolean disableCompilation; + + long timeCompilationStarted; + long timePartialEvaluationFinished; + long timeCompilationFinished; + int codeSize; + + @Override + public Object call(PackedFrame caller, Arguments args) { + for (;;) { + if (compiledMethod != null) { + try { + return compiledMethod.execute(this, caller, args); + } catch (InvalidInstalledCodeException ex) { + compiledMethod = null; + invokeCounter = invalidationReprofileCount; + if (TruffleFunctionInlining.getValue()) { + originalInvokeCounter += invalidationReprofileCount; + } + if (TraceTruffleCompilation.getValue()) { + OUT.printf("[truffle] invalidated %-48s |Alive %4.0fms\n", rootNode, (System.nanoTime() - timeCompilationFinished) / 1e6); + } + } + } else { + invokeCounter--; + loopAndInvokeCounter--; + if (disableCompilation || loopAndInvokeCounter > 0 || invokeCounter > 0) { + return executeHelper(caller, args); + } else { + if (TruffleFunctionInlining.getValue()) { + if (inline()) { + invokeCounter = 2; + loopAndInvokeCounter = inliningReprofileCount; + originalInvokeCounter = inliningReprofileCount; + } else { + compile(); + } + } else { + compile(); + } + } + } + } + } + + public boolean inline() { + return new InliningHelper(this).inline(); + } + + public void compile() { + try { + compiledMethod = compiler.compile(this); + if (compiledMethod == null) { + throw new BailoutException(String.format("code installation failed (codeSize=%s)", codeSize)); + } else { + if (TraceTruffleCompilation.getValue()) { + OUT.printf("[truffle] optimized %-50s |Total %5.0fms |PE %4.0fms |Graal %4.0fms |CodeSize %d\n", rootNode, (timeCompilationFinished - timeCompilationStarted) / 1e6, + (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, codeSize); + } + } + } catch (Throwable e) { + invokeCounter = Integer.MAX_VALUE; + loopAndInvokeCounter = Integer.MAX_VALUE; + if (TraceTruffleCompilation.getValue()) { + if (e instanceof BailoutException) { + disableCompilation = true; + BailoutException bailoutException = (BailoutException) e; + OUT.printf("[truffle] opt bailout %-48s %s\n", rootNode, bailoutException.getMessage()); + } else { + OUT.printf("[truffle] opt failed %-49s %s\n", rootNode, e.toString()); + if (TraceTruffleCompilationExceptions.getValue()) { + e.printStackTrace(OUT); + } + if (TruffleCompilationExceptionsAreFatal.getValue()) { + System.exit(-1); + } + } + } + } + } + + public Object executeHelper(PackedFrame caller, Arguments args) { + VirtualFrame frame = createFrame(frameDescriptor, caller, args); + return rootNode.execute(frame); + } + + private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return new FrameWithoutBoxing(descriptor, caller, args); + } + + @Override + public VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return createFrame(descriptor, caller, args); + } + + @Override + public String toString() { + return "CallTarget " + rootNode; + } + + @Override + public void reportLoopCount(int count) { + loopAndInvokeCounter -= count; + } + + private class InliningHelper { + + private static final int MAX_SIZE = 300; + private static final int MAX_INLINE_SIZE = 62; + + private final OptimizedCallTarget target; + + public InliningHelper(OptimizedCallTarget target) { + this.target = target; + } + + public boolean inline() { + CallTargetProfile profile = new CallTargetProfile(target.getRootNode()); + + if (profile.inlinableCallSites.isEmpty()) { + return false; + } + + if (profile.nodeCount > MAX_SIZE) { + return false; + } + + double max = 0.0D; + ProfiledInlinableCallSite inliningDecision = null; + for (Node callNode : profile.inlinableCallSites) { + InlinableCallSite callSite = (InlinableCallSite) callNode; + Node inlineTree = callSite.getInlineTree(); + if (inlineTree == null) { + continue; + } + CallTargetProfile inlineProfile = new CallTargetProfile(inlineTree); + if (inlineProfile.nodeCount > MAX_INLINE_SIZE || inlineProfile.nodeCount + profile.nodeCount > MAX_SIZE) { + continue; + } + + ProfiledInlinableCallSite inlinable = new ProfiledInlinableCallSite(inlineProfile, callSite); + double metric = (inlinable.callCount / inlineProfile.nodeCount) + ((double) inlinable.callCount / (double) originalInvokeCounter); + if (metric >= max) { + inliningDecision = inlinable; + max = metric; + } + } + + for (Node callSite : profile.inlinableCallSites) { + ((InlinableCallSite) callSite).resetCallCount(); + } + + if (inliningDecision != null) { + if (inliningDecision.callSite.inline(target)) { + if (TraceTruffleCompilation.getValue()) { + + String calls = String.format("%4s/%4s", inliningDecision.callCount, originalInvokeCounter); + String nodes = String.format("%3s/%3s", inliningDecision.profile.nodeCount, profile.nodeCount); + + OUT.printf("[truffle] inlined %-50s |Nodes %6s |Calls %6s |into %s\n", inliningDecision.callSite, nodes, calls, target.getRootNode()); + } + return true; + } + } + return false; + } + + private class ProfiledInlinableCallSite { + + final CallTargetProfile profile; + final InlinableCallSite callSite; + final int callCount; + + public ProfiledInlinableCallSite(CallTargetProfile profile, InlinableCallSite callSite) { + this.profile = profile; + this.callSite = callSite; + this.callCount = callSite.getCallCount(); + } + + } + + private class CallTargetProfile { + + final Node root; + final int nodeCount; + final List inlinableCallSites = new ArrayList<>(); + + public CallTargetProfile(Node rootNode) { + root = rootNode; + + VisitorImpl impl = new VisitorImpl(); + root.accept(impl); + + this.nodeCount = impl.visitedCount; + } + + private class VisitorImpl implements NodeVisitor { + + int visitedCount; + + @Override + public boolean visit(Node node) { + if (node instanceof RootNode && node != root) { + return false; + } + + if (node instanceof InlinableCallSite) { + inlinableCallSites.add(node); + } + visitedCount++; + return true; + } + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PackedFrameImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PackedFrameImpl.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import com.oracle.truffle.api.frame.*; + +/** + * Implementation of a packed frame that contains only a raw pointer to the native stack. This + * packed frame is only handed out by Truffle compiled methods. + * + */ +public class PackedFrameImpl implements PackedFrame { + + private long stackPointer; + + @Override + public VirtualFrame unpack() { + return unpackNative(); + } + + private native VirtualFrame unpackNative(); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import static com.oracle.graal.compiler.GraalDebugConfig.*; +import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.java.*; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.graal.truffle.nodes.NewFrameNode.VirtualOnlyInstanceNode; +import com.oracle.graal.truffle.phases.*; +import com.oracle.graal.truffle.printer.*; +import com.oracle.graal.truffle.printer.method.*; +import com.oracle.graal.virtual.phases.ea.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Class performing the partial evaluation starting from the root node of an AST. + */ +public class PartialEvaluator { + + private final MetaAccessProvider metaAccessProvider; + private final ResolvedJavaType nodeClass; + private final ResolvedJavaMethod executeHelperMethod; + private final CustomCanonicalizer customCanonicalizer; + private final ResolvedJavaType[] skippedExceptionTypes; + private final Replacements replacements; + private Set constantReceivers; + private final HotSpotGraphCache cache; + + public PartialEvaluator(GraalCodeCacheProvider runtime, MetaAccessProvider metaAccessProvider) { + this.metaAccessProvider = metaAccessProvider; + this.nodeClass = runtime.lookupJavaType(com.oracle.truffle.api.nodes.Node.class); + this.customCanonicalizer = new PartialEvaluatorCanonicalizer(runtime, nodeClass); + this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(metaAccessProvider); + this.replacements = Graal.getRequiredCapability(Replacements.class); + this.cache = HotSpotGraalRuntime.graalRuntime().getCache(); + + try { + executeHelperMethod = runtime.lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("executeHelper", PackedFrame.class, Arguments.class)); + } catch (NoSuchMethodException ex) { + throw new RuntimeException(ex); + } + } + + public StructuredGraph createGraph(final OptimizedCallTarget node, final Assumptions assumptions) { + if (Dump.getValue() != null && Dump.getValue().contains("Truffle")) { + RootNode root = node.getRootNode(); + if (root != null) { + new GraphPrintVisitor().beginGroup("TruffleGraph").beginGraph(node.toString()).visit(root).printToNetwork(); + } + } + + if (TraceTruffleCompilationDetails.getValue()) { + constantReceivers = new HashSet<>(); + } + + final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); + config.setSkippedExceptionTypes(skippedExceptionTypes); + + final StructuredGraph graph = new StructuredGraph(executeHelperMethod); + + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.initialize(); + } + + Debug.scope("createGraph", graph, new Runnable() { + + @Override + public void run() { + new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph); + + // Replace thisNode with constant. + LocalNode thisNode = graph.getLocal(0); + thisNode.replaceAndDelete(ConstantNode.forObject(node, metaAccessProvider, graph)); + + // Canonicalize / constant propagate. + CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), null, customCanonicalizer); + canonicalizerPhase.apply(graph); + + // Intrinsify methods. + new ReplaceIntrinsicsPhase(replacements).apply(graph); + + NewFrameNode newFrameNode = graph.getNodes(NewFrameNode.class).first(); + if (newFrameNode == null) { + throw GraalInternalError.shouldNotReachHere("frame not found"); + } + + Debug.dump(graph, "Before inlining"); + + // Make sure frame does not escape. + expandTree(config, graph, newFrameNode, assumptions); + + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.printTree(); + InlinePrinterProcessor.reset(); + } + + if (TraceTruffleCompilationDetails.getValue() && constantReceivers != null) { + DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes"); + for (Constant c : constantReceivers) { + histogram.add(c.asObject().getClass().getSimpleName()); + } + histogram.print(TTY.out().out()); + } + + // Additional inlining. + final PhasePlan plan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations); + plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase); + plan.addPhase(PhasePosition.AFTER_PARSING, new ReplaceIntrinsicsPhase(replacements)); + + new ConvertDeoptimizeToGuardPhase().apply(graph); + canonicalizerPhase.apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + InliningPhase inliningPhase = new InliningPhase(metaAccessProvider, null, replacements, assumptions, cache, plan, OptimisticOptimizations.NONE); + inliningPhase.setCustomCanonicalizer(customCanonicalizer); + inliningPhase.apply(graph); + + // Convert deopt to guards. + new ConvertDeoptimizeToGuardPhase().apply(graph); + + // Canonicalize / constant propagate. + canonicalizerPhase.apply(graph); + + for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) { + Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage()); + throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception); + } + + // EA frame and clean up. + new VerifyFrameDoesNotEscapePhase().apply(graph, false); + new PartialEscapePhase(false, new CanonicalizerPhase(!AOTCompilation.getValue())).apply(graph, new HighTierContext(metaAccessProvider, assumptions, replacements)); + new VerifyNoIntrinsicsLeftPhase().apply(graph, false); + for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { + materializeNode.replaceAtUsages(materializeNode.getFrame()); + graph.removeFixed(materializeNode); + } + for (VirtualOnlyInstanceNode virtualOnlyNode : graph.getNodes(VirtualOnlyInstanceNode.class)) { + virtualOnlyNode.setAllowMaterialization(true); + } + + // Convert deopt to guards. + new ConvertDeoptimizeToGuardPhase().apply(graph); + + // Canonicalize / constant propagate. + canonicalizerPhase.apply(graph); + } + }); + + return graph; + } + + private void expandTree(GraphBuilderConfiguration config, StructuredGraph graph, NewFrameNode newFrameNode, Assumptions assumptions) { + for (Node usage : newFrameNode.usages().snapshot()) { + if (usage instanceof MethodCallTargetNode && !usage.isDeleted()) { + MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) usage; + InvokeKind kind = methodCallTargetNode.invokeKind(); + if (kind == InvokeKind.Special || kind == InvokeKind.Static) { + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.addInlining(MethodHolder.getNewTruffleExecuteMethod(methodCallTargetNode)); + } + if (TraceTruffleCompilationDetails.getValue() && kind == InvokeKind.Special && methodCallTargetNode.arguments().first() instanceof ConstantNode) { + ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first(); + constantReceivers.add(constantNode.asConstant()); + } + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); + NewFrameNode otherNewFrame = null; + if (inlineGraph == null) { + inlineGraph = parseGraph(config, methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, !AOTCompilation.getValue()); + otherNewFrame = inlineGraph.getNodes(NewFrameNode.class).first(); + } + int mark = graph.getMark(); + Map mapping = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false); + if (Debug.isDumpEnabled()) { + Debug.dump(graph, "After inlining %s +%d (%d)", methodCallTargetNode.targetMethod().toString(), graph.getNewNodes(mark).count(), graph.getNodeCount()); + } + + if (newFrameNode.isAlive() && newFrameNode.usages().isNotEmpty()) { + expandTree(config, graph, newFrameNode, assumptions); + } + + if (otherNewFrame != null) { + otherNewFrame = (NewFrameNode) mapping.get(otherNewFrame); + if (otherNewFrame.isAlive() && otherNewFrame.usages().isNotEmpty()) { + expandTree(config, graph, otherNewFrame, assumptions); + } + } + } + } + } + } + + private StructuredGraph parseGraph(final GraphBuilderConfiguration config, final ResolvedJavaMethod targetMethod, final NodeInputList arguments, final Assumptions assumptions, + final boolean canonicalizeReads) { + + final StructuredGraph graph = new StructuredGraph(targetMethod); + Debug.scope("parseGraph", targetMethod, new Runnable() { + + @Override + public void run() { + new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph); + // Pass on constant arguments. + for (LocalNode local : graph.getNodes(LocalNode.class)) { + ValueNode arg = arguments.get(local.index()); + if (arg instanceof NewFrameNode) { + local.setStamp(arg.stamp()); + } else if (arg.isConstant()) { + Constant constant = arg.asConstant(); + local.replaceAndDelete(ConstantNode.forConstant(constant, metaAccessProvider, graph)); + } + } + + // Canonicalize / constant propagate. + new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph); + + // Intrinsify methods. + new ReplaceIntrinsicsPhase(replacements).apply(graph); + + // Inline trivial getter methods + new InlineTrivialGettersPhase(metaAccessProvider, assumptions, customCanonicalizer).apply(graph); + + // Convert deopt to guards. + new ConvertDeoptimizeToGuardPhase().apply(graph); + + if (graph.hasLoops()) { + boolean unrolled; + do { + unrolled = false; + LoopsData loopsData = new LoopsData(graph); + loopsData.detectedCountedLoops(); + for (LoopEx ex : innerLoopsFirst(loopsData.countedLoops())) { + if (ex.counted().isConstantMaxTripCount()) { + long constant = ex.counted().constantMaxTripCount(); + if (constant <= TruffleConstantUnrollLimit.getValue() || targetMethod.getAnnotation(ExplodeLoop.class) != null) { + LoopTransformations.fullUnroll(ex, metaAccessProvider, assumptions, canonicalizeReads); + Debug.dump(graph, "After loop unrolling %d times", constant); + new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph); + unrolled = true; + break; + } + } + } + } while (unrolled); + } + } + + private List innerLoopsFirst(Collection loops) { + ArrayList sortedLoops = new ArrayList<>(loops); + Collections.sort(sortedLoops, new Comparator() { + + @Override + public int compare(LoopEx o1, LoopEx o2) { + return o2.lirLoop().depth - o1.lirLoop().depth; + } + }); + return sortedLoops; + } + }); + + return graph; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.phases.common.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.Node.Child; + +final class PartialEvaluatorCanonicalizer implements CanonicalizerPhase.CustomCanonicalizer { + + private final MetaAccessProvider runtime; + private final ResolvedJavaType nodeClass; + + PartialEvaluatorCanonicalizer(MetaAccessProvider runtime, ResolvedJavaType nodeClass) { + this.runtime = runtime; + this.nodeClass = nodeClass; + } + + @Override + public ValueNode canonicalize(ValueNode node) { + if (node instanceof LoadFieldNode) { + LoadFieldNode loadFieldNode = (LoadFieldNode) node; + if (!loadFieldNode.isStatic() && + loadFieldNode.object().isConstant() && + !loadFieldNode.object().isNullConstant() && + ((loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || Modifier.isFinal(loadFieldNode.field().getModifiers()) || loadFieldNode.field().getAnnotation( + CompilerDirectives.CompilationFinal.class) != null)) { + Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); + return ConstantNode.forConstant(constant, this.runtime, node.graph()); + } + } else if (node instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node; + Stamp stamp = loadIndexedNode.array().stamp(); + if (stamp.kind() == Kind.Object && loadIndexedNode.array().isConstant() && !loadIndexedNode.array().isNullConstant() && loadIndexedNode.index().isConstant()) { + ObjectStamp objectStamp = (ObjectStamp) stamp; + ResolvedJavaType type = objectStamp.type(); + if (type != null && type.isArray() && this.nodeClass.isAssignableFrom(type.getComponentType())) { + Object array = loadIndexedNode.array().asConstant().asObject(); + int index = loadIndexedNode.index().asConstant().asInt(); + Object value = Array.get(array, index); + return ConstantNode.forObject(value, this.runtime, node.graph()); + } + } + } else if (node instanceof UnsafeLoadNode) { + UnsafeLoadNode unsafeLoadNode = (UnsafeLoadNode) node; + if (unsafeLoadNode.offset().isConstant()) { + long offset = unsafeLoadNode.offset().asConstant().asLong() + unsafeLoadNode.displacement(); + ResolvedJavaType type = unsafeLoadNode.object().objectStamp().type(); + ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset); + if (field != null) { + return node.graph().add(new LoadFieldNode(unsafeLoadNode.object(), field)); + } + } + } else if (node instanceof UnsafeStoreNode) { + UnsafeStoreNode unsafeStoreNode = (UnsafeStoreNode) node; + if (unsafeStoreNode.offset().isConstant()) { + long offset = unsafeStoreNode.offset().asConstant().asLong() + unsafeStoreNode.displacement(); + ResolvedJavaType type = unsafeStoreNode.object().objectStamp().type(); + ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset); + if (field != null) { + StoreFieldNode storeFieldNode = node.graph().add(new StoreFieldNode(unsafeStoreNode.object(), field, unsafeStoreNode.value())); + storeFieldNode.setStateAfter(unsafeStoreNode.stateAfter()); + return storeFieldNode; + } + } + } + + return node; + } + + private ResolvedJavaField recursiveFindFieldWithOffset(ResolvedJavaType type, long offset) { + if (type != null) { + ResolvedJavaField field = type.findInstanceFieldWithOffset(offset); + if (field != null) { + return field; + } + return recursiveFindFieldWithOffset(type.getSuperclass(), offset); + } + return null; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import com.oracle.graal.api.code.*; + +/** + * Interface of the Truffle compiler producing an {@link InstalledCode} object from the partial + * evaluation starting with the AST represented by the given {@link OptimizedCallTarget} node. + */ +public interface TruffleCompiler { + + InstalledCode compile(OptimizedCallTarget node); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import static com.oracle.graal.api.code.CodeUtil.*; +import static com.oracle.graal.compiler.GraalDebugConfig.*; + +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Assumptions.Assumption; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.printer.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Implementation of the Truffle compiler using Graal. + */ +public class TruffleCompilerImpl implements TruffleCompiler { + + private final GraalCodeCacheProvider runtime; + private final Suites suites; + private final PartialEvaluator nodeCompiler; + private final MetaAccessProvider metaAccessProvider; + private final Replacements replacements; + private final Backend backend; + private final ResolvedJavaType[] skippedExceptionTypes; + private final HotSpotGraalRuntime graalRuntime; + + private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class}; + + public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability, + OptimisticOptimizations.Optimization.RemoveNeverExecutedCode); + + public TruffleCompilerImpl() { + this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); + this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites(); + this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class); + this.backend = Graal.getRequiredCapability(Backend.class); + this.replacements = Graal.getRequiredCapability(Replacements.class); + this.graalRuntime = HotSpotGraalRuntime.graalRuntime(); + + this.nodeCompiler = new PartialEvaluator(runtime, metaAccessProvider); + this.skippedExceptionTypes = getSkippedExceptionTypes(metaAccessProvider); + + if (DebugEnabled.getValue()) { + DebugEnvironment.initialize(System.out); + } + } + + static ResolvedJavaType[] getSkippedExceptionTypes(MetaAccessProvider metaAccessProvider) { + ResolvedJavaType[] skippedExceptionTypes = new ResolvedJavaType[SKIPPED_EXCEPTION_CLASSES.length]; + for (int i = 0; i < SKIPPED_EXCEPTION_CLASSES.length; i++) { + skippedExceptionTypes[i] = metaAccessProvider.lookupJavaType(SKIPPED_EXCEPTION_CLASSES[i]); + } + return skippedExceptionTypes; + } + + public InstalledCode compile(final OptimizedCallTarget compilable) { + Object[] debug = new Object[]{new DebugDumpScope("Truffle: " + compilable)}; + return Debug.scope("Truffle", debug, new Callable() { + + @Override + public InstalledCode call() throws Exception { + return compileMethodImpl(compilable); + } + }); + } + + private InstalledCode compileMethodImpl(final OptimizedCallTarget compilable) { + final StructuredGraph graph; + final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); + config.setSkippedExceptionTypes(skippedExceptionTypes); + graalRuntime.evictDeoptedGraphs(); + + compilable.timeCompilationStarted = System.nanoTime(); + Assumptions assumptions = new Assumptions(true); + graph = nodeCompiler.createGraph(compilable, assumptions); + compilable.timePartialEvaluationFinished = System.nanoTime(); + InstalledCode compiledMethod = compileMethodHelper(graph, config, compilable, assumptions); + compilable.timeCompilationFinished = System.nanoTime(); + return compiledMethod; + } + + public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final Assumptions assumptions) { + return compileMethodHelper(graph, config, null, assumptions); + } + + public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final OptimizedCallTarget compilable, final Assumptions assumptions) { + final PhasePlan plan = createPhasePlan(config); + + Debug.scope("TruffleFinal", graph, new Runnable() { + + @Override + public void run() { + Debug.dump(graph, "After TruffleTier"); + } + }); + + final Graph graphCopy = graph.copy(); + + final CompilationResult result = Debug.scope("TruffleGraal", new Callable() { + + @Override + public CompilationResult call() { + CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false); + return GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, plan, OptimisticOptimizations.ALL, new SpeculationLog(), suites); + } + }); + + List validAssumptions = new ArrayList<>(); + Assumptions newAssumptions = new Assumptions(true); + if (assumptions != null) { + for (Assumption assumption : assumptions.getAssumptions()) { + processAssumption(newAssumptions, assumption, validAssumptions); + } + } + + if (result.getAssumptions() != null) { + for (Assumption assumption : result.getAssumptions().getAssumptions()) { + processAssumption(newAssumptions, assumption, validAssumptions); + } + } + + result.setAssumptions(newAssumptions); + + InstalledCode compiledMethod = Debug.scope("CodeInstall", new Object[]{graph.method()}, new Callable() { + + @Override + public InstalledCode call() throws Exception { + InstalledCode installedCode = runtime.addMethod(graph.method(), result, graphCopy); + if (installedCode != null) { + Debug.dump(new Object[]{result, installedCode}, "After code installation"); + } + return installedCode; + } + }); + + for (AssumptionValidAssumption a : validAssumptions) { + a.getAssumption().registerInstalledCode(compiledMethod); + } + + if (Debug.isLogEnabled()) { + Debug.log(runtime.disassemble(result, compiledMethod)); + } + if (compilable != null) { + compilable.codeSize = result.getTargetCodeSize(); + } + return compiledMethod; + } + + private PhasePlan createPhasePlan(final GraphBuilderConfiguration config) { + final PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + return phasePlan; + } + + public void processAssumption(Assumptions newAssumptions, Assumption assumption, List manual) { + if (assumption != null) { + if (assumption instanceof AssumptionValidAssumption) { + AssumptionValidAssumption assumptionValidAssumption = (AssumptionValidAssumption) assumption; + manual.add(assumptionValidAssumption); + } else { + newAssumptions.record(assumption); + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, 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.truffle; + +import com.oracle.graal.options.*; + +/** + * Options for the Truffle compiler. + */ +public class TruffleCompilerOptions { + + // @formatter:off + // configuration + /** + * Instructs the Truffle Compiler to compile call targets only if their name contains at least one element of a comma-separated list of includes. + * Excludes are prefixed with a tilde (~). + * + * The format in EBNF: + *
+     * CompileOnly = Element, { ',', Element } ;
+     * Element = Include | '~' Exclude ;
+     * 
+ */ + @Option(help = "") + public static final OptionValue TruffleCompileOnly = new OptionValue<>(null); + @Option(help = "") + public static final OptionValue TruffleCompilationThreshold = new OptionValue<>(1000); + @Option(help = "") + public static final OptionValue TruffleInvalidationReprofileCount = new OptionValue<>(3); + @Option(help = "") + public static final OptionValue TruffleInliningReprofileCount = new OptionValue<>(100); + @Option(help = "") + public static final OptionValue TruffleFunctionInlining = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue TruffleConstantUnrollLimit = new OptionValue<>(32); + + // tracing + @Option(help = "") + public static final OptionValue TraceTruffleCompilation = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue TraceTruffleCompilationDetails = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TruffleInlinePrinter = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TraceTruffleCompilationExceptions = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue TruffleCompilationExceptionsAreFatal = new OptionValue<>(true); + // @formatter:on +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.truffle.*; + +public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Simplifiable { + + public AssumptionNode(Invoke invoke) { + super(invoke); + assert super.arguments.size() == 1; + } + + private ValueNode getAssumption() { + return arguments.first(); + } + + public void simplify(SimplifierTool tool) { + ValueNode assumption = getAssumption(); + if (tool.assumptions() != null && assumption.isConstant()) { + Constant c = assumption.asConstant(); + assert c.getKind() == Kind.Object; + Object object = c.asObject(); + OptimizedAssumption assumptionObject = (OptimizedAssumption) object; + StructuredGraph graph = graph(); + if (assumptionObject.isValid()) { + tool.assumptions().record(new AssumptionValidAssumption(assumptionObject)); + if (super.getReturnType().getKind() == Kind.Boolean) { + graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(true, graph())); + } else { + graph.removeFixed(this); + } + } else { + if (super.getReturnType().getKind() == Kind.Boolean) { + graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(false, graph())); + } else { + tool.deleteBranch(this.next()); + this.replaceAndDelete(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None))); + } + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.truffle.*; + +public class AssumptionValidAssumption extends Assumptions.Assumption { + + private static final long serialVersionUID = 2010244979610891262L; + + private OptimizedAssumption assumption; + + public AssumptionValidAssumption(OptimizedAssumption assumption) { + this.assumption = assumption; + } + + public OptimizedAssumption getAssumption() { + return assumption; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; + +public class BailoutNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Canonicalizable { + + public BailoutNode(Invoke invoke) { + super(invoke); + assert arguments.size() == 1; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + ValueNode arg = arguments.get(0); + String message = ""; + if (arg.isConstant()) { + message = (String) arg.asConstant().asObject(); + } + throw new BailoutException(message); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/CompilationConstantNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/CompilationConstantNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +public class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable { + + public CompilationConstantNode(Invoke invoke) { + super(invoke, "The value could not be reduced to a compile time constant."); + assert arguments.size() == 1; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (arguments.get(0).isConstant()) { + return arguments.get(0); + } + return this; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameAccessNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameAccessNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.truffle.api.frame.*; + +/** + * Base node class for the intrinsic nodes for read and write access to a Truffle frame. + */ +public abstract class FrameAccessNode extends FixedWithNextNode implements Simplifiable { + + @Input private ValueNode frame; + @Input private ValueNode slot; + protected final ResolvedJavaField field; + protected final Kind slotKind; + + public FrameAccessNode(Stamp stamp, Kind slotKind, ValueNode frame, ValueNode slot, ResolvedJavaField field) { + super(stamp); + this.slotKind = slotKind; + this.frame = frame; + this.slot = slot; + this.field = field; + } + + public ValueNode getFrame() { + return frame; + } + + public ValueNode getSlot() { + return slot; + } + + public Kind getSlotKind() { + return slotKind; + } + + protected int getSlotIndex() { + return getFrameSlot().getIndex(); + } + + protected boolean isFrameSlotConstant() { + return slot.isConstant(); + } + + protected FrameSlot getFrameSlot() { + assert isFrameSlotConstant() : slot; + return (FrameSlot) slot.asConstant().asObject(); + } + + protected final void insertDeoptimization(VirtualizerTool tool) { + LogicNode contradiction = LogicConstantNode.contradiction(graph()); + FixedGuardNode fixedGuard = new FixedGuardNode(contradiction, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile); + tool.addNode(fixedGuard); + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(verbosity) + getSlotKind().name() + (isFrameSlotConstant() ? " " + getFrameSlot() : ""); + } else { + return super.toString(verbosity); + } + } + + protected final ValueNode getSlotOffset(int scale, MetaAccessProvider metaAccessProvider) { + if (isFrameSlotConstant()) { + return ConstantNode.forInt(getSlotIndex() * scale, graph()); + } else { + LoadFieldNode loadFrameSlotIndex = graph().add(new LoadFieldNode(getSlot(), metaAccessProvider.lookupJavaField(getFrameSlotIndexField()))); + graph().addBeforeFixed(this, loadFrameSlotIndex); + return scale == 1 ? loadFrameSlotIndex : IntegerArithmeticNode.mul(loadFrameSlotIndex, ConstantNode.forInt(scale, graph())); + } + } + + private static Field getFrameSlotIndexField() { + try { + return FrameSlotImpl.class.getDeclaredField("index"); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + protected final boolean isValidAccessKind() { + if (getSlotKind() == Kind.Byte) { + // tag access + return true; + } + + return getSlotKind() == getGraalKind(getFrameSlot().getKind()); + } + + private static Kind getGraalKind(FrameSlotKind kind) { + switch (kind) { + case Object: + return Kind.Object; + case Long: + return Kind.Long; + case Int: + return Kind.Int; + case Double: + return Kind.Double; + case Float: + return Kind.Float; + case Boolean: + return Kind.Boolean; + case Illegal: + default: + return Kind.Illegal; + } + } + + @Override + public final void simplify(SimplifierTool tool) { + if (isFrameSlotConstant()) { + if (!isValidAccessKind()) { + tool.deleteBranch(this.next()); + this.replaceAndDelete(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode))); + } + } + } + + @Override + public Map getDebugProperties(Map map) { + Map properties = super.getDebugProperties(map); + if (isFrameSlotConstant()) { + properties.put("frameSlot", getFrameSlot().toString()); + } + return properties; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameGetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameGetNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Node.IterableNodeType; +import com.oracle.graal.graph.*; +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.nodes.virtual.*; +import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.frame.*; + +/** + * Intrinsic node for read access to a Truffle frame. + */ +@NodeInfo(nameTemplate = "FrameGet{p#slotKind/s}{p#frameSlot/s}") +public class FrameGetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable { + + public FrameGetNode(Kind kind, ValueNode frame, ValueNode slot, ResolvedJavaField field) { + super(StampFactory.forKind(kind), kind, frame, slot, field); + } + + @Override + public void virtualize(VirtualizerTool tool) { + if (!isFrameSlotConstant()) { + return; + } + assert isValidAccessKind(); + State virtualFrame = tool.getObjectState(getFrame()); + if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) { + return; + } + assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame; + VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject(); + int arrayFieldIndex = virtualFrameObject.fieldIndex(field); + State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex)); + assert virtualArray != null; + ValueNode result = virtualArray.getEntry(getSlotIndex()); + State virtualResult = tool.getObjectState(result); + if (virtualResult != null) { + tool.replaceWithVirtual(virtualResult.getVirtualObject()); + } else { + tool.replaceWithValue(result); + } + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + assert !(getFrame() instanceof NewFrameNode); + StructuredGraph structuredGraph = graph(); + + LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field)); + structuredGraph.addBeforeFixed(this, loadFieldNode); + FixedWithNextNode loadNode; + if (!getSlotKind().isPrimitive()) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Object)); + } else if (getSlotKind() == Kind.Byte) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Byte)); + } else { + ValueNode slotOffset = getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime()); + loadNode = graph().add(new UnsafeLoadNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, getSlotKind())); + } + structuredGraph.replaceFixedWithFixed(this, loadNode); + } + + @NodeIntrinsic + public static native T get(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, @ConstantNodeParameter ResolvedJavaField field); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameSetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameSetNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Node.IterableNodeType; +import com.oracle.graal.graph.*; +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.nodes.virtual.*; +import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.frame.*; + +/** + * Intrinsic node for write access to a Truffle frame. + */ +@NodeInfo(nameTemplate = "FrameSet{p#slotKind/s}{p#frameSlot/s}") +public class FrameSetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable { + + @Input private ValueNode value; + + public FrameSetNode(Kind kind, ValueNode frame, ValueNode frameSlot, ValueNode value, ResolvedJavaField field) { + super(StampFactory.forVoid(), kind, frame, frameSlot, field); + this.value = value; + } + + public ValueNode getValue() { + return value; + } + + @Override + public void virtualize(VirtualizerTool tool) { + if (!isFrameSlotConstant()) { + return; + } + assert isValidAccessKind(); + State virtualFrame = tool.getObjectState(getFrame()); + if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) { + return; + } + assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame; + VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject(); + int arrayFieldIndex = virtualFrameObject.fieldIndex(field); + State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex)); + assert virtualArray != null; + ValueNode storedValue = value; + tool.setVirtualEntry(virtualArray, getSlotIndex(), storedValue); + tool.delete(); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + assert !(getFrame() instanceof NewFrameNode); + StructuredGraph structuredGraph = graph(); + + LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field)); + structuredGraph.addBeforeFixed(this, loadFieldNode); + FixedWithNextNode storeNode; + if (!getSlotKind().isPrimitive()) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Object, value)); + } else if (getSlotKind() == Kind.Byte) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Byte, value)); + } else { + ValueNode slotOffset = getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime()); + storeNode = graph().add(new UnsafeStoreNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, value, getSlotKind())); + } + structuredGraph.replaceFixedWithFixed(this, storeNode); + } + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, Object value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, byte value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, boolean value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, int value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, long value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, double value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, float value, @ConstantNodeParameter ResolvedJavaField field); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.truffle.api.*; + +/** + * Node representing an exact integer addition that will throw an {@link ArithmeticException} in + * case the addition would overflow the 32 bit range. + */ +public class IntegerAddExactNode extends IntegerAddNode implements Canonicalizable, IntegerExactArithmeticNode { + + public IntegerAddExactNode(ValueNode x, ValueNode y) { + super(x.kind(), x, y); + assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + } + + @Override + public boolean inferStamp() { + // TODO Should probably use a specialised version which understands that it can't overflow + return updateStamp(StampTool.add(x().integerStamp(), y().integerStamp())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x().isConstant() && !y().isConstant()) { + return graph().unique(new IntegerAddExactNode(y(), x())); + } + if (x().isConstant()) { + try { + if (kind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.addExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(ExactMath.addExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 0) { + return x(); + } + } + return this; + } + + @Override + public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt)); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + IntegerExactArithmeticSplitNode.lower(tool, this); + } + + @NodeIntrinsic + public static native int addExact(int a, int b); + + @NodeIntrinsic + public static native long addExact(long a, long b); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactSplitNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode { + + public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp, x, y, next, overflowSuccessor); + } + + @Override + protected Value generateArithmetic(LIRGeneratorTool gen) { + return gen.emitAdd(gen.operand(getX()), gen.operand(getY())); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +interface IntegerExactArithmeticNode extends Lowerable { + + IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticSplitNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRGenLowerable { + + @Successor private AbstractBeginNode overflowSuccessor; + @Successor private AbstractBeginNode next; + @Input private ValueNode x; + @Input private ValueNode y; + + public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp); + this.x = x; + this.y = y; + this.overflowSuccessor = overflowSuccessor; + this.next = next; + } + + @Override + public double probability(AbstractBeginNode successor) { + return successor == scheduledNext() ? 1 : 0; + } + + @Override + public void setProbability(AbstractBeginNode successor, double value) { + assert probability(successor) == value; + } + + public AbstractBeginNode getNext() { + return next; + } + + public AbstractBeginNode getOverflowSuccessor() { + return overflowSuccessor; + } + + public ValueNode getX() { + return x; + } + + public ValueNode getY() { + return y; + } + + @Override + public void generate(LIRGenerator generator) { + generator.setResult(this, generateArithmetic(generator)); + generator.emitOverflowCheckBranch(generator.getLIRBlock(getNext()), generator.getLIRBlock(getOverflowSuccessor())); + } + + protected abstract Value generateArithmetic(LIRGeneratorTool generator); + + static void lower(LoweringTool tool, IntegerExactArithmeticNode node) { + FloatingNode floatingNode = (FloatingNode) node; + FixedWithNextNode previous = tool.lastFixedNode(); + FixedNode next = previous.next(); + previous.setNext(null); + DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException)); + BeginNode normalBegin = floatingNode.graph().add(new BeginNode()); + normalBegin.setNext(next); + IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt)); + previous.setNext(split); + floatingNode.replaceAndDelete(split); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.truffle.api.*; + +/** + * Node representing an exact integer multiplication that will throw an {@link ArithmeticException} + * in case the addition would overflow the 32 bit range. + */ +public class IntegerMulExactNode extends IntegerMulNode implements Canonicalizable, IntegerExactArithmeticNode { + + public IntegerMulExactNode(ValueNode x, ValueNode y) { + super(x.kind(), x, y); + assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x().isConstant() && !y().isConstant()) { + return graph().unique(new IntegerMulExactNode(y(), x())); + } + if (x().isConstant()) { + try { + if (kind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.multiplyExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(ExactMath.multiplyExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 1) { + return x(); + } + if (c == 0) { + return ConstantNode.defaultForKind(kind(), graph()); + } + } + return this; + } + + @Override + public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt)); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + IntegerExactArithmeticSplitNode.lower(tool, this); + } + + @NodeIntrinsic + public static native int multiplyExact(int a, int b); + + @NodeIntrinsic + public static native long multiplyExact(long a, long b); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactSplitNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode { + + public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp, x, y, next, overflowSuccessor); + } + + @Override + protected Value generateArithmetic(LIRGeneratorTool gen) { + return gen.emitMul(gen.operand(getX()), gen.operand(getY())); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.truffle.api.*; + +/** + * Node representing an exact integer substraction that will throw an {@link ArithmeticException} in + * case the addition would overflow the 32 bit range. + */ +public class IntegerSubExactNode extends IntegerSubNode implements Canonicalizable, IntegerExactArithmeticNode { + + public IntegerSubExactNode(ValueNode x, ValueNode y) { + super(x.kind(), x, y); + assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + } + + @Override + public boolean inferStamp() { + // TODO Should probably use a specialised version which understands that it can't overflow + return updateStamp(StampTool.sub(x().integerStamp(), y().integerStamp())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x() == y()) { + return ConstantNode.forIntegerKind(kind(), 0, graph()); + } + if (x().isConstant() && y().isConstant()) { + try { + if (kind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.subtractExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(ExactMath.subtractExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 0) { + return x(); + } + } + return this; + } + + @Override + public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt)); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + IntegerExactArithmeticSplitNode.lower(tool, this); + } + + @NodeIntrinsic + public static native int subtractExact(int a, int b); + + @NodeIntrinsic + public static native long subtractExact(long a, long b); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactSplitNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode { + + public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp, x, y, next, overflowSuccessor); + } + + @Override + protected Value generateArithmetic(LIRGeneratorTool gen) { + return gen.emitSub(gen.operand(getX()), gen.operand(getY())); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/MaterializeFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/MaterializeFrameNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.graph.Node.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.truffle.*; + +/** + * Intrinsic node for materializing a Truffle frame. + */ +@NodeInfo(nameTemplate = "MaterializeFrame{p#frame/s}") +public class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType { + + @Input private ValueNode frame; + + public MaterializeFrameNode(ValueNode frame) { + super(frame.stamp()); + this.frame = frame; + } + + public ValueNode getFrame() { + return frame; + } + + @NodeIntrinsic + public static native T materialize(FrameWithoutBoxing frame); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverInlineMacroNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverInlineMacroNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; + +public class NeverInlineMacroNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType { + + public NeverInlineMacroNode(Invoke invoke) { + super(invoke); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + InvokeNode invoke = createInvoke(); + graph().replaceFixedWithFixed(this, invoke); + invoke.setUseForInlining(false); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverPartOfCompilationNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverPartOfCompilationNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType { + + private final String message; + + public NeverPartOfCompilationNode(Invoke invoke) { + this(invoke, "This code path should never be part of a compilation."); + } + + public NeverPartOfCompilationNode(Invoke invoke, String message) { + super(invoke); + this.message = message; + } + + public final String getMessage() { + return message; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NewFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NewFrameNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.IterableNodeType; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * Intrinsic node representing the call for creating a frame in the {@link OptimizedCallTarget} + * class. + */ +public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable { + + static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(MetaAccessProvider.class).lookupJavaType(FrameWithoutBoxing.class); + + @Input private ValueNode descriptor; + @Input private ValueNode caller; + @Input private ValueNode arguments; + + public NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode caller, ValueNode arguments) { + super(stamp); + this.descriptor = descriptor; + this.caller = caller; + this.arguments = arguments; + } + + public NewFrameNode(ValueNode descriptor, ValueNode caller, ValueNode arguments) { + this(StampFactory.declaredNonNull(FRAME_TYPE), descriptor, caller, arguments); + } + + public ValueNode getDescriptor() { + return descriptor; + } + + public ValueNode getCaller() { + return caller; + } + + public ValueNode getArguments() { + return arguments; + } + + private FrameDescriptor getConstantFrameDescriptor() { + assert descriptor.isConstant() && !descriptor.isNullConstant(); + return (FrameDescriptor) descriptor.asConstant().asObject(); + } + + private int getFrameSize() { + return getConstantFrameDescriptor().getSize(); + } + + private static ResolvedJavaField findField(ResolvedJavaField[] fields, String fieldName) { + for (ResolvedJavaField field : fields) { + if (field.getName().equals(fieldName)) { + return field; + } + } + throw new RuntimeException("Frame field not found: " + fieldName); + } + + public static class VirtualOnlyInstanceNode extends VirtualInstanceNode implements Node.IterableNodeType { + + private boolean allowMaterialization; + + public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { + super(type, fields); + } + + @Override + public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, int[] locks) { + if (allowMaterialization) { + return super.getMaterializedRepresentation(fixed, entries, locks); + } + return getMaterializedRepresentationHelper(this, fixed); + } + + public void setAllowMaterialization(boolean b) { + this.allowMaterialization = b; + } + } + + public static ValueNode getMaterializedRepresentationHelper(VirtualObjectNode virtualNode, FixedNode fixed) { + if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode) { + // We need to conservatively assume that a materialization of a virtual frame can also + // happen at a merge point. + return new AllocatedObjectNode(virtualNode); + } + String escapeReason; + if (fixed instanceof StoreFieldNode) { + escapeReason = "Must not store virtual frame object into a field."; + } else if (fixed instanceof Invoke) { + escapeReason = "Must not pass virtual frame object into an invoke that cannot be inlined."; + } else { + escapeReason = "Must not let virtual frame object escape at node " + fixed + "."; + } + + Throwable exception = new GraalInternalError(escapeReason + + " Insert a call to VirtualFrame.materialize() to convert the instance to a materialized frame object (source position of following stack trace is approximate)"); + throw GraphUtil.approxSourceException(fixed, exception); + } + + @Override + public void virtualize(VirtualizerTool tool) { + int frameSize = getFrameSize(); + + ResolvedJavaType frameType = stamp().javaType(tool.getMetaAccessProvider()); + ResolvedJavaField[] frameFields = frameType.getInstanceFields(true); + + ResolvedJavaField descriptorField = findField(frameFields, "descriptor"); + ResolvedJavaField callerField = findField(frameFields, "caller"); + ResolvedJavaField argumentsField = findField(frameFields, "arguments"); + ResolvedJavaField localsField = findField(frameFields, "locals"); + ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals"); + ResolvedJavaField tagsField = findField(frameFields, "tags"); + + VirtualObjectNode virtualFrame = new VirtualOnlyInstanceNode(frameType, frameFields); + VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFramePrimitiveArray = new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFrameTagArray = new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize); + + ValueNode[] objectArrayEntryState = new ValueNode[frameSize]; + ValueNode[] primitiveArrayEntryState = new ValueNode[frameSize]; + ValueNode[] tagArrayEntryState = new ValueNode[frameSize]; + + if (frameSize > 0) { + FrameDescriptor frameDescriptor = getConstantFrameDescriptor(); + ConstantNode objectDefault = ConstantNode.forObject(frameDescriptor.getTypeConversion().getDefaultValue(), tool.getMetaAccessProvider(), graph()); + ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph()); + for (int i = 0; i < frameSize; i++) { + objectArrayEntryState[i] = objectDefault; + primitiveArrayEntryState[i] = initialValue(frameDescriptor.getSlots().get(i).getKind()); + tagArrayEntryState[i] = tagDefault; + } + tool.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); + } + + tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, null); + tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, null); + tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, null); + + assert frameFields.length == 6; + ValueNode[] frameEntryState = new ValueNode[frameFields.length]; + List frameFieldList = Arrays.asList(frameFields); + frameEntryState[frameFieldList.indexOf(descriptorField)] = getDescriptor(); + frameEntryState[frameFieldList.indexOf(callerField)] = getCaller(); + frameEntryState[frameFieldList.indexOf(argumentsField)] = getArguments(); + frameEntryState[frameFieldList.indexOf(localsField)] = virtualFrameObjectArray; + frameEntryState[frameFieldList.indexOf(primitiveLocalsField)] = virtualFramePrimitiveArray; + frameEntryState[frameFieldList.indexOf(tagsField)] = virtualFrameTagArray; + tool.createVirtualObject(virtualFrame, frameEntryState, null); + tool.replaceWithVirtual(virtualFrame); + } + + private ValueNode initialValue(FrameSlotKind kind) { + Kind graalKind = Kind.Long; + switch (kind) { + case Int: + graalKind = Kind.Int; + break; + case Double: + graalKind = Kind.Double; + break; + case Float: + graalKind = Kind.Float; + break; + case Boolean: + graalKind = Kind.Boolean; + break; + } + + return ConstantNode.defaultForKind(graalKind, graph()); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (usages().isEmpty()) { + return null; + } else { + return this; + } + } + + @NodeIntrinsic + public static native FrameWithoutBoxing allocate(FrameDescriptor descriptor, PackedFrame caller, Arguments args); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 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.truffle.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class UnsafeCastMacroNode extends NeverPartOfCompilationNode implements Canonicalizable { + + public UnsafeCastMacroNode(Invoke invoke) { + super(invoke, "The class of the unsafe cast could not be reduced to a compile time constant."); + assert arguments.size() == 2; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (arguments.get(1).isConstant()) { + Class c = (Class) arguments.get(1).asConstant().asObject(); + ResolvedJavaType lookupJavaType = tool.runtime().lookupJavaType(c); + Stamp s = StampFactory.declaredNonNull(lookupJavaType); + return graph().unique(new UnsafeCastNode(arguments.get(0), s)); + } + return this; + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013, 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.truffle.phases; + +import static com.oracle.graal.phases.GraalOptions.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; +import com.oracle.graal.truffle.*; + +/** + * Inline all trivial getters (i.e. simple field loads). + */ +public class InlineTrivialGettersPhase extends Phase { + + private static final int TRIVIAL_GETTER_SIZE = 5; + private final MetaAccessProvider metaAccessProvider; + private final Assumptions assumptions; + private final CustomCanonicalizer customCanonicalizer; + + public InlineTrivialGettersPhase(MetaAccessProvider metaAccessProvider, Assumptions assumptions, CustomCanonicalizer customCanonicalizer) { + this.metaAccessProvider = metaAccessProvider; + this.assumptions = assumptions; + this.customCanonicalizer = customCanonicalizer; + } + + @Override + protected void run(StructuredGraph graph) { + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + if (methodCallTarget.isAlive()) { + InvokeKind invokeKind = methodCallTarget.invokeKind(); + if (invokeKind == InvokeKind.Special) { + ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod(); + if (methodCallTarget.receiver().isConstant() && !methodCallTarget.receiver().isNullConstant()) { + if (targetMethod.getCodeSize() == TRIVIAL_GETTER_SIZE && targetMethod.getDeclaringClass().isInitialized() && targetMethod.getName().startsWith("get")) { + StructuredGraph inlineGraph = new StructuredGraph(targetMethod); + new GraphBuilderPhase(metaAccessProvider, GraphBuilderConfiguration.getDefault(), TruffleCompilerImpl.Optimizations).apply(inlineGraph); + int mark = graph.getMark(); + InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, false); + Debug.dump(graph, "After inlining trivial getter %s", targetMethod.toString()); + new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), mark, customCanonicalizer).apply(graph); + } + } + } + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, 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.truffle.phases; + +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +/** + * Compiler phase for intrinsifying the access to the Truffle virtual frame. + */ +public class ReplaceIntrinsicsPhase extends Phase { + + private final Replacements replacements; + + public ReplaceIntrinsicsPhase(Replacements replacements) { + this.replacements = replacements; + } + + @Override + protected void run(StructuredGraph graph) { + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + if (methodCallTarget.isAlive()) { + InvokeKind invokeKind = methodCallTarget.invokeKind(); + if (invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special) { + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod()); + if (inlineGraph != null) { + InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, false); + Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString()); + } + } + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013, 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.truffle.phases; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.truffle.nodes.*; + +/** + * Compiler phase for verifying that the Truffle virtual frame does not escape and can therefore be + * escape analyzed. + */ +public class VerifyFrameDoesNotEscapePhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + NewFrameNode frame = graph.getNodes(NewFrameNode.class).first(); + if (frame != null) { + for (MethodCallTargetNode callTarget : frame.usages().filter(MethodCallTargetNode.class)) { + if (callTarget.invoke() != null) { + Throwable exception = new VerificationError("Frame escapes at: %s#%s", callTarget, callTarget.targetMethod()); + throw GraphUtil.approxSourceException(callTarget, exception); + } + } + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 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.truffle.phases; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.IterableNodeType; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; + +/** + * Verification phase for checking that no frame intrinsic nodes introduced by the + * {@link PartialEvaluator} are still in the graph. + */ +public class VerifyNoIntrinsicsLeftPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + verifyNoInstanceLeft(graph, NewFrameNode.class); + } + + public static void verifyNoInstanceLeft(StructuredGraph graph, Class clazz) { + if (graph.getNodes(clazz).count() != 0) { + throw new VerificationError("Found unexpected node(s): %s", graph.getNodes(clazz)); + } + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; + +@ClassSubstitution(CompilerAsserts.class) +public class CompilerAssertsSubstitutions { + + @MacroSubstitution(macro = NeverPartOfCompilationNode.class, isStatic = true) + public static native void neverPartOfCompilation(); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native boolean compilationConstant(boolean value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native byte compilationConstant(byte value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native char compilationConstant(char value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native short compilationConstant(short value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native int compilationConstant(int value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native long compilationConstant(long value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native float compilationConstant(float value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native double compilationConstant(double value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native Object compilationConstant(Object value); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; + +@ClassSubstitution(CompilerDirectives.class) +public class CompilerDirectivesSubstitutions { + + @MethodSubstitution + public static void transferToInterpreter() { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } + + @MethodSubstitution + public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) { + } + + @MethodSubstitution + public static T interpreterOnly(@SuppressWarnings("unused") Callable callable) throws Exception { + return null; + } + + @MethodSubstitution + public static boolean injectBranchProbability(double probability, boolean condition) { + return BranchProbabilityNode.probability(probability, condition); + } + + @MacroSubstitution(macro = BailoutNode.class, isStatic = true) + public static native void bailout(String reason); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; + +@ClassSubstitution(DefaultCallTarget.class) +public class DefaultCallTargetSubstitutions { + + @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) + public static native Object call(DefaultCallTarget target, PackedFrame caller, Arguments args); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; + +/** + * Intrinsics for exact math operations that throw an exception in case the operation would overflow + * the allowed range. + */ +@ClassSubstitution(ExactMath.class) +public class ExactMathSubstitutions { + + @MethodSubstitution + public static int addExact(int x, int y) { + return IntegerAddExactNode.addExact(x, y); + } + + @MethodSubstitution + public static long addExact(long x, long y) { + return IntegerAddExactNode.addExact(x, y); + } + + @MethodSubstitution + public static int subtractExact(int x, int y) { + return IntegerSubExactNode.subtractExact(x, y); + } + + @MethodSubstitution + public static long subtractExact(long x, long y) { + return IntegerSubExactNode.subtractExact(x, y); + } + + @MethodSubstitution + public static int multiplyExact(int x, int y) { + return IntegerMulExactNode.multiplyExact(x, y); + } + + @MethodSubstitution + public static long multiplyExact(long x, long y) { + return IntegerMulExactNode.multiplyExact(x, y); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.frame.*; + +@ClassSubstitution(FrameWithoutBoxing.class) +public class FrameWithoutBoxingSubstitutions { + + private static final ResolvedJavaField LOCALS_FIELD; + private static final ResolvedJavaField PRIMITIVELOCALS_FIELD; + private static final ResolvedJavaField TAGS_FIELD; + + static { + try { + MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class); + LOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("locals")); + PRIMITIVELOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("primitiveLocals")); + TAGS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("tags")); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + @MacroSubstitution(macro = UnsafeCastMacroNode.class, isStatic = true) + public static native Object unsafeCast(Object value, Class clazz); + + @SuppressWarnings("unused") + @MethodSubstitution(isStatic = false) + public static Object pack(FrameWithoutBoxing frame) { + return null; + } + + @MethodSubstitution(isStatic = false) + public static Object getObject(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Object); + return getObjectUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setObject(FrameWithoutBoxing frame, FrameSlot slot, Object value) { + verifySet(frame, slot, FrameSlotKind.Object); + setObjectUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static boolean getBoolean(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Boolean); + return getBooleanUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setBoolean(FrameWithoutBoxing frame, FrameSlot slot, boolean value) { + verifySet(frame, slot, FrameSlotKind.Boolean); + setBooleanUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static float getFloat(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Float); + return getFloatUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setFloat(FrameWithoutBoxing frame, FrameSlot slot, float value) { + verifySet(frame, slot, FrameSlotKind.Float); + setFloatUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static long getLong(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Long); + return getLongUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setLong(FrameWithoutBoxing frame, FrameSlot slot, long value) { + verifySet(frame, slot, FrameSlotKind.Long); + setLongUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static int getInt(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Int); + return getIntUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setInt(FrameWithoutBoxing frame, FrameSlot slot, int value) { + verifySet(frame, slot, FrameSlotKind.Int); + setIntUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static double getDouble(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Double); + return getDoubleUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setDouble(FrameWithoutBoxing frame, FrameSlot slot, double value) { + verifySet(frame, slot, FrameSlotKind.Double); + setDoubleUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static Object getObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Object, frame, slot, LOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot, Object value) { + FrameSetNode.set(Kind.Object, frame, slot, value, LOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static boolean getBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Boolean, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot, boolean value) { + FrameSetNode.set(Kind.Boolean, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static int getIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Int, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot, int value) { + FrameSetNode.set(Kind.Int, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static long getLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Long, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot, long value) { + FrameSetNode.set(Kind.Long, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static double getDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Double, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot, double value) { + FrameSetNode.set(Kind.Double, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static float getFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Float, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot, float value) { + FrameSetNode.set(Kind.Float, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + private static void verifySet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) { + setTag(frame, slot, (byte) accessType.ordinal()); + } + + private static void verifyGet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) { + if (getTag(frame, slot) != (byte) accessType.ordinal()) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode); + } + } + + private static byte getTag(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Byte, frame, slot, TAGS_FIELD); + } + + private static void setTag(FrameWithoutBoxing frame, FrameSlot slot, byte tag) { + FrameSetNode.set(Kind.Byte, frame, slot, tag, TAGS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static MaterializedFrame materialize(FrameWithoutBoxing frame) { + return MaterializeFrameNode.materialize(frame); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; + +@ClassSubstitution(OptimizedAssumption.class) +public class OptimizedAssumptionSubstitutions { + + @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) + public static native void check(OptimizedAssumption assumption); + + @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) + public static native boolean isValid(OptimizedAssumption assumption); +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +@ClassSubstitution(OptimizedCallTarget.class) +public class OptimizedCallTargetSubstitutions { + + @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) + public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args); + + @MethodSubstitution + private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return NewFrameNode.allocate(descriptor, caller, args); + } + + @SuppressWarnings("unused") + @MethodSubstitution(isStatic = false) + private static VirtualFrame create(OptimizedCallTarget target, FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return createFrame(descriptor, caller, args); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Deoptimize on creation of a new SlowPathException instance. + */ +@ClassSubstitution(SlowPathException.class) +public class SlowPathExceptionSubstitutions { + + @MethodSubstitution(value = "") + public static void init() { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } + + @SuppressWarnings("unused") + @MethodSubstitution(value = "") + public static void init(String result, Throwable cause) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } + + @SuppressWarnings("unused") + @MethodSubstitution(value = "") + public static void init(String result) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } + + @SuppressWarnings("unused") + @MethodSubstitution(value = "") + public static void init(Throwable cause) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 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.truffle.substitutions; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Deoptimize on creation of a new UnexpectedResultException instance. + */ +@ClassSubstitution(UnexpectedResultException.class) +public class UnexpectedResultExceptionSubstitutions { + + @SuppressWarnings("unused") + @MethodSubstitution(value = "") + public static void init(Object result) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012, 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.truffle.api.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +public interface FrameFactory { + + VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args); + +} diff -r 3e6f538829ce -r 0097fb11c16f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java Sun Jun 23 21:44:15 2013 +0200 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, 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.truffle.api.nodes; + +public interface InlinableCallSite { + + int getCallCount(); + + void resetCallCount(); + + Node getInlineTree(); + + boolean inline(FrameFactory factory); + +} diff -r 3e6f538829ce -r 0097fb11c16f mx/projects --- a/mx/projects Sun Jun 23 21:36:00 2013 +0200 +++ b/mx/projects Sun Jun 23 21:44:15 2013 +0200 @@ -25,7 +25,7 @@ library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar distribution@GRAAL@path=graal.jar -distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot +distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.truffle,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot # graal.api.runtime project@com.oracle.graal.api.runtime@subDir=graal @@ -404,7 +404,7 @@ # graal.printer project@com.oracle.graal.printer@subDir=graal project@com.oracle.graal.printer@sourceDirs=src -project@com.oracle.graal.printer@dependencies=com.oracle.graal.java,com.oracle.graal.compiler +project@com.oracle.graal.printer@dependencies=com.oracle.graal.java.decompiler,com.oracle.graal.compiler project@com.oracle.graal.printer@checkstyle=com.oracle.graal.graph project@com.oracle.graal.printer@javaCompliance=1.7 project@com.oracle.graal.printer@workingSets=Graal,Graph @@ -539,5 +539,28 @@ project@com.oracle.truffle.sl.test@javaCompliance=1.7 project@com.oracle.truffle.sl.test@workingSets=Truffle,SimpleLanguage,Test +# graal.truffle +project@com.oracle.graal.truffle@subDir=graal +project@com.oracle.graal.truffle@sourceDirs=src +project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot +project@com.oracle.graal.truffle@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.truffle@javaCompliance=1.7 +project@com.oracle.graal.truffle@workingSets=Graal,Truffle + +# graal.truffle.test +project@com.oracle.graal.truffle.test@subDir=graal +project@com.oracle.graal.truffle.test@sourceDirs=src +project@com.oracle.graal.truffle.test@dependencies=com.oracle.graal.truffle,com.oracle.graal.compiler.test +project@com.oracle.graal.truffle.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.truffle.test@javaCompliance=1.7 +project@com.oracle.graal.truffle.test@workingSets=Graal,Truffle,Test + +# graal.truffle.printer +project@com.oracle.graal.truffle.printer@subDir=graal +project@com.oracle.graal.truffle.printer@sourceDirs=src +project@com.oracle.graal.truffle.printer@dependencies=com.oracle.graal.nodes +project@com.oracle.graal.truffle.printer@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.truffle.printer@javaCompliance=1.7 +project@com.oracle.graal.truffle.printer@workingSets=Graal,Truffle