# HG changeset patch # User Doug Simon # Date 1355849972 -3600 # Node ID 19f5c9b96fa7577b092f2ecb663a339ffeaab446 # Parent 7f6bf286629c9f1d8a480f85a3f2b63f65d87e7f# Parent 17e12b5a3386f684e9b4923a65d53649faa13a3f Merge. diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Tue Dec 18 17:59:03 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Tue Dec 18 17:59:32 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.extended; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -34,8 +36,8 @@ @Successor protected final NodeSuccessorList successors; protected double[] successorProbabilities; @Input private ValueNode value; - private final double[] keyProbabilities; - private final int[] keySuccessors; + private double[] keyProbabilities; + private int[] keySuccessors; public ValueNode value() { return value; @@ -139,4 +141,13 @@ } return probability; } + + @Override + public SwitchNode clone(Graph into) { + SwitchNode newSwitch = (SwitchNode) super.clone(into); + newSwitch.successorProbabilities = Arrays.copyOf(successorProbabilities, successorProbabilities.length); + newSwitch.keyProbabilities = Arrays.copyOf(keyProbabilities, keyProbabilities.length); + newSwitch.keySuccessors = Arrays.copyOf(keySuccessors, keySuccessors.length); + return newSwitch; + } } diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,100 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + + +/** + *

Passing Arguments

+ * + *

+ * A guest language can pass its own custom arguments when invoking a Truffle method by creating a subclass of + * {@link Arguments}. When invoking a call target with {@link CallTarget#call(Arguments)}, the arguments can be passed. + * A Truffle node can access the arguments passed into the Truffle method by using {@link VirtualFrame#getArguments()}. + *

+ * + *

+ * The arguments class should only contain fields that are declared as final. This allows the Truffle runtime to improve + * optimizations around guest language method calls. Also, the arguments object must never be stored into a field. It + * should be created immediately before invoking {@link CallTarget#call(Arguments)} and no longer be accessed + * afterwards. + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.FrameTest}. + *

+ */ +public class ArgumentsTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + TestRootNode rootNode = new TestRootNode(new TestArgumentNode[]{new TestArgumentNode(0), new TestArgumentNode(1)}); + CallTarget target = runtime.createCallTarget(rootNode); + Object result = target.call(new TestArguments(20, 22)); + Assert.assertEquals(42, result); + } + + class TestArguments extends Arguments { + final int[] values; + TestArguments(int... values) { + this.values = values; + } + } + + class TestRootNode extends RootNode { + + @Children private TestArgumentNode[] children; + + TestRootNode(TestArgumentNode[] children) { + this.children = adoptChildren(children); + } + + @Override + public Object execute(VirtualFrame frame) { + int sum = 0; + for (int i = 0; i < children.length; ++i) { + sum += children[i].execute(frame); + } + return sum; + } + } + + class TestArgumentNode extends Node { + private final int index; + + TestArgumentNode(int index) { + this.index = index; + } + + int execute(VirtualFrame frame) { + return ((TestArguments) frame.getArguments()).values[index]; + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,85 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + + +/** + *

Calling Another Tree

+ * + *

+ * A guest language implementation can create multiple call targets using the {@link TruffleRuntime#createCallTarget(RootNode)} method. + * Those call targets can be passed around as normal Java objects and used for calling guest language methods. + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ArgumentsTest}. + *

+ */ +public class CallTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + CallTarget foo = runtime.createCallTarget(new ConstantRootNode(20)); + CallTarget bar = runtime.createCallTarget(new ConstantRootNode(22)); + CallTarget main = runtime.createCallTarget(new DualCallNode(foo, bar)); + Object result = main.call(); + Assert.assertEquals(42, result); + } + + class DualCallNode extends RootNode { + + private final CallTarget firstTarget; + private final CallTarget secondTarget; + + DualCallNode(CallTarget firstTarget, CallTarget secondTarget) { + this.firstTarget = firstTarget; + this.secondTarget = secondTarget; + } + + @Override + public Object execute(VirtualFrame frame) { + return ((Integer) firstTarget.call()) + ((Integer) secondTarget.call()); + } + } + + class ConstantRootNode extends RootNode { + private final int value; + + public ConstantRootNode(int value) { + this.value = value; + } + + @Override + public Object execute(VirtualFrame frame) { + return value; + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,93 @@ +/* + * 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.test; + +import java.util.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.Node.Child; + +/** + *

Creating a Child Node

+ * + *

+ * Child nodes are stored in the class of the parent node in fields that are marked with the {@link Child} annotation. + * Before such a field is assigned, {@link Node#adoptChild} must be called. This method automatically establishes a link + * from the child to the parent. The {@link Node#getParent()} method allows access to this field. Every node also + * provides the ability to iterate over its children using {@link Node#getChildren()}.

+ * + *

A child node field must be declared private and non-final. It may only be assigned in the constructor of the parent + * node. For changing the structure of the tree at run time, the method {@link Node#replace(Node)} must be used (see + * {@link ReplaceTest}). + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ChildrenNodesTest}. + *

+ */ +public class ChildNodeTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + TestChildNode leftChild = new TestChildNode(); + TestChildNode rightChild = new TestChildNode(); + TestRootNode rootNode = new TestRootNode(leftChild, rightChild); + Assert.assertEquals(rootNode, leftChild.getParent()); + Assert.assertEquals(rootNode, rightChild.getParent()); + Iterator iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(leftChild, iterator.next()); + Assert.assertEquals(rightChild, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + CallTarget target = runtime.createCallTarget(rootNode); + Object result = target.call(); + Assert.assertEquals(42, result); + } + + class TestRootNode extends RootNode { + + @Child private TestChildNode left; + @Child private TestChildNode right; + + public TestRootNode(TestChildNode left, TestChildNode right) { + this.left = adoptChild(left); + this.right = adoptChild(right); + } + + @Override + public Object execute(VirtualFrame frame) { + return left.execute() + right.execute(); + } + } + + class TestChildNode extends Node { + + public int execute() { + return 21; + } + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,91 @@ +/* + * 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.test; + +import java.util.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + *

Creating an Array of Children Nodes

+ * + *

+ * An array of children nodes can be used as a field in a parent node. The field has to be annotated with + * {@link com.oracle.truffle.api.nodes.Node.Children} and must be declared private and final. Before assigning the field + * in the parent node constructor, {@link Node#adoptChildren} must be called in order to update the parent pointers in + * the child nodes. After filling the array with its first values, it must never be changed. It is only possible to call + * {@link Node#replace} on a child node. + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.FinalFieldTest}. + *

+ */ +public class ChildrenNodesTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + TestChildNode firstChild = new TestChildNode(); + TestChildNode secondChild = new TestChildNode(); + TestRootNode rootNode = new TestRootNode(new TestChildNode[]{firstChild, secondChild}); + Assert.assertEquals(rootNode, firstChild.getParent()); + Assert.assertEquals(rootNode, secondChild.getParent()); + Iterator iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(firstChild, iterator.next()); + Assert.assertEquals(secondChild, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + CallTarget target = runtime.createCallTarget(rootNode); + Object result = target.call(); + Assert.assertEquals(42, result); + } + + class TestRootNode extends RootNode { + + @Children private final TestChildNode[] children; + + public TestRootNode(TestChildNode[] children) { + this.children = adoptChildren(children); + } + + @Override + public Object execute(VirtualFrame frame) { + int sum = 0; + for (int i = 0; i < children.length; ++i) { + sum += children[i].execute(); + } + return sum; + } + } + + class TestChildNode extends Node { + public int execute() { + return 21; + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,92 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + *

Using Final Fields in Node Classes

+ * + *

+ * The usage of final fields in node classes is highly encouraged. It is beneficial for performance to declare every + * field that is not pointing to a child node as final. This gives the Truffle runtime an increased opportunity to + * optimize this node. + *

+ * + *

+ * If a node has a value which may change at run time, but will rarely do so, it is recommended to speculate on the + * field being final. This involves starting executing with a node where this field is final and only if this + * turns out to be no longer the case, the node is replaced with an alternative implementation of the operation (see + * {@link ReplaceTest}). + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ReplaceTest}. + *

+ */ +public class FinalFieldTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + TestRootNode rootNode = new TestRootNode(new TestChildNode[]{new TestChildNode(20), new TestChildNode(22)}); + CallTarget target = runtime.createCallTarget(rootNode); + Object result = target.call(); + Assert.assertEquals(42, result); + } + + class TestRootNode extends RootNode { + + @Children TestChildNode[] children; + + public TestRootNode(TestChildNode[] children) { + this.children = adoptChildren(children); + } + + @Override + public Object execute(VirtualFrame frame) { + int sum = 0; + for (int i = 0; i < children.length; ++i) { + sum += children[i].execute(); + } + return sum; + } + } + + class TestChildNode extends Node { + private final int value; + + public TestChildNode(int value) { + this.value = value; + } + + public int execute() { + return value; + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,178 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + + +/** + *

Specializing Frame Slot Types

+ * + *

+ * Dynamically typed languages can speculate on the type of a frame slot and only fall back at run time to a more + * generic type if necessary. The new type of a frame slot can be set using the {@link FrameSlot#setType(Class)} method. + * It is the responsibility of the language implementor to update the content of currently active frames (using + * {@link Frame#updateToLatestVersion()}). Also, nodes that depend a specific type of a frame slot must be replaced. + * Such node can register a listener that implements {@link FrameSlotTypeListener} using + * {@link FrameSlot#registerOneShotTypeListener(FrameSlotTypeListener)}. The event of a type change on the frame slot + * will fire only once for the next upcoming change. + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}. + *

+ */ +public class FrameSlotTypeSpecializationTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + FrameDescriptor frameDescriptor = new FrameDescriptor(); + FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class); + TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot)); + CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor); + Assert.assertEquals(Integer.class, slot.getType()); + Object result = target.call(); + Assert.assertEquals("42", result); + Assert.assertEquals(Object.class, slot.getType()); + } + + class TestRootNode extends RootNode { + + @Child TestChildNode left; + @Child TestChildNode right; + + public TestRootNode(TestChildNode left, TestChildNode right) { + this.left = adoptChild(left); + this.right = adoptChild(right); + } + + @Override + public Object execute(VirtualFrame frame) { + left.execute(frame); + return right.execute(frame); + } + } + + abstract class TestChildNode extends Node { + abstract Object execute(VirtualFrame frame); + } + + abstract class FrameSlotNode extends TestChildNode { + protected final FrameSlot slot; + + public FrameSlotNode(FrameSlot slot) { + this.slot = slot; + } + } + + class StringTestChildNode extends TestChildNode { + + @Override + Object execute(VirtualFrame frame) { + return "42"; + } + + } + + class IntAssignLocal extends FrameSlotNode implements FrameSlotTypeListener { + @Child private TestChildNode value; + + IntAssignLocal(FrameSlot slot, TestChildNode value) { + super(slot); + this.value = adoptChild(value); + slot.registerOneShotTypeListener(this); + } + + @Override + Object execute(VirtualFrame frame) { + Object o = value.execute(frame); + if (o instanceof Integer) { + frame.setInt(slot, (Integer) o); + } else { + slot.setType(Object.class); + frame.updateToLatestVersion(); + frame.setObject(slot, o); + } + return null; + } + + @Override + public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) { + if (changedSlot.getType() == Object.class) { + this.replace(new ObjectAssignLocal(changedSlot, value)); + } + } + } + + class ObjectAssignLocal extends FrameSlotNode { + @Child private TestChildNode value; + + ObjectAssignLocal(FrameSlot slot, TestChildNode value) { + super(slot); + this.value = adoptChild(value); + } + + @Override + Object execute(VirtualFrame frame) { + Object o = value.execute(frame); + frame.setObject(slot, o); + return null; + } + } + + class IntReadLocal extends FrameSlotNode implements FrameSlotTypeListener { + IntReadLocal(FrameSlot slot) { + super(slot); + slot.registerOneShotTypeListener(this); + } + + @Override + Object execute(VirtualFrame frame) { + return frame.getInt(slot); + } + + @Override + public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) { + if (changedSlot.getType() == Object.class) { + this.replace(new ObjectReadLocal(changedSlot)); + } + } + } + + class ObjectReadLocal extends FrameSlotNode { + ObjectReadLocal(FrameSlot slot) { + super(slot); + } + + @Override + Object execute(VirtualFrame frame) { + return frame.getObject(slot); + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,122 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + *

Storing Values in Frame Slots

+ * + *

+ * The frame is the preferred data structure for passing values between nodes. It can in particular be used for storing + * the values of local variables of the guest language. The {@link FrameDescriptor} represents the current structure of + * the frame. The method {@link FrameDescriptor#addFrameSlot(String, Class)} can be used to create predefined frame + * slots. The setter and getter methods in the {@link Frame} class can be used to access the current value of a + * particular frame slot. + *

+ * + *

+ * There are five primitive types for slots available: {@link java.lang.Boolean}, @{link java.lang.Integer}, + * {@link java.lang.Long}, {@link java.lang.Float}, and {@link java.lang.Double}. It is encouraged to use those types + * whenever possible. Dynamically typed languages can speculate on the type of a value fitting into a primitive (see + * {@link FrameSlotTypeSpecializationTest}). When a frame slot is of one of those particular primitive types, its value + * may only be accessed with the repectively typed getter method ({@link Frame#getBoolean}, {@link Frame#getInt}, + * {@link Frame#getLong}, {@link Frame#getFloat}, or {@link Frame#getDouble}) or setter method ({@link Frame#setBoolean}, + * {@link Frame#setInt}, {@link Frame#setLong}, {@link Frame#setFloat}, or {@link Frame#setDouble}) in the + * {@link Frame} class. + *

+ * + *

+ * The next part of the Truffle API introduction is at + * {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}. + *

+ */ +public class FrameTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + FrameDescriptor frameDescriptor = new FrameDescriptor(); + FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class); + TestRootNode rootNode = new TestRootNode(new AssignLocal(slot), new ReadLocal(slot)); + CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor); + Object result = target.call(); + Assert.assertEquals(42, result); + } + + class TestRootNode extends RootNode { + + @Child TestChildNode left; + @Child TestChildNode right; + + public TestRootNode(TestChildNode left, TestChildNode right) { + this.left = adoptChild(left); + this.right = adoptChild(right); + } + + @Override + public Object execute(VirtualFrame frame) { + return left.execute(frame) + right.execute(frame); + } + } + + abstract class TestChildNode extends Node { + abstract int execute(VirtualFrame frame); + } + + abstract class FrameSlotNode extends TestChildNode { + protected final FrameSlot slot; + + public FrameSlotNode(FrameSlot slot) { + this.slot = slot; + } + } + + class AssignLocal extends FrameSlotNode { + AssignLocal(FrameSlot slot) { + super(slot); + } + + @Override + int execute(VirtualFrame frame) { + frame.setInt(slot, 42); + return 0; + } + } + + class ReadLocal extends FrameSlotNode { + ReadLocal(FrameSlot slot) { + super(slot); + } + + @Override + int execute(VirtualFrame frame) { + return frame.getInt(slot); + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,133 @@ +/* + * 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.test; + +import static org.junit.Assert.*; + +import java.util.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + + +/** + *

Replacing Nodes at Run Time

+ * + *

+ * The structure of the Truffle tree can be changed at run time by replacing nodes using the {@link Node#replace(Node)} + * method. This method will automatically change the child pointer in the parent of the node and replace it with a + * pointer to the new node. + *

+ * + *

+ * Replacing nodes is a costly operation, so it should not happen too often. The convention is that the implementation + * of the Truffle nodes should ensure that there are maximal a small (and constant) number of node replacements per + * Truffle node. + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.CallTest}. + *

+ */ +public class ReplaceTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + UnresolvedNode leftChild = new UnresolvedNode("20"); + UnresolvedNode rightChild = new UnresolvedNode("22"); + TestRootNode rootNode = new TestRootNode(new ValueNode[]{leftChild, rightChild}); + assertEquals(rootNode, leftChild.getParent()); + assertEquals(rootNode, rightChild.getParent()); + Iterator iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(leftChild, iterator.next()); + Assert.assertEquals(rightChild, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + CallTarget target = runtime.createCallTarget(rootNode); + Object result = target.call(); + assertEquals(42, result); + assertEquals(42, target.call()); + iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(ResolvedNode.class, iterator.next().getClass()); + Assert.assertEquals(ResolvedNode.class, iterator.next().getClass()); + Assert.assertFalse(iterator.hasNext()); + iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(rootNode, iterator.next().getParent()); + Assert.assertEquals(rootNode, iterator.next().getParent()); + Assert.assertFalse(iterator.hasNext()); + } + + class TestRootNode extends RootNode { + + @Children private ValueNode[] children; + + public TestRootNode(ValueNode[] children) { + this.children = adoptChildren(children); + } + + @Override + public Object execute(VirtualFrame frame) { + int sum = 0; + for (int i = 0; i < children.length; ++i) { + sum += children[i].execute(); + } + return sum; + } + } + + abstract class ValueNode extends Node { + abstract int execute(); + } + + class UnresolvedNode extends ValueNode { + private final String value; + + public UnresolvedNode(String value) { + this.value = value; + } + + @Override + int execute() { + int intValue = Integer.parseInt(value); + ResolvedNode newNode = this.replace(new ResolvedNode(intValue)); + return newNode.execute(); + } + } + + class ResolvedNode extends ValueNode { + private final int value; + + ResolvedNode(int value) { + this.value = value; + } + + @Override + int execute() { + return value; + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,184 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + *

Specializing Return Types

+ * + *

+ * In order to avoid boxing and/or type casts on the return value of a node, the return value the method for executing a + * node can have a specific type and need not be of type {@link java.lang.Object}. For dynamically typed languages, this + * return type is something that should be speculated on. When the speculation fails and the child node cannot return + * the appropriate type of value, it can use an {@link UnexpectedResultException} to still pass the result to the + * caller. In such a case, the caller must rewrite itself to a more general version in oder to avoid future failures of + * this kind. + *

+ */ +public class ReturnTypeSpecializationTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + FrameDescriptor frameDescriptor = new FrameDescriptor(); + FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class); + TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot)); + CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor); + Assert.assertEquals(Integer.class, slot.getType()); + Object result = target.call(); + Assert.assertEquals("42", result); + Assert.assertEquals(Object.class, slot.getType()); + } + + class TestRootNode extends RootNode { + + @Child TestChildNode left; + @Child TestChildNode right; + + public TestRootNode(TestChildNode left, TestChildNode right) { + this.left = adoptChild(left); + this.right = adoptChild(right); + } + + @Override + public Object execute(VirtualFrame frame) { + left.execute(frame); + return right.execute(frame); + } + } + + abstract class TestChildNode extends Node { + abstract Object execute(VirtualFrame frame); + + int executeInt(VirtualFrame frame) throws UnexpectedResultException { + Object result = execute(frame); + if (result instanceof Integer) { + return (Integer) result; + } + throw new UnexpectedResultException(result); + } + } + + abstract class FrameSlotNode extends TestChildNode { + protected final FrameSlot slot; + + public FrameSlotNode(FrameSlot slot) { + this.slot = slot; + } + } + + class StringTestChildNode extends TestChildNode { + + @Override + Object execute(VirtualFrame frame) { + return "42"; + } + + } + + class IntAssignLocal extends FrameSlotNode implements FrameSlotTypeListener { + @Child private TestChildNode value; + + IntAssignLocal(FrameSlot slot, TestChildNode value) { + super(slot); + this.value = adoptChild(value); + slot.registerOneShotTypeListener(this); + } + + @Override + Object execute(VirtualFrame frame) { + try { + frame.setInt(slot, value.executeInt(frame)); + } catch (UnexpectedResultException e) { + slot.setType(Object.class); + frame.updateToLatestVersion(); + frame.setObject(slot, e.getResult()); + } + return null; + } + + @Override + public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) { + if (changedSlot.getType() == Object.class) { + this.replace(new ObjectAssignLocal(changedSlot, value)); + } + } + } + + class ObjectAssignLocal extends FrameSlotNode { + @Child private TestChildNode value; + + ObjectAssignLocal(FrameSlot slot, TestChildNode value) { + super(slot); + this.value = adoptChild(value); + } + + @Override + Object execute(VirtualFrame frame) { + Object o = value.execute(frame); + frame.setObject(slot, o); + return null; + } + } + + class IntReadLocal extends FrameSlotNode implements FrameSlotTypeListener { + IntReadLocal(FrameSlot slot) { + super(slot); + slot.registerOneShotTypeListener(this); + } + + @Override + Object execute(VirtualFrame frame) { + return executeInt(frame); + } + + @Override + int executeInt(VirtualFrame frame) { + return frame.getInt(slot); + } + + @Override + public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) { + if (changedSlot.getType() == Object.class) { + this.replace(new ObjectReadLocal(changedSlot)); + } + } + } + + class ObjectReadLocal extends FrameSlotNode { + ObjectReadLocal(FrameSlot slot) { + super(slot); + } + + @Override + Object execute(VirtualFrame frame) { + return frame.getObject(slot); + } + } +} + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,65 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + *

Creating a Root Node

+ * + *

+ * A Truffle root node is the entry point into a Truffle tree that represents a guest language method. It contains a + * {@link RootNode#execute(VirtualFrame)} method that can return a {@link java.lang.Object} value as the result of the + * guest language method invocation. This method must however never be called directly. Instead, the Truffle runtime + * must be used to create a {@link CallTarget} object from a root node using the + * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be executed using the + * {@link CallTarget#call()} method or one of its overloads. + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.ChildNodeTest}. + *

+ */ +public class RootNodeTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + TestRootNode rootNode = new TestRootNode(); + CallTarget target = runtime.createCallTarget(rootNode); + Object result = target.call(); + Assert.assertEquals(42, result); + } + + class TestRootNode extends RootNode { + + @Override + public Object execute(VirtualFrame frame) { + return 42; + } + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,51 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; + +/** + *

Accessing the Truffle Runtime

+ * + *

+ * The Truffle runtime can be accessed at any point in time globally using the static method + * {@link Truffle#getRuntime()}. This method is guaranteed to return a non-null Truffle runtime object with an + * identifying name. A Java Virtual Machine implementation can chose to replace the default implementation of the + * {@link TruffleRuntime} interface with its own implementation for providing improved performance. + *

+ * + *

+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.RootNodeTest}. + *

+ */ +public class TruffleRuntimeTest { + + @Test + public void test() { + TruffleRuntime runtime = Truffle.getRuntime(); + Assert.assertNotNull(runtime); + Assert.assertNotNull(runtime.getName()); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012, 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. + */ +/** + *

This package contains basic tests of the Truffle API and serves at the same + * time as an introduction to the Truffle API for language implementors. Every test gives an example on how to use the construct explained in the class description.

+ * + *

+ * Truffle is a language implementation framework. A guest language method is represented as a tree of executable nodes. + * The framework provides mechanisms for those trees to call each other. Additionally it contains dedicated data structures for storing data local to a tree invocation. + *

+ * + *

+ * This introduction to Truffle contains items in the following recommended order: + * + *

    + *
  • How to get access to the Truffle runtime? {@link com.oracle.truffle.api.test.TruffleRuntimeTest}
  • + *
  • How to create a root node? {@link com.oracle.truffle.api.test.RootNodeTest}
  • + *
  • How to create a child node and link it with its parent? {@link com.oracle.truffle.api.test.ChildNodeTest}
  • + *
  • How to create an array of child nodes? {@link com.oracle.truffle.api.test.ChildrenNodesTest}
  • + *
  • Why are final fields in node classes important? {@link com.oracle.truffle.api.test.FinalFieldTest}
  • + *
  • How to replace one node with another node and what for? {@link com.oracle.truffle.api.test.ReplaceTest}
  • + *
  • How to let one Truffle tree invoke another one? {@link com.oracle.truffle.api.test.CallTest}
  • + *
  • How to pass arguments when executing a tree? {@link com.oracle.truffle.api.test.ArgumentsTest}
  • + *
  • How to use frames and frame slots to store values local to an activation? {@link com.oracle.truffle.api.test.FrameTest}
  • + *
  • How to use type specialization and speculation for frame slots? {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}
  • + *
  • How to use type specialization and speculation for node return values? {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}
  • + *
+ * + *

+ * + */ +package com.oracle.truffle.api.test; + + diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Arguments.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Arguments.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * Base class for arguments passed to guest language methods via the + * {@link CallTarget#call(com.oracle.truffle.api.frame.PackedFrame, Arguments)} method. A guest language create a + * subclass with immutable fields representing the arguments passed to a guest language method. The {@link Arguments} + * object must be created immediately before a method call and it must not be stored in a field or cast to + * {@link java.lang.Object}. + */ +public class Arguments { + + /** + * Constant that can be used as an argument to + * {@link CallTarget#call(com.oracle.truffle.api.frame.PackedFrame, Arguments)} in case no arguments should be + * supplied. + */ + public static final Arguments EMPTY_ARGUMENTS = new Arguments(); + + /** + * Constructs an empty {@link Arguments} instance. Guest languages should create a subclass to specify their own arguments. + */ + protected Arguments() { + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,66 @@ +/* + * 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; + +import com.oracle.truffle.api.frame.*; + +/** + * Represents the target of a call. Instances of this interface can be created using the + * {@link TruffleRuntime#createCallTarget(com.oracle.truffle.api.nodes.RootNode, FrameDescriptor)} method. + */ +public abstract class CallTarget { + + /** + * Calls this target as a root method and without arguments. + * @return the return result of the call + */ + public final Object call() { + return call(null, Arguments.EMPTY_ARGUMENTS); + } + + /** + * Calls this target with a caller frame and no arguments. + * @param caller the caller frame + * @return the return result of the call + */ + public final Object call(PackedFrame caller) { + return call(caller, Arguments.EMPTY_ARGUMENTS); + } + + /** + * Calls this target as a root method passing arguments. + * @param arguments the arguments that should be passed to the callee + * @return the return result of the call + */ + public final Object call(Arguments arguments) { + return call(null, arguments); + } + + /** + * Calls this target passing a caller frame and arguments. + * @param caller the caller frame + * @param arguments the arguments that should be passed to the callee + * @return the return result of the call + */ + public abstract Object call(PackedFrame caller, Arguments arguments); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, 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; + +import com.oracle.truffle.api.impl.*; + +/** + * Class for obtaining the Truffle runtime singleton object of this virtual machine. + */ +public class Truffle { + + private static TruffleRuntime runtime; + + private static native TruffleRuntime initializeRuntime(); + + public static TruffleRuntime getRuntime() { + return runtime; + } + + static { + try { + runtime = initializeRuntime(); + } catch (UnsatisfiedLinkError e) { + runtime = new DefaultTruffleRuntime(); + } + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,52 @@ +/* + * 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; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Interface representing a Truffle runtime object. The runtime is responsible for creating call targets and performing optimizations for them. + */ +public interface TruffleRuntime { + /** + * Name describing this runtime implementation for debugging purposes. + * @return the name as a String + */ + String getName(); + + /** + * Creates a new call target for a given root node. + * @param rootNode the root node whose {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method represents the entry point + * @return the new call target object + */ + CallTarget createCallTarget(RootNode rootNode); + + /** + * Creates a new call target for a given root node and a given frame descriptor. + * @param rootNode the root node whose {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method represents the entry point + * @param frameDescriptor the descriptor used for creating a new frame at each invocation + * @return the new call target object + */ + CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/DefaultTypeConversion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/DefaultTypeConversion.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,49 @@ +/* + * 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.frame; + +/** + * Default type conversion semantics where a conversion is without changing any data. + */ +public final class DefaultTypeConversion implements TypeConversion { + + private static DefaultTypeConversion instance = new DefaultTypeConversion(); + + public static TypeConversion getInstance() { + return instance; + } + + private DefaultTypeConversion() { + + } + + @Override + public Class< ? > getTopType() { + return Object.class; + } + + @Override + public Object convertTo(Class< ? > targetType, Object value) { + return value; + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,135 @@ +/* + * 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.frame; + +import com.oracle.truffle.api.*; + +/** + * Represents a frame containing values of local variables of the guest language. Instances of this type must not be + * stored in a field or cast to {@link java.lang.Object}. + */ +public interface Frame { + + /** + * @return the arguments used when calling this method + */ + Arguments getArguments(); + + /** + * Read access to a local variable of type {@link Object}. + * + * @param slot the slot of the local variable + * @return the current value of the local variable + */ + Object getObject(FrameSlot slot); + + /** + * Write access to a local variable of type {@link Object}. + * + * @param slot the slot of the local variable + * @param value the new value of the local variable + */ + void setObject(FrameSlot slot, Object value); + + /** + * Read access to a local variable of type boolean. + * + * @param slot the slot of the local variable + * @return the current value of the local variable + */ + boolean getBoolean(FrameSlot slot); + + /** + * Write access to a local variable of type boolean. + * + * @param slot the slot of the local variable + * @param value the new value of the local variable + */ + void setBoolean(FrameSlot slot, boolean value); + + /** + * Read access to a local variable of type int. + * + * @param slot the slot of the local variable + * @return the current value of the local variable + */ + int getInt(FrameSlot slot); + + /** + * Write access to a local variable of type int. + * + * @param slot the slot of the local variable + * @param value the new value of the local variable + */ + void setInt(FrameSlot slot, int value); + + /** + * Read access to a local variable of type long. + * + * @param slot the slot of the local variable + * @return the current value of the local variable + */ + long getLong(FrameSlot slot); + + /** + * Write access to a local variable of type long. + * + * @param slot the slot of the local variable + * @param value the new value of the local variable + */ + void setLong(FrameSlot slot, long value); + + /** + * Read access to a local variable of type float. + * + * @param slot the slot of the local variable + * @return the current value of the local variable + */ + float getFloat(FrameSlot slot); + + /** + * Write access to a local variable of type float. + * + * @param slot the slot of the local variable + * @param value the new value of the local variable + */ + void setFloat(FrameSlot slot, float value); + + /** + * Read access to a local variable of type double. + * + * @param slot the slot of the local variable + * @return the current value of the local variable + */ + double getDouble(FrameSlot slot); + + /** + * Write access to a local variable of type double. + * + * @param slot the slot of the local variable + * @param value the new value of the local variable + */ + void setDouble(FrameSlot slot, double value); + + void updateToLatestVersion(); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,201 @@ +/* + * 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.frame; + +import java.util.*; + +/** + * Descriptor of the slots of frame objects. Multiple frame instances are associated with one such descriptor. + */ +public final class FrameDescriptor { + + protected final TypeConversion typeConversion; + private final ArrayList slots; + private FrameVersionImpl lastVersion; + private final HashMap nameToSlotMap; + + public FrameDescriptor() { + this(DefaultTypeConversion.getInstance()); + } + + public FrameDescriptor(TypeConversion typeConversion) { + this.typeConversion = typeConversion; + slots = new ArrayList<>(); + nameToSlotMap = new HashMap<>(); + lastVersion = new FrameVersionImpl(); + } + + public FrameSlot addFrameSlot(String name) { + return addFrameSlot(name, typeConversion.getTopType()); + } + + public FrameSlot addFrameSlot(String name, Class type) { + assert !nameToSlotMap.containsKey(name); + FrameSlotImpl slot = new FrameSlotImpl(this, name, slots.size(), type); + slots.add(slot); + nameToSlotMap.put(name, slot); + return slot; + } + + public FrameSlot findFrameSlot(String name) { + return nameToSlotMap.get(name); + } + + public FrameSlot findOrAddFrameSlot(String name) { + FrameSlot result = findFrameSlot(name); + if (result != null) { + return result; + } + return addFrameSlot(name); + } + + public FrameVersion getCurrentVersion() { + return lastVersion; + } + + public int getSize() { + return slots.size(); + } + + public List< ? extends FrameSlot> getSlots() { + return Collections.unmodifiableList(slots); + } + + protected void appendVersion(FrameVersionImpl newVersion) { + lastVersion.next = newVersion; + lastVersion = newVersion; + } +} + +class FrameVersionImpl implements FrameVersion { + + protected FrameVersionImpl next; + + @Override + public final FrameVersion getNext() { + return next; + } +} + +class TypeChangeFrameVersionImpl extends FrameVersionImpl implements FrameVersion.TypeChange { + + private final FrameSlotImpl slot; + private final Class< ? > oldType; + private final Class< ? > newType; + + protected TypeChangeFrameVersionImpl(FrameSlotImpl slot, Class< ? > oldType, Class< ? > newType) { + this.slot = slot; + this.oldType = oldType; + this.newType = newType; + } + + @Override + public final void applyTransformation(Frame frame) { + Object value = slot.getValue(oldType, frame); + slot.setValue(newType, frame, value); + } +} + +class FrameSlotImpl implements FrameSlot { + + private final FrameDescriptor descriptor; + private final String name; + private final int index; + private Class< ? > type; + private ArrayList listeners; + + protected FrameSlotImpl(FrameDescriptor descriptor, String name, int index, Class< ? > type) { + this.descriptor = descriptor; + this.name = name; + this.index = index; + this.type = type; + assert type != null; + } + + public String getName() { + return name; + } + + public int getIndex() { + return index; + } + + public Class< ? > getType() { + return type; + } + + protected Object getValue(Class< ? > accessType, Frame frame) { + if (accessType == Integer.class) { + return frame.getInt(this); + } else if (accessType == Long.class) { + return frame.getLong(this); + } else if (accessType == Float.class) { + return frame.getFloat(this); + } else if (accessType == Double.class) { + return frame.getDouble(this); + } else { + return frame.getObject(this); + } + } + + protected void setValue(Class< ? > accessType, Frame frame, Object value) { + Object newValue = descriptor.typeConversion.convertTo(accessType, value); + if (accessType == Integer.class) { + frame.setInt(this, (Integer) newValue); + } else if (accessType == Long.class) { + frame.setLong(this, (Long) newValue); + } else if (accessType == Float.class) { + frame.setFloat(this, (Float) newValue); + } else if (accessType == Double.class) { + frame.setDouble(this, (Double) newValue); + } else { + frame.setObject(this, newValue); + } + } + + public void setType(final Class< ? > type) { + final Class< ? > oldType = this.type; + this.type = type; + ArrayList oldListeners = this.listeners; + this.listeners = null; + if (oldListeners != null) { + for (FrameSlotTypeListener listener : oldListeners) { + listener.typeChanged(this, oldType); + } + } + descriptor.appendVersion(new TypeChangeFrameVersionImpl(this, oldType, type)); + } + + @Override + public String toString() { + return "[" + index + "," + name + "]"; + } + + @Override + public void registerOneShotTypeListener(FrameSlotTypeListener listener) { + if (listeners == null) { + listeners = new ArrayList<>(); + } + listeners.add(listener); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,34 @@ +/* + * 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.frame; + +/** + * A slot in a frame that can store a value of a given type. + */ +public interface FrameSlot { + String getName(); + int getIndex(); + Class< ? > getType(); + void setType(Class< ? > type); + void registerOneShotTypeListener(FrameSlotTypeListener listener); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeListener.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,30 @@ +/* + * 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.frame; + +/** + * Listener for the event of a type change of a frame slot. + */ +public interface FrameSlotTypeListener { + void typeChanged(FrameSlot slot, Class< ? > oldType); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameVersion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameVersion.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,41 @@ +/* + * 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.frame; + +/** + * Represents a specific version of a frame. + */ +public interface FrameVersion { + + FrameVersion getNext(); + + public interface Resize { + + int getNewSize(); + } + + public interface TypeChange { + + void applyTransformation(Frame frame); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java Tue Dec 18 17:59:32 2012 +0100 @@ -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.frame; + +/** + * Represents a materialized frame containing values of local variables of the guest language. It can be created using + * the {@link VirtualFrame#materialize()} method. Instances of this type are the only frame instances that may be stored + * in fields or cast to {@link java.lang.Object}. In contrast to a {@link VirtualFrame}, a {@link MaterializedFrame} can + * no longer be packed and it also does not provide access to the caller frame. + */ +public interface MaterializedFrame extends Frame { +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,129 @@ +/* + * 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.frame; + +import com.oracle.truffle.api.*; + +/** + * Represents a native frame without any local variables. Instances of this type must not be stored in a field or cast + * to {@link java.lang.Object}. + */ +public class NativeFrame implements VirtualFrame, PackedFrame { + + private PackedFrame caller; + private Arguments arguments; + + public NativeFrame(PackedFrame caller, Arguments arguments) { + this.caller = caller; + this.arguments = arguments; + } + + @Override + public Arguments getArguments() { + return arguments; + } + + @Override + public Object getObject(FrameSlot slot) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public void setObject(FrameSlot slot, Object value) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public boolean getBoolean(FrameSlot slot) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public void setBoolean(FrameSlot slot, boolean value) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public int getInt(FrameSlot slot) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public void setInt(FrameSlot slot, int value) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public long getLong(FrameSlot slot) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public void setLong(FrameSlot slot, long value) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public float getFloat(FrameSlot slot) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public void setFloat(FrameSlot slot, float value) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public double getDouble(FrameSlot slot) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public void setDouble(FrameSlot slot, double value) { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public PackedFrame pack() { + return this; + } + + @Override + public PackedFrame getCaller() { + return caller; + } + + @Override + public MaterializedFrame materialize() { + throw new UnsupportedOperationException("native frame"); + } + + @Override + public VirtualFrame unpack() { + return this; + } + + @Override + public void updateToLatestVersion() { + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,37 @@ +/* + * 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.frame; + +/** + * Represents a packed frame that represents a virtual frame. A packed frame instance can be retrieved with the + * {@link VirtualFrame#pack()} method. It can be converted back into a virtual frame using {@link PackedFrame#unpack()}. + * Instances of this type must not be stored in a field or cast to {@link java.lang.Object}. + */ +public interface PackedFrame { + + /** + * Unpacks this frame and converts it back to a virtual frame. + * @return the virtual frame that was the content of this packed frame + */ + VirtualFrame unpack(); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/TypeConversion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/TypeConversion.java Tue Dec 18 17:59:32 2012 +0100 @@ -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.frame; + +/** + * Interface for defining type conversions for frame slot values. + */ +public interface TypeConversion { + Class getTopType(); + + Object convertTo(Class targetType, Object value); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,60 @@ +/* + * 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.frame; + +import com.oracle.truffle.api.*; + +/** + * Represents a frame containing values of local variables of the guest language. Instances of this type must not be + * stored in a field or cast to {@link java.lang.Object}. If this is necessary, the frame must be explicitly converted + * into a materialized frame using the {@link VirtualFrame#materialize()} method. Whenever fast access to the local + * variables of a frame is no longer necessary, a virtual frame should be converted into a packed frame using the + * {@link VirtualFrame#pack()} method. + */ +public interface VirtualFrame extends Frame { + + /** + * Converts this virtual frame into a packed frame that has no longer direct access to the local variables. This + * packing is an important hint to the Truffle optimizer and therefore passing around a {@link PackedFrame} should + * be preferred over passing around a {@link VirtualFrame} when the probability that an unpacking will occur is low. + * + * @return the packed frame + */ + PackedFrame pack(); + + /** + * Accesses the caller frame passed in via {@link CallTarget#call}. To get full access, it must be first unpacked + * using {@link PackedFrame#unpack()}. + * + * @return the caller frame or null if this was a root method call + */ + PackedFrame getCaller(); + + /** + * Materializes this frame, which allows it to be stored in a field or cast to {@link java.lang.Object}. The frame + * however looses the ability to be packed or to access the caller frame. + * + * @return the new materialized frame + */ + MaterializedFrame materialize(); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,49 @@ +/* + * 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.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +final class DefaultCallTarget extends CallTarget { + + protected final RootNode rootNode; + protected final FrameDescriptor frameDescriptor; + + DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) { + this.rootNode = function; + this.frameDescriptor = frameDescriptor; + } + + @Override + public String toString() { + return "DefaultCallTarget " + rootNode; + } + + @Override + public Object call(PackedFrame caller, Arguments args) { + VirtualFrame frame = new DefaultVirtualFrame(frameDescriptor, caller, args); + return rootNode.execute(frame); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,104 @@ +/* + * 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.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +final class DefaultMaterializedFrame implements MaterializedFrame { + private final DefaultVirtualFrame wrapped; + + protected DefaultMaterializedFrame(DefaultVirtualFrame wrapped) { + this.wrapped = wrapped; + } + + @Override + public Arguments getArguments() { + return wrapped.getArguments(); + } + + @Override + public Object getObject(FrameSlot slot) { + return wrapped.getObject(slot); + } + + @Override + public void setObject(FrameSlot slot, Object value) { + wrapped.setObject(slot, value); + } + + @Override + public boolean getBoolean(FrameSlot slot) { + return wrapped.getBoolean(slot); + } + + @Override + public void setBoolean(FrameSlot slot, boolean value) { + wrapped.setBoolean(slot, value); + } + + @Override + public int getInt(FrameSlot slot) { + return wrapped.getInt(slot); + } + + @Override + public void setInt(FrameSlot slot, int value) { + wrapped.setInt(slot, value); + } + + @Override + public long getLong(FrameSlot slot) { + return wrapped.getLong(slot); + } + + @Override + public void setLong(FrameSlot slot, long value) { + wrapped.setLong(slot, value); + } + + @Override + public float getFloat(FrameSlot slot) { + return wrapped.getFloat(slot); + } + + @Override + public void setFloat(FrameSlot slot, float value) { + wrapped.setFloat(slot, value); + } + + @Override + public double getDouble(FrameSlot slot) { + return wrapped.getDouble(slot); + } + + @Override + public void setDouble(FrameSlot slot, double value) { + wrapped.setDouble(slot, value); + } + + @Override + public void updateToLatestVersion() { + wrapped.updateToLatestVersion(); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultPackedFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultPackedFrame.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,38 @@ +/* + * 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.impl; + +import com.oracle.truffle.api.frame.*; + +final class DefaultPackedFrame implements PackedFrame { + private final DefaultVirtualFrame wrapped; + + protected DefaultPackedFrame(DefaultVirtualFrame wrapped) { + this.wrapped = wrapped; + } + + @Override + public VirtualFrame unpack() { + return wrapped; + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,48 @@ +/* + * 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.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Default implementation of the Truffle runtime if the virtual machine does not provide a better performing alternative. + */ +public final class DefaultTruffleRuntime implements TruffleRuntime { + + @Override + public String getName() { + return "Default Truffle Runtime"; + } + + @Override + public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) { + return new DefaultCallTarget(rootNode, frameDescriptor); + } + + @Override + public CallTarget createCallTarget(RootNode rootNode) { + return createCallTarget(rootNode, new FrameDescriptor()); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,194 @@ +/* + * 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.impl; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +final class DefaultVirtualFrame implements VirtualFrame { + + private static final Object UNDEFINED_OBJECT = null; + private static final Boolean UNDEFINED_BOOLEAN = false; + private static final Integer UNDEFINED_INTEGER = 0; + private static final Float UNDEFINED_FLOAT = 0.0f; + private static final Long UNDEFINED_LONG = 0L; + private static final Double UNDEFINED_DOUBLE = 0.0d; + + private final FrameDescriptor descriptor; + private final PackedFrame caller; + private final Arguments arguments; + private FrameVersion currentVersion; + protected Object[] locals; + protected Class[] tags; + + DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { + this.descriptor = descriptor; + this.caller = caller; + this.arguments = arguments; + this.currentVersion = descriptor.getCurrentVersion(); + this.locals = new Object[descriptor.getSize()]; + // The tags are only needed for assertion checking, so initialize the field only when assertions are enabled + assert (this.tags = new Class[descriptor.getSize()]) != null; + } + + @Override + public Arguments getArguments() { + return arguments; + } + + @Override + public PackedFrame getCaller() { + return caller; + } + + @Override + public PackedFrame pack() { + return new DefaultPackedFrame(this); + } + + @Override + public MaterializedFrame materialize() { + return new DefaultMaterializedFrame(this); + } + + @Override + public Object getObject(FrameSlot slot) { + return get(slot, Object.class, UNDEFINED_OBJECT); + } + + @Override + public void setObject(FrameSlot slot, Object value) { + set(slot, Object.class, value); + } + + @Override + public boolean getBoolean(FrameSlot slot) { + return (Boolean) get(slot, Float.class, UNDEFINED_BOOLEAN); + } + + @Override + public void setBoolean(FrameSlot slot, boolean value) { + set(slot, Float.class, value); + } + + @Override + public int getInt(FrameSlot slot) { + return (Integer) get(slot, Integer.class, UNDEFINED_INTEGER); + } + + @Override + public void setInt(FrameSlot slot, int value) { + set(slot, Integer.class, value); + } + + @Override + public long getLong(FrameSlot slot) { + return (Long) get(slot, Long.class, UNDEFINED_LONG); + } + + @Override + public void setLong(FrameSlot slot, long value) { + set(slot, Long.class, value); + } + + @Override + public float getFloat(FrameSlot slot) { + return (Float) get(slot, Float.class, UNDEFINED_FLOAT); + } + + @Override + public void setFloat(FrameSlot slot, float value) { + set(slot, Float.class, value); + } + + @Override + public double getDouble(FrameSlot slot) { + return (Double) get(slot, Double.class, UNDEFINED_DOUBLE); + } + + @Override + public void setDouble(FrameSlot slot, double value) { + set(slot, Double.class, value); + } + + private Object get(FrameSlot slot, Class< ? > accessType, Object defaultValue) { + Object value = locals[slot.getIndex()]; + assert verifyGet(slot, accessType, value); + if (value == null) { + return defaultValue; + } else { + return value; + } + } + + private boolean verifyGet(FrameSlot slot, Class< ? > accessType, Object value) { + assert descriptor.getSlots().get(slot.getIndex()) == slot; + Class< ? > tag = tags[slot.getIndex()]; + if (value == null) { + assert tag == null || tag == Object.class; + } else { + assert tag == accessType : "Local variable " + slot + " was written with set" + tag.getSimpleName() + ", but is read with get" + accessType.getSimpleName(); + } + return true; + } + + private void set(FrameSlot slot, Class< ? > accessType, Object value) { + assert verifySet(slot, accessType, value); + locals[slot.getIndex()] = value; + } + + private boolean verifySet(FrameSlot slot, Class< ? > accessType, Object value) { + assert descriptor.getSlots().get(slot.getIndex()) == slot; + tags[slot.getIndex()] = accessType; + assert accessType.isAssignableFrom(slot.getType()) : "Local variable " + slot + ": " + accessType + " is not assignable from " + slot.getType(); + if (value == null) { + assert accessType == Object.class; + } else { + assert slot.getType().isAssignableFrom(value.getClass()) : "Local variable " + slot + ": " + slot.getType() + " is not assignable from " + value.getClass(); + } + return true; + } + + @Override + public void updateToLatestVersion() { + if (currentVersion.getNext() != null) { + doUpdateToLatestVersion(); + } + } + + private void doUpdateToLatestVersion() { + FrameVersion version = currentVersion; + while (version.getNext() != null) { + version = version.getNext(); + if (version instanceof FrameVersion.TypeChange) { + ((FrameVersion.TypeChange) version).applyTransformation(this); + } else if (version instanceof FrameVersion.Resize) { + int newSize = ((FrameVersion.Resize) version).getNewSize(); + locals = Arrays.copyOf(locals, newSize); + } + } + currentVersion = version; + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/ExactMath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/ExactMath.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,91 @@ +/* + * 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.intrinsics; + +/** + * This class contains methods that will be part of java.lang.Math starting with JDK 8. Until JDK 8 is release, we + * duplicate them here because they are generally useful for dynamic language implementations. + */ +public class ExactMath { + + public static int addExact(int x, int y) { + int r = x + y; + // HD 2-12 Overflow iff both arguments have the opposite sign of the result + if (((x ^ r) & (y ^ r)) < 0) { + throw new ArithmeticException("integer overflow"); + } + return r; + } + + public static long addExact(long x, long y) { + long r = x + y; + // HD 2-12 Overflow iff both arguments have the opposite sign of the result + if (((x ^ r) & (y ^ r)) < 0) { + throw new ArithmeticException("long overflow"); + } + return r; + } + + public static int subtractExact(int x, int y) { + int r = x - y; + // HD 2-12 Overflow iff the arguments have different signs and + // the sign of the result is different than the sign of x + if (((x ^ y) & (x ^ r)) < 0) { + throw new ArithmeticException("integer overflow"); + } + return r; + } + + public static long subtractExact(long x, long y) { + long r = x - y; + // HD 2-12 Overflow iff the arguments have different signs and + // the sign of the result is different than the sign of x + if (((x ^ y) & (x ^ r)) < 0) { + throw new ArithmeticException("long overflow"); + } + return r; + } + + public static int multiplyExact(int x, int y) { + long r = (long) x * (long) y; + if ((int) r != r) { + throw new ArithmeticException("long overflow"); + } + return (int) r; + } + + public static long multiplyExact(long x, long y) { + long r = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + if (((ax | ay) >>> 31 != 0)) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((y != 0) && (r / y != x)) || (x == Long.MIN_VALUE && y == -1)) { + throw new ArithmeticException("long overflow"); + } + } + return r; + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/TruffleIntrinsics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/TruffleIntrinsics.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,45 @@ +/* + * 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.intrinsics; + +/** + * Predefined Truffle intrinsics that allow direct influence of the generated machine code. + */ +public final class TruffleIntrinsics { + + /** + * Specifies that the compiler should put a deoptimization point at this position that will continue execution in the interpreter. + * Should be used to cut off cold paths that should not be part of the compiled machine code. + */ + public static void deoptimize() { + } + + /** + * Checks whether the Thread has been interrupted in the interpreter in order to avoid endless loops. The compiled code may choose a more efficient implementation. + */ + public static void checkThreadInterrupted() { + if (Thread.currentThread().isInterrupted()) { + throw new RuntimeException("Timeout"); + } + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,33 @@ +/* + * 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 java.lang.annotation.*; + +/** + * Specifies for a method that the loops with constant number of invocations should be fully unrolled. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ExplodeLoop { +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,385 @@ +/* + * 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 java.io.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.net.*; +import java.util.*; + +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.*; +import javax.xml.transform.stream.*; + +import org.w3c.dom.*; + +/** + * Utility class for creating output for the ideal graph visualizer. + */ +public class GraphPrintVisitor { + + public static final String GraphVisualizerAddress = "127.0.0.1"; + public static final int GraphVisualizerPort = 4444; + + private Document dom; + private Map nodeMap; + private List edgeList; + private Map prevNodeMap; + private int id; + private Element graphDocument; + private Element groupElement; + private Element graphElement; + private Element nodesElement; + private Element edgesElement; + + public GraphPrintVisitor() { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + + dom = db.newDocument(); + } catch (ParserConfigurationException ex) { + System.out.println("Error while trying to instantiate DocumentBuilder " + ex); + } + + graphDocument = dom.createElement("graphDocument"); + dom.appendChild(graphDocument); + } + + public GraphPrintVisitor beginGroup(String groupName) { + groupElement = dom.createElement("group"); + graphDocument.appendChild(groupElement); + Element properties = dom.createElement("properties"); + groupElement.appendChild(properties); + + if (!groupName.isEmpty()) { + // set group name + Element propName = dom.createElement("p"); + propName.setAttribute("name", "name"); + propName.setTextContent(groupName); + properties.appendChild(propName); + } + + // forget old nodes + nodeMap = prevNodeMap = null; + edgeList = null; + + return this; + } + + public GraphPrintVisitor beginGraph(String graphName) { + if (null == groupElement) { + beginGroup(""); + } else if (null != prevNodeMap) { + // TODO: difference (create removeNode,removeEdge elements) + } + + graphElement = dom.createElement("graph"); + groupElement.appendChild(graphElement); + Element properties = dom.createElement("properties"); + graphElement.appendChild(properties); + nodesElement = dom.createElement("nodes"); + graphElement.appendChild(nodesElement); + edgesElement = dom.createElement("edges"); + graphElement.appendChild(edgesElement); + + // set graph name + Element propName = dom.createElement("p"); + propName.setAttribute("name", "name"); + propName.setTextContent(graphName); + properties.appendChild(propName); + + // save old nodes + prevNodeMap = nodeMap; + nodeMap = new HashMap<>(); + edgeList = new ArrayList<>(); + + return this; + } + + @Override + public String toString() { + if (null != dom) { + try { + Transformer tr = TransformerFactory.newInstance().newTransformer(); + tr.setOutputProperty(OutputKeys.INDENT, "yes"); + tr.setOutputProperty(OutputKeys.METHOD, "xml"); + tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + StringWriter strWriter = new StringWriter(); + tr.transform(new DOMSource(dom), new StreamResult(strWriter)); + return strWriter.toString(); + } catch (TransformerException e) { + e.printStackTrace(); + } + } + return ""; + } + + public void printToFile(File f) { + try { + Transformer tr = TransformerFactory.newInstance().newTransformer(); + tr.setOutputProperty(OutputKeys.INDENT, "yes"); + tr.setOutputProperty(OutputKeys.METHOD, "xml"); + tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + tr.transform(new DOMSource(dom), new StreamResult(new FileOutputStream(f))); + } catch (TransformerException | FileNotFoundException e) { + e.printStackTrace(); + } + } + + public void printToSysout() { + try { + Transformer tr = TransformerFactory.newInstance().newTransformer(); + tr.setOutputProperty(OutputKeys.INDENT, "yes"); + tr.setOutputProperty(OutputKeys.METHOD, "xml"); + tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + tr.transform(new DOMSource(dom), new StreamResult(System.out)); + } catch (TransformerException e) { + e.printStackTrace(); + } + } + + public void printToNetwork() { + try { + Transformer tr = TransformerFactory.newInstance().newTransformer(); + tr.setOutputProperty(OutputKeys.METHOD, "xml"); + + Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort); + BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000); + tr.transform(new DOMSource(dom), new StreamResult(stream)); + } catch (TransformerException | IOException e) { + e.printStackTrace(); + } + } + + private String nextId() { + return String.valueOf(id++); + } + + private String oldOrNextId(Object node) { + if (null != prevNodeMap && prevNodeMap.containsKey(node)) { + Element nodeElem = prevNodeMap.get(node); + return nodeElem.getAttribute("id"); + } else { + return nextId(); + } + } + + protected Element getElementByObject(Object op) { + return nodeMap.get(op); + } + + protected void createElementForNode(Object node) { + boolean exists = nodeMap.containsKey(node); + if (!exists || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) { + Element nodeElem = dom.createElement("node"); + nodeElem.setAttribute("id", !exists ? oldOrNextId(node) : nextId()); + nodeMap.put(node, nodeElem); + Element properties = dom.createElement("properties"); + nodeElem.appendChild(properties); + nodesElement.appendChild(nodeElem); + + setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", "")); + NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class); + if (nodeInfo != null && !nodeInfo.shortName().isEmpty()) { + setNodeProperty(node, "shortName", nodeInfo.shortName()); + } + setNodeProperty(node, "nodeType", (Node.class.isAssignableFrom(node.getClass()) ? Node.class.getSimpleName() : "other")); + setNodeProperty(node, "nodeClass", node.getClass().getSimpleName()); + copyDebugProperties(node); // TODO: may overwrite property "name"? (currently allowed) + readNodeProperties(node); + } + } + + private Element getPropertyElement(Object node, String propertyName) { + Element nodeElem = getElementByObject(node); + Element propertiesElem = (Element) nodeElem.getElementsByTagName("properties").item(0); + if (propertiesElem == null) { + return null; + } + + NodeList propList = propertiesElem.getElementsByTagName("p"); + for (int i = 0; i < propList.getLength(); i++) { + Element p = (Element) propList.item(i); + if (propertyName.equals(p.getAttribute("name"))) { + return p; + } + } + return null; + } + + protected void setNodeProperty(Object node, String propertyName, Object value) { + Element nodeElem = getElementByObject(node); + Element propElem = getPropertyElement(node, propertyName); // if property exists, replace its value + if (null == propElem) { // if property doesn't exist, create one + propElem = dom.createElement("p"); + propElem.setAttribute("name", propertyName); + nodeElem.getElementsByTagName("properties").item(0).appendChild(propElem); + } + propElem.setTextContent(String.valueOf(value)); + } + + private void copyDebugProperties(Object node) { + if (node instanceof Node) { + Map debugProperties = ((Node) node).getDebugProperties(); + for (Map.Entry property : debugProperties.entrySet()) { + setNodeProperty(node, property.getKey(), property.getValue()); + } + } + } + + private void readNodeProperties(Object node) { + Field[] fields = NodeUtil.getAllFields(node.getClass()); + for (Field field : fields) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + if (Node.class.isAssignableFrom(field.getType()) || (field.getType().getComponentType() != null && Node.class.isAssignableFrom(field.getType()))) { + continue; + } + String key = field.getName(); + if (field.getAnnotation(HiddenField.class) == null && getPropertyElement(node, key) == null) { + try { + field.setAccessible(true); + Object value = field.get(node); + setNodeProperty(node, key, value); + } catch (IllegalArgumentException | IllegalAccessException e) { + assert false : e; + } + } + } + } + + protected void connectNodes(Object a, Object b) { + if (nodeMap.get(a) == null || nodeMap.get(b) == null) { + return; + } + + String fromId = nodeMap.get(a).getAttribute("id"); + String toId = nodeMap.get(b).getAttribute("id"); + + // count existing to-edges + int count = 0; + for (Element e : edgeList) { + if (e.getAttribute("to").equals(toId)) { + ++count; + } + } + + Element edgeElem = dom.createElement("edge"); + edgeElem.setAttribute("from", fromId); + edgeElem.setAttribute("to", toId); + edgeElem.setAttribute("index", String.valueOf(count)); + edgesElement.appendChild(edgeElem); + edgeList.add(edgeElem); + } + + public GraphPrintVisitor visit(Object node) { + if (null == graphElement) { + beginGraph("truffle tree"); + } + + // if node is visited once again, skip + if (getElementByObject(node) == null || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) { + visitAny(node); + } + + return this; + } + + private void visitAny(Object node) { + // respect node's custom handler + if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) { + return; + } + if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) { + Class gpHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler(); + try { + GraphPrintHandler gpHandler = gpHandlerClass.newInstance(); + gpHandler.visit(node, new GraphPrintAdapter()); + } catch (InstantiationException e) { + assert false; + } catch (IllegalAccessException e) { + assert false; + } + return; + } + + // default handler + createElementForNode(node); + + List children = NodeUtil.findNodeChildren(node); + for (Object child : children) { + if (child == null) { + continue; + } else if (child instanceof Node) { + visit(child); + } else { + continue; + } + connectNodes(node, child); + } + } + + public class GraphPrintAdapter { + public void createElementForNode(Object node) { + GraphPrintVisitor.this.createElementForNode(node); + } + public void visit(Object node) { + GraphPrintVisitor.this.visit(node); + } + public void connectNodes(Object node, Object child) { + GraphPrintVisitor.this.connectNodes(node, child); + } + public void setNodeProperty(Object node, String propertyName, Object value) { + GraphPrintVisitor.this.setNodeProperty(node, propertyName, value); + } + } + + public interface GraphPrintHandler { + void visit(Object node, GraphPrintAdapter gPrinter); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface CustomGraphPrintHandler { + Class handler(); + } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface NullGraphPrintHandler { + } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface GraphDuplicate { + } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface HiddenField { + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,212 @@ +/* + * 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 java.lang.annotation.*; +import java.util.*; + +/** + * Abstract base class for all Truffle nodes. + */ +public abstract class Node implements Cloneable { + + /** + * Utility constant representing an empty node array. + */ + public static final Node[] EMPTY_ARRAY = new Node[0]; + + private Node parent; + + /** + * Marks array fields that are children of this node. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface Children { + } + + /** + * Marks fields that represent child nodes of this node. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface Child { + } + + /** + * Method that updates the link to the parent in the array of specified new child nodes to this node. + * + * @param newChildren the array of new children whose parent should be updated + * @return the array of new children + */ + protected final T[] adoptChildren(T[] newChildren) { + if (newChildren != null) { + for (T n : newChildren) { + adoptChild(n); + } + } + return newChildren; + } + + /** + * Method that updates the link to the parent in the specified new child node to this node. + * + * @param newChild the new child whose parent should be updated + * @return the new child + */ + protected final T adoptChild(T newChild) { + if (newChild != null) { + ((Node) newChild).parent = this; + } + return newChild; + } + + /** + * Returns properties of this node interesting for debugging and can be overwritten by subclasses to add their own + * custom properties. + * + * @return the properties as a key/value hash map + */ + public Map getDebugProperties() { + Map properties = new HashMap<>(); + return properties; + } + + /** + * The current parent node of this node. + * + * @return the parent node + */ + public final Node getParent() { + return parent; + } + + /** + * Replaces one child of this node with another node. + * + * @param oldChild the old child + * @param newChild the new child that should replace the old child + * @return the new child + */ + public final T replaceChild(T oldChild, T newChild) { + NodeUtil.replaceChild(this, oldChild, newChild); + adoptChild(newChild); + return newChild; + } + + /** + * Replaces this node with another node. + * + * @param newNode the new node that is the replacement + * @param reason a description of the reason for the replacement + * @return the new node + */ + @SuppressWarnings({"unchecked"}) + public T replace(T newNode, String reason) { + assert this.getParent() != null; + return (T) this.getParent().replaceChild(this, newNode); + } + + /** + * Replaces this node with another node. + * + * @param newNode the new node that is the replacement + * @return the new node + */ + public T replace(T newNode) { + return replace(newNode, ""); + } + + /** + * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all child nodes. + * + * @param nodeVisitor the visitor + */ + public final void accept(NodeVisitor nodeVisitor) { + if (nodeVisitor.visit(this)) { + for (Node child : this.getChildren()) { + if (child != null) { + child.accept(nodeVisitor); + } + } + } + } + + /** + * Iterator over the children of this node. + * + * @return the iterator + */ + public final Iterable getChildren() { + final Node node = this; + return new Iterable() { + + public Iterator iterator() { + return new NodeUtil.NodeIterator(node); + } + }; + } + + /** + * Creates a shallow copy of this node. + * + * @return the new copy + */ + public Node copy() { + try { + return (Node) super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + + /** + * This method must never be called. It enforces that {@link Object#clone} is not directly called by subclasses. + * Use the {@link #copy()} method instead. + */ + @Override + @Deprecated + protected final Object clone() throws CloneNotSupportedException { + throw new IllegalStateException("This method should never be called, use the copy method instead!"); + } + + /** + * Converts this node to a textual representation useful for debugging. + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getSimpleName()); + Map properties = getDebugProperties(); + boolean hasProperties = false; + for (Map.Entry entry : properties.entrySet()) { + sb.append(hasProperties ? "," : "<"); + hasProperties = true; + sb.append(entry.getKey()).append("=").append(entry.getValue()); + } + if (hasProperties) { + sb.append(">"); + } + sb.append("@").append(Integer.toHexString(hashCode())); + return sb.toString(); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,39 @@ +/* + * 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 java.lang.annotation.*; + +/** + * Annotation for providing additional information on nodes. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface NodeInfo { + + /** + * Short name representing the node that can be used for debugging. + * @return the short name + */ + String shortName() default ""; +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,702 @@ +/* + * 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 java.io.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; + +import sun.misc.*; + +/** + * Utility class that manages the special access methods for node instances. + */ +public class NodeUtil { + + public static final class NodeClass { + + private final Class parentClass; + private final long[] nodeFieldOffsets; + private final Class[] nodeFieldClasses; + private final long[] nodeArrayFieldOffsets; + private final Class[] nodeArrayFieldClasses; + private final long parentOffset; + private final long[] nodeDataFieldOffsets; + private final Class< ? >[] nodeDataFieldClasses; + + private static final Map, NodeClass> nodeClasses = new IdentityHashMap<>(); + + public static NodeClass get(Class< ? > clazz) { + NodeClass nodeClass = nodeClasses.get(clazz); + if (nodeClass == null) { + nodeClass = new NodeClass(clazz); + nodeClasses.put(clazz, nodeClass); + } + return nodeClass; + } + + private NodeClass(Class< ? > clazz) { + // scan object fields + Class< ? > parentClassTmp = null; + List nodeFieldOffsetsList = new ArrayList<>(); + List> nodeFieldClassesList = new ArrayList<>(); + List nodeArrayFieldOffsetsList = new ArrayList<>(); + List> nodeArrayFieldClassesList = new ArrayList<>(); + List nodeDataFieldOffsetList = new ArrayList<>(); + List> nodeDataFieldClassList = new ArrayList<>(); + Field[] fields = getAllFields(clazz); + long parentOffsetTemp = -1; + for (Field field : fields) { + if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) { + continue; + } + + // Node fields + if (Node.class.isAssignableFrom(field.getType())) { + if (!field.getName().equals("parent")) { + nodeFieldOffsetsList.add(unsafe.objectFieldOffset(field)); + nodeFieldClassesList.add(field.getType()); + } else { + parentOffsetTemp = unsafe.objectFieldOffset(field); + parentClassTmp = field.getType(); + } + } else if (field.getType().getComponentType() != null && Node.class.isAssignableFrom(field.getType().getComponentType())) { + nodeArrayFieldOffsetsList.add(unsafe.objectFieldOffset(field)); + nodeArrayFieldClassesList.add(field.getType()); + } else { + nodeDataFieldOffsetList.add(unsafe.objectFieldOffset(field)); + nodeDataFieldClassList.add(field.getType()); + } + } + this.parentClass = parentClassTmp; + this.nodeFieldOffsets = toLongArray(nodeFieldOffsetsList); + this.nodeFieldClasses = nodeFieldClassesList.toArray(new Class[nodeFieldClassesList.size()]); + this.nodeArrayFieldOffsets = toLongArray(nodeArrayFieldOffsetsList); + this.nodeArrayFieldClasses = nodeArrayFieldClassesList.toArray(new Class[nodeArrayFieldClassesList.size()]); + this.nodeDataFieldOffsets = toLongArray(nodeDataFieldOffsetList); + this.nodeDataFieldClasses = nodeDataFieldClassList.toArray(new Class< ? >[nodeDataFieldClassList.size()]); + + this.parentOffset = parentOffsetTemp; + } + } + + public static class NodeIterator implements Iterator { + + private final Node node; + private final NodeClass nodeClass; + private final int childrenCount; + private int index; + + public NodeIterator(Node node) { + this(node, 0); + } + + public NodeIterator(Node node, int index) { + this.node = node; + this.index = index; + this.nodeClass = NodeClass.get(node.getClass()); + this.childrenCount = childrenCount(); + } + + private int childrenCount() { + int nodeCount = nodeClass.nodeFieldOffsets.length; + for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) { + Node[] children = ((Node[]) unsafe.getObject(node, fieldOffset)); + if (children != null) { + nodeCount += children.length; + } + } + return nodeCount; + } + + private Node nodeAt(int idx) { + int nodeCount = nodeClass.nodeFieldOffsets.length; + if (idx < nodeCount) { + return (Node) unsafe.getObject(node, nodeClass.nodeFieldOffsets[idx]); + } else { + for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) { + Node[] nodeArray = (Node[]) unsafe.getObject(node, fieldOffset); + if (idx < nodeCount + nodeArray.length) { + return nodeArray[idx - nodeCount]; + } + nodeCount += nodeArray.length; + } + } + return null; + } + + private void forward() { + if (index < childrenCount) { + index++; + } + } + + @Override + public boolean hasNext() { + return index < childrenCount; + } + + @Override + public Node next() { + try { + return nodeAt(index); + } finally { + forward(); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + private static long[] toLongArray(List list) { + long[] array = new long[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; + } + + private static final Unsafe unsafe = getUnsafe(); + + private static Unsafe getUnsafe() { + try { + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } + + @SuppressWarnings("unchecked") + public static T cloneNode(T orig) { + Class< ? extends Node> clazz = orig.getClass(); + NodeClass nodeClass = NodeClass.get(clazz); + Node clone = orig.copy(); + if (clone == null) { + return null; + } + + unsafe.putObject(clone, nodeClass.parentOffset, null); + + for (long fieldOffset : nodeClass.nodeFieldOffsets) { + Node child = (Node) unsafe.getObject(orig, fieldOffset); + if (child != null) { + Node clonedChild = cloneNode(child); + if (clonedChild == null) { + return null; + } + + unsafe.putObject(clonedChild, nodeClass.parentOffset, clone); + unsafe.putObject(clone, fieldOffset, clonedChild); + } + } + for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) { + Node[] children = (Node[]) unsafe.getObject(orig, fieldOffset); + if (children != null) { + Node[] clonedChildren = new Node[children.length]; + for (int i = 0; i < children.length; i++) { + Node clonedChild = cloneNode(children[i]); + if (clonedChild == null) { + return null; + } + + clonedChildren[i] = clonedChild; + unsafe.putObject(clonedChild, nodeClass.parentOffset, clone); + } + unsafe.putObject(clone, fieldOffset, clonedChildren); + } + } + return (T) clone; + } + + public static List findNodeChildren(Object node) { + List nodes = new ArrayList<>(); + NodeClass nodeClass = NodeClass.get(node.getClass()); + + for (long fieldOffset : nodeClass.nodeFieldOffsets) { + Object child = unsafe.getObject(node, fieldOffset); + if (child != null) { + nodes.add(child); + } + } + for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) { + Object[] children = (Object[]) unsafe.getObject(node, fieldOffset); + if (children != null) { + nodes.addAll(Arrays.asList(children)); + } + } + + return nodes; + } + + public static void replaceChild(Node parent, Node oldChild, Node newChild) { + NodeClass nodeClass = NodeClass.get(parent.getClass()); + + for (long fieldOffset : nodeClass.nodeFieldOffsets) { + if (unsafe.getObject(parent, fieldOffset) == oldChild) { + unsafe.putObject(parent, fieldOffset, newChild); + } + } + for (long fieldOffset : nodeClass.nodeArrayFieldOffsets) { + Node[] array = (Node[]) unsafe.getObject(parent, fieldOffset); + if (array != null) { + for (int i = 0; i < array.length; i++) { + if (array[i] == oldChild) { + array[i] = newChild; + return; + } + } + } + } + } + + public static long[] getNodeDataFieldOffsets(Class< ? > nodeClass) { + NodeClass clazz = NodeClass.get(nodeClass); + return Arrays.copyOf(clazz.nodeDataFieldOffsets, clazz.nodeDataFieldClasses.length); + } + + public static Class[] getNodeDataFieldClasses(Class< ? > nodeClass) { + NodeClass clazz = NodeClass.get(nodeClass); + return Arrays.copyOf(clazz.nodeDataFieldClasses, clazz.nodeDataFieldClasses.length); + } + + public static long getNodeParentOffset(Class< ? > nodeClass) { + NodeClass clazz = NodeClass.get(nodeClass); + return clazz.parentOffset; + } + + /** Returns the number of Node field declarations in the class hierarchy. */ + public static long[] getNodeFieldOffsets(Class< ? > nodeClass) { + NodeClass clazz = NodeClass.get(nodeClass); + return Arrays.copyOf(clazz.nodeFieldOffsets, clazz.nodeFieldOffsets.length); + } + + /** Returns the number of Node[] declaration in the class hierarchy. */ + public static long[] getNodeFieldArrayOffsets(Class< ? > nodeClass) { + NodeClass clazz = NodeClass.get(nodeClass); + return Arrays.copyOf(clazz.nodeArrayFieldOffsets, clazz.nodeArrayFieldOffsets.length); + } + + public static Class[] getNodeFieldArrayClasses(Class< ? > nodeClass) { + NodeClass clazz = NodeClass.get(nodeClass); + return Arrays.copyOf(clazz.nodeArrayFieldClasses, clazz.nodeArrayFieldClasses.length); + } + + public static Class getNodeParentClass(Class< ? > nodeClass) { + return NodeClass.get(nodeClass).parentClass; + } + + public static Class[] getNodeFieldClasses(Class< ? > nodeClass) { + NodeClass clazz = NodeClass.get(nodeClass); + return Arrays.copyOf(clazz.nodeFieldClasses, clazz.nodeFieldClasses.length); + } + + /** Returns all declared fields in the class hierarchy. */ + public static Field[] getAllFields(Class< ? extends Object> clazz) { + Field[] declaredFields = clazz.getDeclaredFields(); + if (clazz.getSuperclass() != null) { + return concat(getAllFields(clazz.getSuperclass()), declaredFields); + } + return declaredFields; + } + + public static T[] concat(T[] first, T[] second) { + T[] result = Arrays.copyOf(first, first.length + second.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } + + /** find annotation in class/interface hierarchy. */ + public static T findAnnotation(Class< ? > clazz, Class annotationClass) { + if (clazz.getAnnotation(annotationClass) != null) { + return clazz.getAnnotation(annotationClass); + } else { + for (Class< ? > intf : clazz.getInterfaces()) { + if (intf.getAnnotation(annotationClass) != null) { + return intf.getAnnotation(annotationClass); + } + } + if (clazz.getSuperclass() != null) { + return findAnnotation(clazz.getSuperclass(), annotationClass); + } + } + return null; + } + + @SuppressWarnings("unchecked") + public static T findParent(final Node start, final Class clazz) { + assert start != null; + if (clazz.isInstance(start.getParent())) { + return (T) start.getParent(); + } else { + return start.getParent() != null ? findParent(start.getParent(), clazz) : null; + } + } + + @SuppressWarnings("unchecked") + public static I findParentInterface(final Node start, final Class clazz) { + assert start != null; + if (clazz.isInstance(start.getParent())) { + return (I) start.getParent(); + } else { + return (start.getParent() != null ? findParentInterface(start.getParent(), clazz) : null); + } + } + + @SuppressWarnings("unchecked") + public static T findFirstNodeInstance(Object root, Class clazz) { + List childNodes = findNodeChildren(root); + + for (Object childNode : childNodes) { + if (clazz.isInstance(childNode)) { + return (T) childNode; + } else { + return findFirstNodeInstance(childNode, clazz); + } + } + return null; + } + + public static List findAllNodeInstances(final Node root, final Class clazz) { + final List nodeList = new ArrayList<>(); + root.accept(new NodeVisitor() { + + @SuppressWarnings("unchecked") + @Override + public boolean visit(Node node) { + if (clazz.isInstance(node)) { + nodeList.add((T) node); + } + return true; + } + }); + return nodeList; + } + + // Don't visit found node instances. + public static List findNodeInstancesShallow(final Node root, final Class clazz) { + final List nodeList = new ArrayList<>(); + root.accept(new NodeVisitor() { + + @SuppressWarnings("unchecked") + @Override + public boolean visit(Node node) { + if (clazz.isInstance(node)) { + nodeList.add((T) node); + return false; + } + return true; + } + }); + return nodeList; + } + + /** Find node instances within current function only (not in nested functions). */ + public static List findNodeInstancesInFunction(final Node root, final Class clazz) { + final List nodeList = new ArrayList<>(); + root.accept(new NodeVisitor() { + + @SuppressWarnings("unchecked") + @Override + public boolean visit(Node node) { + if (clazz.isInstance(node)) { + nodeList.add((T) node); + } else if (node instanceof RootNode && node != root) { + return false; + } + return true; + } + }); + return nodeList; + } + + public static List findNodeInstancesInFunctionInterface(final Node root, final Class clazz) { + final List nodeList = new ArrayList<>(); + root.accept(new NodeVisitor() { + + @SuppressWarnings("unchecked") + @Override + public boolean visit(Node node) { + if (clazz.isInstance(node)) { + nodeList.add((I) node); + } else if (node instanceof RootNode && node != root) { + return false; + } + return true; + } + }); + return nodeList; + } + + public static String printTreeToString(Node node) { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + printTree(new PrintStream(byteOut), node); + try { + byteOut.flush(); + } catch (IOException e) { + } + return new String(byteOut.toByteArray()); + } + + /** + * Prints a human readable form of a {@link Node} AST to the given {@link PrintStream}. This print method does not + * check for cycles in the node structure. + * + * @param p the {@link PrintStream} to print to. + * @param node the root node to write + */ + public static void printTree(PrintStream p, Node node) { + printTree(p, node, new NodeTreeResolver()); + } + + /** + * Prints a human readable form of a tree to the given {@link PrintStream}. The {@link TreeResolver} interface needs + * to be implemented to specify how the method can read the tree from plain a object. + * + * @param p the {@link PrintStream} to print to. + * @param o the root object to be printed. + * @param resolver an implementation of a tree resolver + */ + public static void printTree(PrintStream p, Object o, TreeResolver resolver) { + printTree(p, o, resolver, 1); + p.println(); + } + + private static void printTree(PrintStream p, Object node, TreeResolver resolver, int level) { + if (node == null) { + p.print("null"); + return; + } + + p.print(node.getClass().getSimpleName()); + + Field[] fields = NodeUtil.getAllFields(node.getClass()); + p.print("("); + + ArrayList childFields = new ArrayList<>(); + + boolean first = true; + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (Modifier.isStatic(field.getModifiers()) || resolver.isFiltered(field)) { + continue; + } + if (resolver.isChildObject(field) || resolver.isChildArrayObject(field)) { + childFields.add(field); + } + if (!resolver.isDataField(field)) { + continue; + } + if (!first) { + p.print(", "); + } else { + first = false; + } + + Object value = getObjectValue(node, field.getType(), unsafe.objectFieldOffset(field)); + + p.print(field.getName()); + p.print(" = "); + p.print(resolver.toString(value)); + } + p.print(")"); + + if (childFields.size() != 0) { + p.print(" {"); + } + + // I refetch the fields to get declaration order. + for (int i = 0; i < childFields.size(); i++) { + Field field = childFields.get(i); + Class< ? > fieldClass = field.getType(); + String name = field.getName(); + + long offset = unsafe.objectFieldOffset(field); + + Object value = getObjectValue(node, fieldClass, offset); + + printNewLine(p, level); + p.print(name); + if (value == null) { + p.print(" = null "); + } else if (resolver.isChildObject(field)) { + p.print(" = "); + printTree(p, value, resolver, level + 1); + } else if (resolver.isChildArrayObject(field)) { + Object[] objectArray = resolver.convertToArray(field, value); + if (objectArray.length == 0) { + p.print(" = []"); + } else { + p.print(" = ["); + for (int j = 0; j < objectArray.length; j++) { + printTree(p, objectArray[j], resolver, level + 1); + if (j < objectArray.length - 1) { + p.print(", "); + } + } + p.print("]"); + } + } else { + assert false; + } + } + + if (childFields.size() != 0) { + printNewLine(p, level - 1); + p.print("}"); + } + } + + private static Object getObjectValue(Object base, Class< ? > fieldClass, long offset) { + if (fieldClass == boolean.class) { + return unsafe.getBoolean(base, offset); + } else if (fieldClass == byte.class) { + return unsafe.getByte(base, offset); + } else if (fieldClass == short.class) { + return unsafe.getShort(base, offset); + } else if (fieldClass == char.class) { + return unsafe.getChar(base, offset); + } else if (fieldClass == int.class) { + return unsafe.getInt(base, offset); + } else if (fieldClass == long.class) { + return unsafe.getLong(base, offset); + } else if (fieldClass == float.class) { + return unsafe.getFloat(base, offset); + } else if (fieldClass == double.class) { + return unsafe.getDouble(base, offset); + } else { + return unsafe.getObject(base, offset); + } + } + + private static void printNewLine(PrintStream p, int level) { + p.println(); + for (int i = 0; i < level; i++) { + p.print(" "); + } + } + + private static class NodeTreeResolver implements TreeResolver { + + @Override + public boolean isFiltered(Field f) { + if (f.getName().equals("parent")) { + return true; + } + return f.isSynthetic(); + } + + @Override + public boolean isDataField(Field f) { + return !isChildArrayObject(f) && !isChildObject(f); + } + + @Override + public boolean isChildObject(Field f) { + return Node.class.isAssignableFrom(f.getType()); + } + + @Override + public boolean isChildArrayObject(Field f) { + return f.getType().getComponentType() != null && Node.class.isAssignableFrom(f.getType().getComponentType()); + } + + @Override + public Object[] convertToArray(Field f, Object data) { + return (Object[]) data; + } + + @Override + public String toString(Object o) { + return o == null ? "null" : o.toString(); + } + } + + /** + * Specifies how a tree can be built from plain objects. + */ + public interface TreeResolver { + + /** + * Returns true if a {@link Field} is filtered from the tree. + * + * @param f the field to check + */ + boolean isFiltered(Field f); + + /** + * Returns true if a {@link Field} is a field that contains a data value which should not be traversed + * recursively. + * + * @param f the field to check + * @return true if a the given field is a data field else false. + */ + boolean isDataField(Field f); + + /** + * Returns true if a {@link Field} is a field that contains an {@link Object} which should be recursively + * visited. + * + * @param f the field to check + * @return true if a the given field is a child field else false. + */ + boolean isChildObject(Field f); + + /** + * Returns true if a {@link Field} is a field that contains any kind of list/array structure which itself holds + * values that should be recursively visited. + * + * @param f the field to check + * @return true if a the given field is a child array/list field else false. + */ + boolean isChildArrayObject(Field f); + + /** + * Converts an given child array object to array which can be traversed. This is especially useful to convert + * any kind of list structure to a traversable array. + * + * @param f the field for meta data needed to convert the data {@link Object}. + * @param value the actual value of the child array/list object. + * @return the converted {@link Object} array. + */ + Object[] convertToArray(Field f, Object value); + + /** + * Returns a human readable string for any data field object in the tree. + * + * @param o the object to convert to string. + * @return the converted string + */ + String toString(Object o); + } + +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,38 @@ +/* + * 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; + +/** + * Visitor for trees of nodes. + */ +public interface NodeVisitor { + + /** + * This visitor method is called for every node in the tree. Its return value determines if the children of this + * node should be excluded in the iteration. + * + * @param node the node that is currently visited + * @return {@code true} if the children should be visited too, {@code false} otherwise + */ + boolean visit(Node node); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,39 @@ +/* + * 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.*; + +/** + * A root node is a node with a method to execute it given only a frame as a parameter. Therefore, a root node can be used to create a call target using {@link TruffleRuntime#createCallTarget(RootNode, FrameDescriptor)}. + */ +public abstract class RootNode extends Node { + + /** + * Executes this function using the specified frame and returns the result value. + * @param frame the frame of the currently executing guest language method + * @return the value of the execution + */ + public abstract Object execute(VirtualFrame frame); +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,39 @@ +/* + * 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; + +/** + * An exception thrown to enter a slow path. The Truffle optimizer has special knowledge of this exception class and + * will never compile a catch block that catches this exception type. + */ +public class SlowPathException extends Exception { + + private static final long serialVersionUID = 3676602078425211386L; + + /** + * Creates an exception thrown to enter a slow path. + */ + public SlowPathException(String message, Throwable cause) { + super(message, cause); + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Tue Dec 18 17:59:32 2012 +0100 @@ -0,0 +1,59 @@ +/* + * 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; + +/** + * An exception that should be thrown if the return value cannot be represented as a value of the return type. The + * Truffle optimizer has special knowledge of this exception class and will never compile a catch block that catches this + * exception type. + */ +public final class UnexpectedResultException extends SlowPathException { + + private static final long serialVersionUID = 3676602078425211386L; + private final Object result; + + /** + * Creates the exception with the alternative result that cannot be respresented as a value of the return type. + * @param result the alternative result + */ + public UnexpectedResultException(Object result) { + super(null, null); + assert !(result instanceof Throwable); + this.result = result; + } + + /** + * @return the unexpected result + */ + public Object getResult() { + return result; + } + + /** + * For performance reasons, this exception does not record any stack trace information. + */ + @Override + public synchronized Throwable fillInStackTrace() { + return null; + } +} diff -r 7f6bf286629c -r 19f5c9b96fa7 mx/projects --- a/mx/projects Tue Dec 18 17:59:03 2012 +0100 +++ b/mx/projects Tue Dec 18 17:59:32 2012 +0100 @@ -254,3 +254,18 @@ project@com.oracle.graal.asm.amd64@dependencies=com.oracle.graal.asm,com.oracle.graal.amd64 project@com.oracle.graal.asm.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.amd64@javaCompliance=1.7 + +# truffle.api +project@com.oracle.truffle.api@subDir=graal +project@com.oracle.truffle.api@sourceDirs=src +project@com.oracle.truffle.api@dependencies= +project@com.oracle.truffle.api@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.api@javaCompliance=1.7 + +# truffle.api.test +project@com.oracle.truffle.api.test@subDir=graal +project@com.oracle.truffle.api.test@sourceDirs=src +project@com.oracle.truffle.api.test@dependencies=com.oracle.truffle.api,JUNIT +project@com.oracle.truffle.api.test@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.api.test@javaCompliance=1.7 +