# HG changeset patch
# User Christian Haeubl
# Date 1355907668 -3600
# Node ID 64f4195d0ecfad62fb34b775950c40888c322d8b
# Parent 707e9cca11de7ba144e7987836999c1aa5cd425e# Parent 3463363253372daaabdb34433872870b218d65f1
Merge.
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java Wed Dec 19 10:01:08 2012 +0100
@@ -28,6 +28,9 @@
public enum DeoptimizationAction {
/**
* Do not invalidate the machine code.
+ * This is typically used when deoptimizing at a point where it's highly likely
+ * nothing will change the likelihood of the deoptimization happening again.
+ * For example, a compiled array allocation where the size is negative.
*/
None,
@@ -43,6 +46,9 @@
/**
* Invalidate the machine code and immediately schedule a recompilation.
+ * This is typically used when deoptimizing to resolve an unresolved symbol in
+ * which case extra profiling is not required to determine that the deoptimization
+ * will not re-occur.
*/
InvalidateRecompile,
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Dec 19 10:01:08 2012 +0100
@@ -26,7 +26,7 @@
import java.util.*;
import java.util.concurrent.*;
-import junit.framework.*;
+import org.junit.*;
import com.oracle.graal.api.code.*;
import com.oracle.graal.api.meta.*;
@@ -162,8 +162,37 @@
private static int compilationId = 0;
+ /**
+ * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}.
+ * Does a deep copy equality comparison if {@code expected} is an array.
+ */
protected void assertEquals(Object expected, Object actual) {
- Assert.assertEquals(expected, actual);
+ if (expected != null && expected.getClass().isArray()) {
+ Assert.assertTrue(expected != null);
+ Assert.assertTrue(actual != null);
+ Assert.assertEquals(expected.getClass(), actual.getClass());
+ if (expected instanceof int[]) {
+ Assert.assertArrayEquals((int[]) expected, (int[]) actual);
+ } else if (expected instanceof byte[]) {
+ Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
+ } else if (expected instanceof char[]) {
+ Assert.assertArrayEquals((char[]) expected, (char[]) actual);
+ } else if (expected instanceof short[]) {
+ Assert.assertArrayEquals((short[]) expected, (short[]) actual);
+ } else if (expected instanceof float[]) {
+ Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
+ } else if (expected instanceof long[]) {
+ Assert.assertArrayEquals((long[]) expected, (long[]) actual);
+ } else if (expected instanceof double[]) {
+ Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
+ } else if (expected instanceof Object[]) {
+ Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
+ } else {
+ Assert.fail("non-array value encountered: " + expected);
+ }
+ } else {
+ Assert.assertEquals(expected, actual);
+ }
}
protected void testN(int n, final String name, final Object... args) {
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Dec 19 10:01:08 2012 +0100
@@ -369,7 +369,7 @@
NodeList list = getNodeList(node, offsets[index]);
return list.get(subIndex);
}
- return null;
+ throw new NoSuchElementException();
}
@Override
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java Wed Dec 19 10:01:08 2012 +0100
@@ -146,16 +146,6 @@
}
}
- boolean replaceFirst(Node node, Node other) {
- for (int i = 0; i < size; i++) {
- if (nodes[i] == node) {
- nodes[i] = other;
- return true;
- }
- }
- return false;
- }
-
@Override
public String toString() {
StringBuilder str = new StringBuilder();
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Wed Dec 19 10:01:08 2012 +0100
@@ -53,7 +53,7 @@
}
@Override
public FilteredNodeIterable nonNull() {
- this.predicate = this.predicate.or(NodePredicates.isNotNull());
+ this.predicate = this.predicate.and(NodePredicates.isNotNull());
return this;
}
@Override
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java Wed Dec 19 10:01:08 2012 +0100
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.snippets.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.PhasePlan.PhasePosition;
+
+
+/**
+ * Tests intrinsification of {@link System#arraycopy(Object, int, Object, int, int)}.
+ */
+public class ArrayCopyIntrinsificationTest extends GraalCompilerTest {
+
+ @Override
+ protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) {
+ phasePlan.addPhase(PhasePosition.HIGH_LEVEL, new IntrinsifyArrayCopyPhase(runtime, new Assumptions(false)));
+ }
+
+ @Override
+ protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) {
+ int nodeCount = graph.getNodeCount();
+ InstalledCode result = super.getCode(method, graph);
+ boolean graphWasProcessed = nodeCount != graph.getNodeCount();
+ if (graphWasProcessed) {
+ if (mustIntrinsify) {
+ for (Node node: graph.getNodes()) {
+ if (node instanceof Invoke) {
+ Invoke invoke = (Invoke) node;
+ Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode);
+ DirectCallTargetNode directCall = (DirectCallTargetNode) invoke.callTarget();
+ Assert.assertTrue(directCall.target() instanceof JavaMethod);
+ JavaMethod callee = (JavaMethod) directCall.target();
+ Assert.assertTrue(callee.getName().equals(""));
+ Assert.assertTrue(runtime.lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) ||
+ runtime.lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass()));
+ }
+ }
+ } else {
+ boolean found = false;
+ for (Node node: graph.getNodes()) {
+ if (node instanceof Invoke) {
+ Invoke invoke = (Invoke) node;
+ DirectCallTargetNode directCall = (DirectCallTargetNode) invoke.callTarget();
+ JavaMethod callee = (JavaMethod) directCall.target();
+ if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
+ found = true;
+ } else {
+ fail("found invoke to some method other than arraycopy: " + callee);
+ }
+ }
+ }
+ Assert.assertTrue("did not find invoke to arraycopy", found);
+ }
+ }
+ return result;
+ }
+
+ boolean mustIntrinsify = true;
+
+ @Test
+ public void test0() {
+ mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified
+ // Array store checks
+ test("genericArraycopy", new Object(), 0, new Object[0], 0, 0);
+ test("genericArraycopy", new Object[0], 0, new Object(), 0, 0);
+ }
+
+ @Test
+ public void test1() {
+ String name = "intArraycopy";
+ int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+ // Null checks
+ test(name, null, 0, src, 0, 0);
+ test(name, src, 0, null, 0, 0);
+ // Bounds checks
+ test(name, src, 0, src, 0, -1);
+ test(name, src, 0, src, 0, src.length + 1);
+ }
+
+ @Test
+ public void testByte() {
+ byte[] src = {-1, 0, 1, 2, 3, 4};
+ testHelper("byteArraycopy", src);
+ }
+
+ @Test
+ public void testChar() {
+ char[] src = "some string of chars".toCharArray();
+ testHelper("charArraycopy", src);
+ }
+
+ @Test
+ public void testShort() {
+ short[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+ testHelper("shortArraycopy", src);
+ }
+
+ @Test
+ public void testInt() {
+ int[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+ testHelper("intArraycopy", src);
+ }
+
+ @Test
+ public void testFloat() {
+ float[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+ testHelper("floatArraycopy", src);
+ }
+
+ @Test
+ public void testLong() {
+ long[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+ testHelper("longArraycopy", src);
+ }
+
+ @Test
+ public void testDouble() {
+ double[] src = {234, 5345, 756, 23, 8, 345, 873, 440};
+ testHelper("doubleArraycopy", src);
+ }
+
+ @Test
+ public void testObject() {
+ Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()};
+ testHelper("objectArraycopy", src);
+ }
+
+ private static Object newArray(Object proto, int length) {
+ assert proto != null;
+ assert proto.getClass().isArray();
+ return Array.newInstance(proto.getClass().getComponentType(), length);
+ }
+
+ private void testHelper(String name, Object src) {
+ int srcLength = Array.getLength(src);
+
+ // Complete array copy
+ test(name, src, 0, newArray(src, srcLength), 0, srcLength);
+
+ for (int length : new int[] {0, 1, srcLength - 1, srcLength}) {
+ // Partial array copying
+ test(name, src, 0, newArray(src, length), 0, length);
+ test(name, src, srcLength - length, newArray(src, length), 0, length);
+ test(name, src, 0, newArray(src, srcLength), 0, length);
+ }
+ }
+
+ public static Object genericArraycopy(Object src, int srcPos, Object dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static Object[] objectArraycopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static byte[] byteArraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static char[] charArraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static short[] shortArraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static int[] intArraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static float[] floatArraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static long[] longArraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+ public static double[] doubleArraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) {
+ System.arraycopy(src, srcPos, dst, dstPos, length);
+ return dst;
+ }
+
+}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Dec 19 10:01:08 2012 +0100
@@ -676,6 +676,8 @@
checkcastSnippets.lower((CheckCastDynamicNode) n);
} else if (n instanceof InstanceOfNode) {
instanceofSnippets.lower((InstanceOfNode) n, tool);
+ } else if (n instanceof InstanceOfDynamicNode) {
+ instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
} else if (n instanceof NewInstanceNode) {
newObjectSnippets.lower((NewInstanceNode) n, tool);
} else if (n instanceof NewArrayNode) {
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -22,6 +22,8 @@
*/
package com.oracle.graal.hotspot.phases;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
import com.oracle.graal.api.code.*;
import com.oracle.graal.api.code.RuntimeCallTarget.*;
import com.oracle.graal.api.meta.*;
@@ -89,7 +91,7 @@
} while (true);
- LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(Kind.Long)));
+ LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind())));
RuntimeCallNode migrationEnd = graph.add(new RuntimeCallNode(OSR_MIGRATION_END, buffer));
FrameState osrState = osr.stateAfter();
migrationEnd.setStateAfter(osrState);
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -21,8 +21,11 @@
* questions.
*/
package com.oracle.graal.hotspot.snippets;
+import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+import com.oracle.graal.api.code.*;
import com.oracle.graal.api.meta.*;
import com.oracle.graal.hotspot.*;
import com.oracle.graal.hotspot.nodes.*;
@@ -42,7 +45,6 @@
private static final Kind VECTOR_KIND = Kind.Long;
private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
- @Snippet
public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) {
checkInputs(src, srcPos, dest, destPos, length);
int header = arrayBaseOffset(baseKind);
@@ -71,13 +73,12 @@
}
}
- @Snippet
public static void checkInputs(Object src, int srcPos, Object dest, int destPos, int length) {
if (src == null || dest == null) {
throw new NullPointerException();
}
if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > ArrayLengthNode.arrayLength(src) || destPos + length > ArrayLengthNode.arrayLength(dest)) {
- throw new IndexOutOfBoundsException();
+ throw new ArrayIndexOutOfBoundsException();
}
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -33,7 +33,6 @@
import com.oracle.graal.graph.Node.NodeIntrinsic;
import com.oracle.graal.hotspot.meta.*;
import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
import com.oracle.graal.nodes.java.*;
import com.oracle.graal.nodes.spi.*;
import com.oracle.graal.nodes.type.*;
@@ -99,7 +98,7 @@
return object;
}
Word objectHub = loadHub(object);
- if (loadWordFromWord(objectHub, superCheckOffset) != hub) {
+ if (objectHub.readWord(superCheckOffset) != hub) {
displayMiss.inc();
DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ClassCastException);
}
@@ -157,12 +156,12 @@
}
static Word loadWordElement(Word metaspaceArray, int index) {
- return loadWordFromWord(metaspaceArray, metaspaceArrayBaseOffset() + index * wordSize());
+ return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize());
}
static boolean checkSecondarySubType(Word t, Word s) {
// if (S.cache == T) return true
- if (loadWordFromWord(s, secondarySuperCacheOffset()) == t) {
+ if (s.readWord(secondarySuperCacheOffset()) == t) {
cacheHit.inc();
return true;
}
@@ -174,8 +173,8 @@
}
// if (S.scan_s_s_array(T)) { S.cache = T; return true; }
- Word secondarySupers = loadWordFromWord(s, secondarySupersOffset());
- int length = loadIntFromWord(secondarySupers, metaspaceArrayLengthOffset());
+ Word secondarySupers = s.readWord(secondarySupersOffset());
+ int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
for (int i = 0; i < length; i++) {
if (t == loadWordElement(secondarySupers, i)) {
DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t);
@@ -189,11 +188,11 @@
static boolean checkUnknownSubType(Word t, Word s) {
// int off = T.offset
- int superCheckOffset = UnsafeLoadNode.load(t, 0, superCheckOffsetOffset(), Kind.Int);
+ int superCheckOffset = t.readInt(superCheckOffsetOffset());
boolean primary = superCheckOffset != secondarySuperCacheOffset();
// if (T = S[off]) return true
- if (loadWordFromWord(s, superCheckOffset) == t) {
+ if (s.readWord(superCheckOffset) == t) {
if (primary) {
cacheHit.inc();
} else {
@@ -215,8 +214,8 @@
}
// if (S.scan_s_s_array(T)) { S.cache = T; return true; }
- Word secondarySupers = loadWordFromWord(s, secondarySupersOffset());
- int length = loadIntFromWord(secondarySupers, metaspaceArrayLengthOffset());
+ Word secondarySupers = s.readWord(secondarySupersOffset());
+ int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
for (int i = 0; i < length; i++) {
if (t == loadWordElement(secondarySupers, i)) {
DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t);
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -23,9 +23,11 @@
package com.oracle.graal.hotspot.snippets;
import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
import java.lang.reflect.*;
+import com.oracle.graal.nodes.*;
import com.oracle.graal.snippets.*;
import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
@@ -41,7 +43,7 @@
// Class for primitive type
return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
} else {
- return loadIntFromWord(klass, klassModifierFlagsOffset());
+ return klass.readInt(klassModifierFlagsOffset());
}
}
@@ -51,7 +53,7 @@
if (klass == Word.zero()) {
return false;
} else {
- int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset());
+ int accessFlags = klass.readInt(klassAccessFlagsOffset());
return (accessFlags & Modifier.INTERFACE) != 0;
}
}
@@ -62,7 +64,7 @@
if (klass == Word.zero()) {
return false;
} else {
- int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+ int layoutHelper = klass.readInt(klassLayoutHelperOffset());
return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0;
}
}
@@ -77,17 +79,17 @@
public static Class> getSuperclass(final Class> thisObj) {
Word klass = loadWordFromObject(thisObj, klassOffset());
if (klass != Word.zero()) {
- int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset());
+ int accessFlags = klass.readInt(klassAccessFlagsOffset());
if ((accessFlags & Modifier.INTERFACE) == 0) {
- int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+ int layoutHelper = klass.readInt(klassLayoutHelperOffset());
if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
return Object.class;
} else {
- Word superKlass = loadWordFromWord(klass, klassSuperKlassOffset());
+ Word superKlass = klass.readWord(klassSuperKlassOffset());
if (superKlass == Word.zero()) {
return null;
} else {
- return (Class>) loadObjectFromWord(superKlass, classMirrorOffset());
+ return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true);
}
}
}
@@ -99,11 +101,17 @@
public static Class> getComponentType(final Class> thisObj) {
Word klass = loadWordFromObject(thisObj, klassOffset());
if (klass != Word.zero()) {
- int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset());
+ int layoutHelper = klass.readInt(klassLayoutHelperOffset());
if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) {
- return (Class>) loadObjectFromWord(klass, arrayKlassComponentMirrorOffset());
+ return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true);
}
}
return null;
}
+
+ @MethodSubstitution(isStatic = false)
+ public static boolean isInstance(final Class> thisObj, Object obj) {
+ return MaterializeNode.isInstance(thisObj, obj);
+ }
+
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Wed Dec 19 10:01:08 2012 +0100
@@ -285,36 +285,16 @@
return HotSpotSnippetUtils.registerAsWord(threadRegister());
}
- public static int loadIntFromWord(Word address, int offset) {
- Integer value = UnsafeLoadNode.load(address, 0, offset, Kind.Int);
- return value;
- }
-
- public static Word loadWordFromWord(Word address, int offset) {
- return loadWordFromWordIntrinsic(address, 0, offset, wordKind());
- }
-
- static Object loadObjectFromWord(Word address, int offset) {
- return UnsafeLoadNode.load(address, 0, offset, Kind.Object);
- }
-
public static Word loadWordFromObject(Object object, int offset) {
return loadWordFromObjectIntrinsic(object, 0, offset, wordKind());
}
- public static Object readFinalObject(Word base, @ConstantNodeParameter int displacement) {
- return ReadNode.read(base, displacement, LocationNode.FINAL_LOCATION, Kind.Object);
- }
-
@NodeIntrinsic(value = RegisterNode.class, setStampFromReturnType = true)
public static native Word registerAsWord(@ConstantNodeParameter Register register);
@NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
private static native Word loadWordFromObjectIntrinsic(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind);
- @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
- private static native Word loadWordFromWordIntrinsic(Word address, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind);
-
@NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true)
static native Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word);
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -93,7 +93,7 @@
return falseValue;
}
Word objectHub = loadHub(object);
- if (loadWordFromWord(objectHub, superCheckOffset) != hub) {
+ if (objectHub.readWord(superCheckOffset) != hub) {
displayMiss.inc();
return falseValue;
}
@@ -134,7 +134,7 @@
static boolean checkSecondarySubType(Word t, Word s) {
// if (S.cache == T) return true
- if (loadWordFromWord(s, secondarySuperCacheOffset()) == t) {
+ if (s.readWord(secondarySuperCacheOffset()) == t) {
cacheHit.inc();
return true;
}
@@ -146,8 +146,8 @@
}
// if (S.scan_s_s_array(T)) { S.cache = T; return true; }
- Word secondarySupers = loadWordFromWord(s, secondarySupersOffset());
- int length = loadIntFromWord(secondarySupers, metaspaceArrayLengthOffset());
+ Word secondarySupers = s.readWord(secondarySupersOffset());
+ int length = secondarySupers.readInt(metaspaceArrayLengthOffset());
for (int i = 0; i < length; i++) {
if (t == loadWordElement(secondarySupers, i)) {
DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t);
@@ -159,45 +159,83 @@
return false;
}
+ /**
+ * Type test used when the type being tested against is not known at compile time.
+ */
+ @Snippet
+ public static Object instanceofDynamic(
+ @Parameter("mirror") Class mirror,
+ @Parameter("object") Object object,
+ @Parameter("trueValue") Object trueValue,
+ @Parameter("falseValue") Object falseValue,
+ @ConstantParameter("checkNull") boolean checkNull) {
+ if (checkNull && object == null) {
+ isNull.inc();
+ return falseValue;
+ }
+
+ Word hub = loadWordFromObject(mirror, klassOffset());
+ Word objectHub = loadHub(object);
+ if (!checkUnknownSubType(hub, objectHub)) {
+ return falseValue;
+ }
+ return trueValue;
+ }
+
public static class Templates extends InstanceOfSnippetsTemplates {
private final ResolvedJavaMethod instanceofExact;
private final ResolvedJavaMethod instanceofPrimary;
private final ResolvedJavaMethod instanceofSecondary;
+ private final ResolvedJavaMethod instanceofDynamic;
public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) {
super(runtime, assumptions, target, InstanceOfSnippets.class);
instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class);
instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class);
instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean.class);
+ instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class);
}
@Override
protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
- InstanceOfNode instanceOf = replacer.instanceOf;
- ValueNode trueValue = replacer.trueValue;
- ValueNode falseValue = replacer.falseValue;
- ValueNode object = instanceOf.object();
- TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
- final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
- ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph());
- boolean checkNull = !object.stamp().nonNull();
- Arguments arguments;
- Key key;
- if (hintInfo.exact) {
- ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
- assert hints.length == 1;
- key = new Key(instanceofExact).add("checkNull", checkNull);
- arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue);
- } else if (type.isPrimaryType()) {
- key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
- arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
+ if (replacer.instanceOf instanceof InstanceOfNode) {
+ InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
+ ValueNode trueValue = replacer.trueValue;
+ ValueNode falseValue = replacer.falseValue;
+ ValueNode object = instanceOf.object();
+ TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints);
+ final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
+ ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph());
+ boolean checkNull = !object.stamp().nonNull();
+ Arguments arguments;
+ Key key;
+ if (hintInfo.exact) {
+ ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
+ assert hints.length == 1;
+ key = new Key(instanceofExact).add("checkNull", checkNull);
+ arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue);
+ } else if (type.isPrimaryType()) {
+ key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
+ arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
+ } else {
+ ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
+ key = new Key(instanceofSecondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
+ arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue);
+ }
+ return new KeyAndArguments(key, arguments);
} else {
- ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
- key = new Key(instanceofSecondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
- arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue);
+ assert replacer.instanceOf instanceof InstanceOfDynamicNode;
+ InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf;
+ ValueNode trueValue = replacer.trueValue;
+ ValueNode falseValue = replacer.falseValue;
+ ValueNode object = instanceOf.object();
+ ValueNode mirror = instanceOf.mirror();
+ boolean checkNull = !object.stamp().nonNull();
+ Key key = new Key(instanceofDynamic).add("checkNull", checkNull);
+ Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
+ return new KeyAndArguments(key, arguments);
}
- return new KeyAndArguments(key, arguments);
}
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -40,7 +40,6 @@
import com.oracle.graal.hotspot.meta.*;
import com.oracle.graal.hotspot.nodes.*;
import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
import com.oracle.graal.nodes.java.*;
import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
import com.oracle.graal.nodes.spi.*;
@@ -107,7 +106,7 @@
// The bias pattern is present in the object's mark word. Need to check
// whether the bias owner and the epoch are both still current.
Word hub = loadHub(object);
- final Word prototypeMarkWord = loadWordFromWord(hub, prototypeMarkWordOffset());
+ final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
final Word thread = thread();
final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord.toLong());
@@ -293,7 +292,7 @@
final Word lock = CurrentLockNode.currentLock();
// Load displaced mark
- final Word displacedMark = loadWordFromWord(lock, lockDisplacedMarkOffset());
+ final Word displacedMark = lock.readWord(lockDisplacedMarkOffset());
trace(trace, " displacedMark: 0x%016lx\n", displacedMark.toLong());
if (displacedMark == Word.zero()) {
@@ -360,7 +359,7 @@
private static void incCounter() {
if (CHECK_BALANCED_MONITORS) {
final Word counter = MonitorCounterNode.counter();
- final int count = UnsafeLoadNode.load(counter, 0, 0, Kind.Int);
+ final int count = counter.readInt(0);
DirectObjectStoreNode.storeInt(counter, 0, 0, count + 1);
}
}
@@ -368,7 +367,7 @@
private static void decCounter() {
if (CHECK_BALANCED_MONITORS) {
final Word counter = MonitorCounterNode.counter();
- final int count = UnsafeLoadNode.load(counter, 0, 0, Kind.Int);
+ final int count = counter.readInt(0);
DirectObjectStoreNode.storeInt(counter, 0, 0, count - 1);
}
}
@@ -382,7 +381,7 @@
@Snippet
private static void checkCounter(String errMsg) {
final Word counter = MonitorCounterNode.counter();
- final int count = UnsafeLoadNode.load(counter, 0, 0, Kind.Int);
+ final int count = counter.readInt(0);
if (count != 0) {
vmError(errMsg, count);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -59,8 +59,8 @@
@Snippet
public static Word allocate(@Parameter("size") int size) {
Word thread = thread();
- Word top = loadWordFromWord(thread, threadTlabTopOffset());
- Word end = loadWordFromWord(thread, threadTlabEndOffset());
+ Word top = thread.readWord(threadTlabTopOffset());
+ Word end = thread.readWord(threadTlabEndOffset());
Word newTop = top.plus(size);
// this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code)
if (newTop.belowOrEqual(end)) {
@@ -187,7 +187,7 @@
* Formats some allocated memory with an object header zeroes out the rest.
*/
private static void formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) {
- Word prototypeMarkWord = useBiasedLocking() ? loadWordFromWord(hub, prototypeMarkWordOffset()) : compileTimePrototypeMarkWord;
+ Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset()) : compileTimePrototypeMarkWord;
storeWord(memory, 0, markOffset(), prototypeMarkWord);
storeWord(memory, 0, hubOffset(), hub);
if (fillContents) {
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -23,6 +23,7 @@
package com.oracle.graal.hotspot.snippets;
import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
+import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
import com.oracle.graal.hotspot.nodes.*;
import com.oracle.graal.snippets.*;
@@ -36,7 +37,7 @@
@MethodSubstitution(isStatic = false)
public static Class> getClass(final Object thisObj) {
Word hub = loadHub(thisObj);
- return (Class>) readFinalObject(hub, classMirrorOffset());
+ return unsafeCast(hub.readFinalObject(classMirrorOffset()), Class.class, true, true);
}
@MethodSubstitution(isStatic = false)
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java Wed Dec 19 10:01:08 2012 +0100
@@ -40,10 +40,10 @@
@MethodSubstitution(isStatic = false)
private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
Word rawThread = HotSpotCurrentRawThreadNode.get();
- Thread thread = (Thread) loadObjectFromWord(rawThread, threadObjectOffset());
+ Thread thread = (Thread) rawThread.readObject(threadObjectOffset());
if (thisObject == thread) {
- Word osThread = loadWordFromWord(rawThread, osThreadOffset());
- boolean interrupted = loadIntFromWord(osThread, osThreadInterruptedOffset()) != 0;
+ Word osThread = rawThread.readWord(osThreadOffset());
+ boolean interrupted = osThread.readInt(osThreadInterruptedOffset()) != 0;
if (!interrupted || !clearInterrupted) {
return interrupted;
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Wed Dec 19 10:01:08 2012 +0100
@@ -70,7 +70,7 @@
@Parameter("length") int length,
@ConstantParameter("intArrayHub") Word intArrayHub,
@ConstantParameter("log") boolean log) {
- int layoutHelper = loadIntFromWord(hub, layoutHelperOffset());
+ int layoutHelper = hub.readInt(layoutHelperOffset());
int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Wed Dec 19 10:01:08 2012 +0100
@@ -68,12 +68,12 @@
@Parameter("hub") Word hub,
@ConstantParameter("intArrayHub") Word intArrayHub,
@ConstantParameter("log") boolean log) {
- int sizeInBytes = loadIntFromWord(hub, klassInstanceSizeOffset());
+ int sizeInBytes = hub.readInt(klassInstanceSizeOffset());
if (!forceSlowPath() && inlineContiguousAllocationSupported()) {
- if (loadIntFromWord(hub, klassStateOffset()) == klassStateFullyInitialized()) {
+ if (hub.readInt(klassStateOffset()) == klassStateFullyInitialized()) {
Word memory = refillAllocate(intArrayHub, sizeInBytes, log);
if (memory != Word.zero()) {
- Word prototypeMarkWord = loadWordFromWord(hub, prototypeMarkWordOffset());
+ Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset());
storeWord(memory, 0, markOffset(), prototypeMarkWord);
storeWord(memory, 0, hubOffset(), hub);
for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) {
@@ -100,8 +100,8 @@
int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords() * wordSize();
Word thread = thread();
- Word top = loadWordFromWord(thread, threadTlabTopOffset());
- Word end = loadWordFromWord(thread, threadTlabEndOffset());
+ Word top = thread.readWord(threadTlabTopOffset());
+ Word end = thread.readWord(threadTlabEndOffset());
// calculate amount of free space
Word tlabFreeSpaceInBytes = end.minus(top);
@@ -116,14 +116,14 @@
// Retain TLAB and allocate object in shared space if
// the amount free in the TLAB is too large to discard.
- Word refillWasteLimit = loadWordFromWord(thread, tlabRefillWasteLimitOffset());
+ Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset());
if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) {
if (tlabStats()) {
// increment number of refills
- storeInt(thread, 0, tlabNumberOfRefillsOffset(), loadIntFromWord(thread, tlabNumberOfRefillsOffset()) + 1);
- log(log, "thread: %p -- number_of_refills %d\n", thread.toLong(), loadIntFromWord(thread, tlabNumberOfRefillsOffset()));
+ storeInt(thread, 0, tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1);
+ log(log, "thread: %p -- number_of_refills %d\n", thread.toLong(), thread.readInt(tlabNumberOfRefillsOffset()));
// accumulate wastage
- Word wastage = loadWordFromWord(thread, tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords);
+ Word wastage = thread.readWord(tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords);
log(log, "thread: %p -- accumulated wastage %d\n", thread.toLong(), wastage.toLong());
storeWord(thread, 0, tlabFastRefillWasteOffset(), wastage);
}
@@ -137,13 +137,13 @@
int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts;
NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false);
- Word allocated = loadWordFromWord(thread, threadAllocatedBytesOffset());
- allocated = allocated.plus(top.minus(loadWordFromWord(thread, threadTlabStartOffset())));
+ Word allocated = thread.readWord(threadAllocatedBytesOffset());
+ allocated = allocated.plus(top.minus(thread.readWord(threadTlabStartOffset())));
storeWord(thread, 0, threadAllocatedBytesOffset(), allocated);
}
// refill the TLAB with an eden allocation
- Word tlabRefillSizeInWords = loadWordFromWord(thread, threadTlabSizeOffset());
+ Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset());
Word tlabRefillSizeInBytes = Word.fromLong(tlabRefillSizeInWords.toLong() * wordSize());
// allocate new TLAB, address returned in top
top = edenAllocate(tlabRefillSizeInBytes, log);
@@ -165,7 +165,7 @@
log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.toLong());
if (tlabStats()) {
- storeInt(thread, 0, tlabSlowAllocationsOffset(), loadIntFromWord(thread, tlabSlowAllocationsOffset()) + 1);
+ storeInt(thread, 0, tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1);
}
return edenAllocate(Word.fromInt(sizeInBytes), log);
@@ -184,13 +184,13 @@
Word heapEndAddress = Word.fromLong(heapEndAddress());
while (true) {
- Word heapTop = loadWordFromWord(heapTopAddress, 0);
+ Word heapTop = heapTopAddress.readWord(0);
Word newHeapTop = heapTop.plus(sizeInBytes);
if (newHeapTop.belowOrEqual(heapTop)) {
return Word.zero();
}
- Word heapEnd = loadWordFromWord(heapEndAddress, 0);
+ Word heapEnd = heapEndAddress.readWord(0);
if (newHeapTop.above(heapEnd)) {
return Word.zero();
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Wed Dec 19 10:01:08 2012 +0100
@@ -63,7 +63,7 @@
int inFalseBranch = loop.nodesInLoopFrom(ifNode.falseSuccessor(), postDom).cardinality();
int loopTotal = loop.size();
int netDiff = loopTotal - (inTrueBranch + inFalseBranch);
- double uncertainty = (0.5 - Math.abs(ifNode.probability(IfNode.TRUE_EDGE) - 0.5)) * 2;
+ double uncertainty = (0.5 - Math.abs(ifNode.probability(ifNode.trueSuccessor()) - 0.5)) * 2;
int maxDiff = GraalOptions.LoopUnswitchMaxIncrease + (int) (GraalOptions.LoopUnswitchUncertaintyBoost * loop.loopBegin().loopFrequency() * uncertainty);
Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of if", loop, ifNode, netDiff, maxDiff, (double) (inTrueBranch + inFalseBranch) / loopTotal * 100);
return netDiff <= maxDiff;
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Wed Dec 19 10:01:08 2012 +0100
@@ -96,7 +96,7 @@
StructuredGraph graph = (StructuredGraph) ifNode.graph();
BeginNode tempBegin = graph.add(new BeginNode());
originalLoop.entryPoint().replaceAtPredecessor(tempBegin);
- double takenProbability = ifNode.probability(ifNode.blockSuccessorIndex(ifNode.trueSuccessor()));
+ double takenProbability = ifNode.probability(ifNode.trueSuccessor());
IfNode newIf = graph.add(new IfNode(ifNode.condition(), duplicateLoop.entryPoint(), originalLoop.entryPoint(), takenProbability, ifNode.leafGraphId()));
tempBegin.setNext(newIf);
ifNode.setCondition(graph.unique(ConstantNode.forBoolean(false, graph)));
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -53,7 +53,7 @@
if (LoopPolicies.shouldTryUnswitch(loop)) {
IfNode ifNode = LoopTransformations.findUnswitchableIf(loop);
if (ifNode != null && LoopPolicies.shouldUnswitch(loop, ifNode)) {
- Debug.log("Unswitching %s at %s [%f - %f]", loop, ifNode, ifNode.probability(0), ifNode.probability(1));
+ Debug.log("Unswitching %s at %s [%f - %f]", loop, ifNode, ifNode.probability(ifNode.trueSuccessor()), ifNode.probability(ifNode.falseSuccessor()));
LoopTransformations.unswitch(loop, ifNode);
UNSWITCHED.increment();
Debug.dump(graph, "After unswitch %s", loop);
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -22,62 +22,16 @@
*/
package com.oracle.graal.nodes;
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
import com.oracle.graal.nodes.type.*;
/**
* The {@code ControlSplitNode} is a base class for all instructions that split the control flow (ie. have more than one successor).
*/
public abstract class ControlSplitNode extends FixedNode {
- @Successor private final NodeSuccessorList blockSuccessors;
- protected double[] branchProbability;
- public BeginNode blockSuccessor(int index) {
- return blockSuccessors.get(index);
- }
-
- public void setBlockSuccessor(int index, BeginNode x) {
- blockSuccessors.set(index, x);
- }
-
- public int blockSuccessorCount() {
- return blockSuccessors.size();
- }
-
- public ControlSplitNode(Stamp stamp, BeginNode[] blockSuccessors, double[] branchProbability) {
+ public ControlSplitNode(Stamp stamp) {
super(stamp);
- assert branchProbability.length == blockSuccessors.length;
- this.blockSuccessors = new NodeSuccessorList<>(this, blockSuccessors);
- this.branchProbability = branchProbability;
}
- public double probability(int successorIndex) {
- return branchProbability[successorIndex];
- }
-
- public void setProbability(int successorIndex, double x) {
- branchProbability[successorIndex] = x;
- }
-
- public NodeIterable blockSuccessors() {
- return blockSuccessors;
- }
-
- public int blockSuccessorIndex(BeginNode successor) {
- int idx = blockSuccessors.indexOf(successor);
- if (idx < 0) {
- throw new IllegalArgumentException();
- }
- return idx;
- }
-
- @Override
- public ControlSplitNode clone(Graph into) {
- ControlSplitNode csn = (ControlSplitNode) super.clone(into);
- csn.branchProbability = Arrays.copyOf(branchProbability, branchProbability.length);
- return csn;
- }
+ public abstract double probability(BeginNode successor);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Dec 19 10:01:08 2012 +0100
@@ -298,10 +298,6 @@
return values.get(localsSize + stackSize + i);
}
- public MergeNode block() {
- return usages().filter(MergeNode.class).first();
- }
-
public NodeIterable innerFrameStates() {
return usages().filter(FrameState.class);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -38,11 +38,11 @@
* comparison.
*/
public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, Negatable {
- public static final int TRUE_EDGE = 0;
- public static final int FALSE_EDGE = 1;
private final long leafGraphId;
-
+ @Successor private BeginNode trueSuccessor;
+ @Successor private BeginNode falseSuccessor;
@Input private BooleanNode condition;
+ private double takenProbability;
public BooleanNode condition() {
return condition;
@@ -54,9 +54,17 @@
}
public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double takenProbability, long leafGraphId) {
- super(StampFactory.forVoid(), new BeginNode[] {BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor)}, new double[] {takenProbability, 1 - takenProbability});
+ this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), takenProbability, leafGraphId);
+ }
+
+ public IfNode(BooleanNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double takenProbability, long leafGraphId) {
+ super(StampFactory.forVoid());
this.condition = condition;
+ this.falseSuccessor = falseSuccessor;
+ this.takenProbability = takenProbability;
this.leafGraphId = leafGraphId;
+ this.trueSuccessor = trueSuccessor;
+
}
public long leafGraphId() {
@@ -69,7 +77,7 @@
* @return the true successor
*/
public BeginNode trueSuccessor() {
- return blockSuccessor(0);
+ return trueSuccessor;
}
/**
@@ -78,15 +86,17 @@
* @return the false successor
*/
public BeginNode falseSuccessor() {
- return blockSuccessor(1);
+ return falseSuccessor;
}
public void setTrueSuccessor(BeginNode node) {
- setBlockSuccessor(0, node);
+ updatePredecessor(trueSuccessor, node);
+ trueSuccessor = node;
}
public void setFalseSuccessor(BeginNode node) {
- setBlockSuccessor(1, node);
+ updatePredecessor(falseSuccessor, node);
+ falseSuccessor = node;
}
/**
@@ -96,7 +106,24 @@
* @return the corresponding successor
*/
public BeginNode successor(boolean istrue) {
- return blockSuccessor(istrue ? 0 : 1);
+ return istrue ? trueSuccessor : falseSuccessor;
+ }
+
+ @Override
+ public Negatable negate() {
+ BeginNode trueSucc = trueSuccessor();
+ BeginNode falseSucc = falseSuccessor();
+ setTrueSuccessor(null);
+ setFalseSuccessor(null);
+ setTrueSuccessor(falseSucc);
+ setFalseSuccessor(trueSucc);
+ takenProbability = 1 - takenProbability;
+ return this;
+ }
+
+ @Override
+ public double probability(BeginNode successor) {
+ return successor == trueSuccessor ? takenProbability : 1 - takenProbability;
}
@Override
@@ -119,11 +146,11 @@
if (c.asConstant().asBoolean()) {
tool.deleteBranch(falseSuccessor());
tool.addToWorkList(trueSuccessor());
- ((StructuredGraph) graph()).removeSplit(this, TRUE_EDGE);
+ ((StructuredGraph) graph()).removeSplit(this, trueSuccessor());
} else {
tool.deleteBranch(trueSuccessor());
tool.addToWorkList(falseSuccessor());
- ((StructuredGraph) graph()).removeSplit(this, FALSE_EDGE);
+ ((StructuredGraph) graph()).removeSplit(this, falseSuccessor());
}
} else if (trueSuccessor().guards().isEmpty() && falseSuccessor().guards().isEmpty()) {
if (removeOrMaterializeIf(tool)) {
@@ -154,7 +181,7 @@
PhiNode singlePhi = phis.next();
if (!phis.hasNext()) {
// one phi at the merge of an otherwise empty if construct: try to convert into a MaterializeNode
- boolean inverted = trueEnd == merge.forwardEndAt(FALSE_EDGE);
+ boolean inverted = trueEnd == merge.forwardEndAt(1);
ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0);
ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1);
if (trueValue.kind() != falseValue.kind()) {
@@ -276,8 +303,8 @@
List trueEnds = new ArrayList<>(mergePredecessors.size());
Map phiValues = new HashMap<>(mergePredecessors.size());
- BeginNode falseSuccessor = falseSuccessor();
- BeginNode trueSuccessor = trueSuccessor();
+ BeginNode oldFalseSuccessor = falseSuccessor();
+ BeginNode oldTrueSuccessor = trueSuccessor();
setFalseSuccessor(null);
setTrueSuccessor(null);
@@ -294,8 +321,8 @@
}
assert !ends.hasNext();
- connectEnds(falseEnds, phiValues, falseSuccessor, merge, tool);
- connectEnds(trueEnds, phiValues, trueSuccessor, merge, tool);
+ connectEnds(falseEnds, phiValues, oldFalseSuccessor, merge, tool);
+ connectEnds(trueEnds, phiValues, oldTrueSuccessor, merge, tool);
GraphUtil.killCFG(merge);
@@ -382,20 +409,20 @@
}
private void removeEmptyIf(SimplifierTool tool) {
- BeginNode trueSuccessor = trueSuccessor();
- BeginNode falseSuccessor = falseSuccessor();
- assert trueSuccessor.next() instanceof EndNode && falseSuccessor.next() instanceof EndNode;
+ BeginNode originalTrueSuccessor = trueSuccessor();
+ BeginNode originalFalseSuccessor = falseSuccessor();
+ assert originalTrueSuccessor.next() instanceof EndNode && originalFalseSuccessor.next() instanceof EndNode;
- EndNode trueEnd = (EndNode) trueSuccessor.next();
- EndNode falseEnd = (EndNode) falseSuccessor.next();
+ EndNode trueEnd = (EndNode) originalTrueSuccessor.next();
+ EndNode falseEnd = (EndNode) originalFalseSuccessor.next();
assert trueEnd.merge() == falseEnd.merge();
FixedWithNextNode pred = (FixedWithNextNode) predecessor();
MergeNode merge = trueEnd.merge();
merge.prepareDelete(pred);
assert merge.usages().isEmpty();
- trueSuccessor.prepareDelete();
- falseSuccessor.prepareDelete();
+ originalTrueSuccessor.prepareDelete();
+ originalFalseSuccessor.prepareDelete();
FixedNode next = merge.next();
merge.setNext(null);
@@ -403,25 +430,11 @@
setFalseSuccessor(null);
pred.setNext(next);
safeDelete();
- trueSuccessor.safeDelete();
- falseSuccessor.safeDelete();
+ originalTrueSuccessor.safeDelete();
+ originalFalseSuccessor.safeDelete();
merge.safeDelete();
trueEnd.safeDelete();
falseEnd.safeDelete();
tool.addToWorkList(next);
}
-
- @Override
- public Negatable negate() {
- BeginNode trueSucc = trueSuccessor();
- BeginNode falseSucc = falseSuccessor();
- setTrueSuccessor(null);
- setFalseSuccessor(null);
- setTrueSuccessor(falseSucc);
- setFalseSuccessor(trueSucc);
- double prop = branchProbability[TRUE_EDGE];
- branchProbability[TRUE_EDGE] = branchProbability[FALSE_EDGE];
- branchProbability[FALSE_EDGE] = prop;
- return this;
- }
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -33,9 +33,8 @@
@NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}")
public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable {
- public static final int NORMAL_EDGE = 0;
- public static final int EXCEPTION_EDGE = 1;
-
+ @Successor private BeginNode next;
+ @Successor private DispatchBeginNode exceptionEdge;
@Input private final CallTargetNode callTarget;
@Input private FrameState stateAfter;
private final int bci;
@@ -44,7 +43,8 @@
private final long leafGraphId;
public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci, long leafGraphId) {
- super(callTarget.returnStamp(), new BeginNode[]{null, exceptionEdge}, new double[]{1.0, 0.0});
+ super(callTarget.returnStamp());
+ this.exceptionEdge = exceptionEdge;
this.bci = bci;
this.callTarget = callTarget;
this.leafGraphId = leafGraphId;
@@ -53,19 +53,21 @@
}
public DispatchBeginNode exceptionEdge() {
- return (DispatchBeginNode) blockSuccessor(EXCEPTION_EDGE);
+ return exceptionEdge;
}
- public void setExceptionEdge(BeginNode x) {
- setBlockSuccessor(EXCEPTION_EDGE, x);
+ public void setExceptionEdge(DispatchBeginNode x) {
+ updatePredecessor(exceptionEdge, x);
+ exceptionEdge = x;
}
public BeginNode next() {
- return blockSuccessor(NORMAL_EDGE);
+ return next;
}
public void setNext(BeginNode x) {
- setBlockSuccessor(NORMAL_EDGE, x);
+ updatePredecessor(next, x);
+ next = x;
}
public CallTargetNode callTarget() {
@@ -170,9 +172,9 @@
}
public void killExceptionEdge() {
- BeginNode exceptionEdge = exceptionEdge();
+ BeginNode edge = exceptionEdge();
setExceptionEdge(null);
- GraphUtil.killCFG(exceptionEdge);
+ GraphUtil.killCFG(edge);
}
@Override
@@ -187,18 +189,24 @@
}
if (node == null) {
assert kind() == Kind.Void && usages().isEmpty();
- ((StructuredGraph) graph()).removeSplit(this, NORMAL_EDGE);
+ ((StructuredGraph) graph()).removeSplit(this, next());
} else if (node instanceof DeoptimizeNode) {
this.replaceAtPredecessor(node);
this.replaceAtUsages(null);
GraphUtil.killCFG(this);
return;
} else {
- ((StructuredGraph) graph()).replaceSplit(this, node, NORMAL_EDGE);
+ ((StructuredGraph) graph()).replaceSplit(this, node, next());
}
call.safeDelete();
if (state.usages().isEmpty()) {
state.safeDelete();
}
}
+
+ private static final double EXCEPTION_PROBA = 1e-5;
+ @Override
+ public double probability(BeginNode successor) {
+ return successor == next ? 1 - EXCEPTION_PROBA : EXCEPTION_PROBA;
+ }
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -26,6 +26,7 @@
import com.oracle.graal.graph.*;
import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
public final class MaterializeNode extends ConditionalNode {
@@ -37,6 +38,10 @@
super(condition, trueValue, falseValue);
}
+ private MaterializeNode(ValueNode type, ValueNode object) {
+ super(type.graph().add(new InstanceOfDynamicNode(type, object)), ConstantNode.forInt(1, type.graph()), ConstantNode.forInt(0, type.graph()));
+ }
+
public static MaterializeNode create(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
Graph graph = condition.graph();
MaterializeNode result = new MaterializeNode(condition, trueValue, falseValue);
@@ -53,4 +58,7 @@
@NodeIntrinsic
public static native boolean materialize(@ConstantNodeParameter Condition condition, long x, long y);
+
+ @NodeIntrinsic
+ public static native boolean isInstance(Class mirror, Object object);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Wed Dec 19 10:01:08 2012 +0100
@@ -241,39 +241,34 @@
node.safeDelete();
}
- public void removeSplit(ControlSplitNode node, int survivingSuccessor) {
+ public void removeSplit(ControlSplitNode node, BeginNode survivingSuccessor) {
assert node != null;
assert node.usages().isEmpty();
- assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
- BeginNode begin = node.blockSuccessor(survivingSuccessor);
- for (int i = 0; i < node.blockSuccessorCount(); i++) {
- node.setBlockSuccessor(i, null);
- }
- node.replaceAtPredecessor(begin);
+ assert survivingSuccessor != null;
+ node.clearSuccessors();
+ node.replaceAtPredecessor(survivingSuccessor);
node.safeDelete();
}
- public void removeSplitPropagate(ControlSplitNode node, int survivingSuccessor) {
+ public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) {
assert node != null;
assert node.usages().isEmpty();
- assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
- BeginNode begin = node.blockSuccessor(survivingSuccessor);
- for (int i = 0; i < node.blockSuccessorCount(); i++) {
- BeginNode successor = node.blockSuccessor(i);
- node.setBlockSuccessor(i, null);
- if (successor != null && successor != begin && successor.isAlive()) {
- GraphUtil.killCFG(successor);
+ assert survivingSuccessor != null;
+ for (Node successor : node.successors().snapshot()) {
+ successor.replaceAtPredecessor(null);
+ if (successor != null && successor != survivingSuccessor && successor.isAlive()) {
+ GraphUtil.killCFG((BeginNode) successor);
}
}
- if (begin.isAlive()) {
- node.replaceAtPredecessor(begin);
+ if (survivingSuccessor.isAlive()) {
+ node.replaceAtPredecessor(survivingSuccessor);
node.safeDelete();
} else {
- assert node.isDeleted() : node + " " + begin;
+ assert node.isDeleted() : node + " " + survivingSuccessor;
}
}
- public void replaceSplit(ControlSplitNode node, Node replacement, int survivingSuccessor) {
+ public void replaceSplit(ControlSplitNode node, Node replacement, BeginNode survivingSuccessor) {
if (replacement instanceof FixedWithNextNode) {
replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor);
} else {
@@ -283,25 +278,19 @@
}
}
- public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, int survivingSuccessor) {
+ public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, BeginNode survivingSuccessor) {
assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
- assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
- BeginNode begin = node.blockSuccessor(survivingSuccessor);
- for (int i = 0; i < node.blockSuccessorCount(); i++) {
- node.setBlockSuccessor(i, null);
- }
- replacement.setNext(begin);
+ assert survivingSuccessor != null;
+ node.clearSuccessors();
+ replacement.setNext(survivingSuccessor);
node.replaceAndDelete(replacement);
}
- public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, int survivingSuccessor) {
+ public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, BeginNode survivingSuccessor) {
assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
- assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
- BeginNode begin = node.blockSuccessor(survivingSuccessor);
- for (int i = 0; i < node.blockSuccessorCount(); i++) {
- node.setBlockSuccessor(i, null);
- }
- node.replaceAtPredecessor(begin);
+ assert survivingSuccessor != null;
+ node.clearSuccessors();
+ node.replaceAtPredecessor(survivingSuccessor);
node.replaceAtUsages(replacement);
node.safeDelete();
}
@@ -322,7 +311,7 @@
public void addBeforeFixed(FixedNode node, FixedWithNextNode newNode) {
assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " before " + node;
assert node.predecessor() != null && node.predecessor() instanceof FixedWithNextNode : "cannot add " + newNode + " before " + node;
- assert newNode.next() == null;
+ assert newNode.next() == null : newNode;
newNode.setProbability(node.probability());
FixedWithNextNode pred = (FixedWithNextNode) node.predecessor();
pred.setNext(newNode);
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -93,7 +93,7 @@
public void simplify(SimplifierTool tool) {
if (blockSuccessorCount() == 1) {
tool.addToWorkList(defaultSuccessor());
- ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+ ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor());
} else if (value() instanceof ConstantNode) {
int constant = value().asConstant().asInt();
@@ -109,7 +109,7 @@
}
}
tool.addToWorkList(blockSuccessor(survivingEdge));
- ((StructuredGraph) graph()).removeSplitPropagate(this, survivingEdge);
+ ((StructuredGraph) graph()).removeSplit(this, blockSuccessor(survivingEdge));
} else if (value() != null) {
IntegerStamp stamp = value().integerStamp();
if (!stamp.isUnrestricted()) {
@@ -121,7 +121,7 @@
}
if (validKeys == 0) {
tool.addToWorkList(defaultSuccessor());
- ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+ ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor());
} else if (validKeys != keys.length) {
ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount());
int[] newKeys = new int[validKeys];
diff -r 707e9cca11de -r 64f4195d0ecf 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 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Wed Dec 19 10:01:08 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.*;
@@ -31,10 +33,11 @@
* The {@code SwitchNode} class is the base of both lookup and table switches.
*/
public abstract class SwitchNode extends ControlSplitNode {
-
+ @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;
@@ -46,13 +49,26 @@
* @param successors the list of successors of this switch
*/
public SwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, int[] keySuccessors, double[] keyProbabilities) {
- super(StampFactory.forVoid(), successors, successorProbabilities);
+ super(StampFactory.forVoid());
+ this.successorProbabilities = successorProbabilities;
assert keySuccessors.length == keyProbabilities.length;
+ this.successors = new NodeSuccessorList<>(this, successors);
this.value = value;
this.keySuccessors = keySuccessors;
this.keyProbabilities = keyProbabilities;
}
+ @Override
+ public double probability(BeginNode successor) {
+ double sum = 0;
+ for (int i = 0; i < successors.size(); i++) {
+ if (successors.get(i) == successor) {
+ sum += successorProbabilities[i];
+ }
+ }
+ return sum;
+ }
+
/**
* The number of distinct keys in this switch.
*/
@@ -74,7 +90,7 @@
* Returns the successor for the key at the given index.
*/
public BeginNode keySuccessor(int i) {
- return blockSuccessor(keySuccessors[i]);
+ return successors.get(keySuccessors[i]);
}
/**
@@ -91,6 +107,18 @@
return keySuccessors[keySuccessors.length - 1];
}
+ public BeginNode blockSuccessor(int i) {
+ return successors.get(i);
+ }
+
+ public void setBlockSuccessor(int i, BeginNode s) {
+ successors.set(i, s);
+ }
+
+ public int blockSuccessorCount() {
+ return successors.count();
+ }
+
/**
* Gets the successor corresponding to the default (fall through) case.
* @return the default successor
@@ -99,7 +127,7 @@
if (defaultSuccessorIndex() == -1) {
throw new GraalInternalError("unexpected");
}
- return defaultSuccessorIndex() == -1 ? null : blockSuccessor(defaultSuccessorIndex());
+ return defaultSuccessorIndex() == -1 ? null : successors.get(defaultSuccessorIndex());
}
/**
@@ -113,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 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -99,7 +99,4 @@
@NodeIntrinsic
public static native T load(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind kind);
-
- @NodeIntrinsic
- public static native Object loadObject(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter boolean nonNull);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * The {@code InstanceOfDynamicNode} represents a type check where the type being checked
+ * is not known at compile time.
+ * This is used, for instance, to intrinsify {@link Class#isInstance(Object)}.
+ */
+public final class InstanceOfDynamicNode extends BooleanNode implements Canonicalizable, Lowerable {
+
+ @Input private ValueNode object;
+ @Input private ValueNode mirror;
+
+ /**
+ * Constructs a new InstanceOfNode.
+ *
+ * @param mirror the {@link Class} value representing the target target type of the instanceof check
+ * @param object the object being tested by the instanceof
+ */
+ public InstanceOfDynamicNode(ValueNode mirror, ValueNode object) {
+ super(StampFactory.condition());
+ this.mirror = mirror;
+ this.object = object;
+ assert mirror.kind() == Kind.Object;
+ assert mirror.objectStamp().isExactType();
+ assert mirror.objectStamp().type().getName().equals("Ljava/lang/Class;");
+ }
+
+ @Override
+ public void lower(LoweringTool tool) {
+ tool.getRuntime().lower(this, tool);
+ }
+
+ @Override
+ public ValueNode canonical(CanonicalizerTool tool) {
+ assert object() != null : this;
+ if (mirror().isConstant()) {
+ Class clazz = (Class) mirror().asConstant().asObject();
+ ResolvedJavaType t = tool.runtime().lookupJavaType(clazz);
+ return graph().unique(new InstanceOfNode(t, object(), null));
+ }
+ return this;
+ }
+
+ public ValueNode object() {
+ return object;
+ }
+
+ public ValueNode mirror() {
+ return mirror;
+ }
+
+ @Override
+ public boolean verify() {
+ for (Node usage : usages()) {
+ assertTrue(usage instanceof IfNode || usage instanceof ConditionalNode, "unsupported usage: ", usage);
+ }
+ return super.verify();
+ }
+}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -33,7 +33,7 @@
/**
* The {@code InstanceOfNode} represents an instanceof test.
*/
-public final class InstanceOfNode extends BooleanNode implements Canonicalizable, Lowerable, LIRLowerable, Virtualizable {
+public final class InstanceOfNode extends BooleanNode implements Canonicalizable, Lowerable, Virtualizable {
@Input private ValueNode object;
private final ResolvedJavaType type;
@@ -54,10 +54,6 @@
}
@Override
- public void generate(LIRGeneratorTool gen) {
- }
-
- @Override
public void lower(LoweringTool tool) {
tool.getRuntime().lower(this, tool);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Wed Dec 19 10:01:08 2012 +0100
@@ -91,7 +91,7 @@
}
}
tool.addToWorkList(blockSuccessor(survivingEdge));
- ((StructuredGraph) graph()).removeSplitPropagate(this, survivingEdge);
+ ((StructuredGraph) graph()).removeSplit(this, blockSuccessor(survivingEdge));
}
if (value() instanceof LoadHubNode) {
ObjectStamp stamp = ((LoadHubNode) value()).object().objectStamp();
@@ -104,7 +104,7 @@
}
if (validKeys == 0) {
tool.addToWorkList(defaultSuccessor());
- ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+ ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor());
} else if (validKeys != keys.length) {
ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount());
ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys];
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java Wed Dec 19 10:01:08 2012 +0100
@@ -104,7 +104,7 @@
//TTY.println(" Already explored, propagate update");
propagateUpdate(csInfo);
} else {
- if (csInfo.parentCount() == cs.blockSuccessorCount()) { // all paths leading to this CS have been explored
+ if (csInfo.parentCount() == cs.successors().count()) { // all paths leading to this CS have been explored
//TTY.println(" All parents explored, Enqueue");
toExplore.add(next);
speculativeExplore.remove(next);
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -244,7 +244,7 @@
}
@Override
- public void afterSplit(FixedNode node) {
+ public void afterSplit(BeginNode node) {
assert node.predecessor() != null;
Node pred = node.predecessor();
if (pred instanceof Invoke) {
@@ -255,13 +255,7 @@
} else {
assert pred instanceof ControlSplitNode;
ControlSplitNode x = (ControlSplitNode) pred;
- double sum = 0;
- for (int i = 0; i < x.blockSuccessorCount(); i++) {
- if (x.blockSuccessor(i) == node) {
- sum += x.probability(i);
- }
- }
- probability *= sum;
+ probability *= x.probability(node);
}
}
}
@@ -316,7 +310,7 @@
}
@Override
- public void afterSplit(FixedNode node) {
+ public void afterSplit(BeginNode node) {
// nothing to do...
}
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -214,7 +214,7 @@
}
@Override
- public void afterSplit(FixedNode node) {
+ public void afterSplit(BeginNode node) {
}
@Override
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -49,11 +49,11 @@
BeginNode insertGuard = null;
BeginNode delete = null;
boolean inverted = false;
- if (ifNode.probability(IfNode.TRUE_EDGE) == 0) {
+ if (ifNode.probability(ifNode.trueSuccessor()) == 0) {
insertGuard = ifNode.falseSuccessor();
delete = ifNode.trueSuccessor();
inverted = true;
- } else if (ifNode.probability(IfNode.FALSE_EDGE) == 0) {
+ } else if (ifNode.probability(ifNode.falseSuccessor()) == 0) {
insertGuard = ifNode.trueSuccessor();
delete = ifNode.falseSuccessor();
}
@@ -61,7 +61,7 @@
GuardNode guard = graph.unique(new GuardNode(ifNode.condition(), BeginNode.prevBegin(ifNode), DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, inverted, ifNode.leafGraphId()));
graph.addBeforeFixed(ifNode, graph.add(new ValueAnchorNode(guard)));
GraphUtil.killCFG(delete);
- graph.removeSplit(ifNode, inverted ? IfNode.FALSE_EDGE : IfNode.TRUE_EDGE);
+ graph.removeSplit(ifNode, inverted ? ifNode.falseSuccessor() : ifNode.trueSuccessor());
}
}
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -87,7 +87,7 @@
}
@Override
- public void afterSplit(FixedNode node) {
+ public void afterSplit(BeginNode node) {
}
@Override
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -149,7 +149,8 @@
private static boolean eliminateAtControlSplit(ControlSplitNode controlSplit) {
Map> conditionToGuard = new HashMap<>();
- for (BeginNode begin : controlSplit.blockSuccessors()) {
+ for (Node successor : controlSplit.successors()) {
+ BeginNode begin = (BeginNode) successor;
for (GuardNode guard : begin.guards()) {
if (guard.dependencies().size() != 1) {
continue;
@@ -196,7 +197,7 @@
if (leafGraphId < 0) {
continue;
}
- if (begins.size() == controlSplit.blockSuccessors().count()) {
+ if (begins.size() == controlSplit.successors().count()) {
hits = true;
Condition condition = entry.getKey();
GuardNode newGuard = controlSplit.graph().unique(new GuardNode(condition.conditionNode, BeginNode.prevBegin(controlSplit), reason, action, condition.negated, leafGraphId));
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -157,7 +157,7 @@
}
@Override
- public void afterSplit(FixedNode node) {
+ public void afterSplit(BeginNode node) {
// nothing
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Dec 19 10:01:08 2012 +0100
@@ -576,11 +576,11 @@
assert exceptionMerge != null && exceptionObjectPhi != null;
InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
- BeginNode exceptionEdge = invokeWithException.exceptionEdge();
+ DispatchBeginNode exceptionEdge = invokeWithException.exceptionEdge();
ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
FrameState stateAfterException = exceptionObject.stateAfter();
- BeginNode newExceptionEdge = (BeginNode) exceptionEdge.copyWithInputs();
+ DispatchBeginNode newExceptionEdge = (DispatchBeginNode) exceptionEdge.copyWithInputs();
ExceptionObjectNode newExceptionObject = (ExceptionObjectNode) exceptionObject.copyWithInputs();
// set new state (pop old exception object, push new one)
newExceptionObject.setStateAfter(stateAfterException.duplicateModified(stateAfterException.bci, stateAfterException.rethrowException(), Kind.Object, newExceptionObject));
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java Wed Dec 19 10:01:08 2012 +0100
@@ -31,5 +31,5 @@
boolean merge(MergeNode merge, List withStates);
void loopBegin(LoopBeginNode loopBegin);
void loopEnds(LoopBeginNode loopBegin, List loopEndStates);
- void afterSplit(FixedNode node);
+ void afterSplit(BeginNode node);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Wed Dec 19 10:01:08 2012 +0100
@@ -38,7 +38,7 @@
public abstract class PostOrderNodeIterator> {
private final NodeBitMap visitedEnds;
- private final Deque nodeQueue;
+ private final Deque nodeQueue;
private final IdentityHashMap nodeStates;
private final FixedNode start;
@@ -109,13 +109,13 @@
for (Node node : successors) {
if (node != null) {
nodeStates.put((FixedNode) node.predecessor(), state);
- nodeQueue.addFirst((FixedNode) node);
+ nodeQueue.addFirst((BeginNode) node);
}
}
} else {
for (Node node : x.successors()) {
if (node != null) {
- nodeQueue.addFirst((FixedNode) node);
+ nodeQueue.addFirst((BeginNode) node);
}
}
}
@@ -124,7 +124,7 @@
private FixedNode nextQueuedNode() {
int maxIterations = nodeQueue.size();
while (maxIterations-- > 0) {
- FixedNode node = nodeQueue.removeFirst();
+ BeginNode node = nodeQueue.removeFirst();
if (node instanceof MergeNode) {
MergeNode merge = (MergeNode) node;
state = nodeStates.get(merge.forwardEndAt(0)).clone();
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfDynamicTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfDynamicTest.java Wed Dec 19 10:01:08 2012 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * Tests for {@link InstanceOfDynamicNode}.
+ */
+public class InstanceOfDynamicTest extends GraalCompilerTest {
+
+ public static int id(int value) {
+ return value;
+ }
+
+ @Test
+ public void test100() {
+ final Object nul = null;
+ test("isStringDynamic", nul);
+ test("isStringDynamic", "object");
+ test("isStringDynamic", Object.class);
+ }
+
+ @Test
+ public void test101() {
+ final Object nul = null;
+ test("isStringIntDynamic", nul);
+ test("isStringIntDynamic", "object");
+ test("isStringIntDynamic", Object.class);
+ }
+
+ @Test
+ public void test103() {
+ test("isInstanceDynamic", String.class, null);
+ test("isInstanceDynamic", String.class, "object");
+ test("isInstanceDynamic", String.class, Object.class);
+ }
+
+ @Test
+ public void test104() {
+ test("isInstanceIntDynamic", String.class, null);
+ test("isInstanceIntDynamic", String.class, "object");
+ test("isInstanceIntDynamic", String.class, Object.class);
+ }
+
+ public static boolean isStringDynamic(Object o) {
+ return String.class.isInstance(o);
+ }
+
+ public static int isStringIntDynamic(Object o) {
+ if (String.class.isInstance(o)) {
+ return o.toString().length();
+ }
+ return o.getClass().getName().length();
+ }
+
+ public static boolean isInstanceDynamic(Class c, Object o) {
+ return c.isInstance(o);
+ }
+
+ public static int isInstanceIntDynamic(Class c, Object o) {
+ if (c.isInstance(o)) {
+ return o.toString().length();
+ }
+ return o.getClass().getName().length();
+ }
+}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java Wed Dec 19 10:01:08 2012 +0100
@@ -65,7 +65,7 @@
@Test
public void testClassIntrinsics() {
test("getModifiersSnippet");
-// test("isInstanceSnippet");
+ test("isInstanceSnippet");
test("isInterfaceSnippet");
test("isArraySnippet");
test("isPrimitiveSnippet");
@@ -128,7 +128,6 @@
public void testSystemIntrinsics() {
test("systemTimeSnippet");
test("systemIdentityHashCode");
-// test("arraycopySnippet");
}
@SuppressWarnings("all")
@@ -140,10 +139,6 @@
public static int systemIdentityHashCode(Object obj) {
return System.identityHashCode(obj);
}
- @SuppressWarnings("all")
- public static void arraycopySnippet(int[] src, int srcPos, int[] dest, int destPos, int length) {
- System.arraycopy(src, srcPos, dest, destPos, length);
- }
@Test
@@ -400,7 +395,7 @@
private StructuredGraph test(final String snippet) {
- return Debug.scope("IntrinsificationTest", new DebugDumpScope(snippet), new Callable() {
+ return Debug.scope("IntrinsificationTest", runtime.lookupJavaMethod(getMethod(snippet)), new Callable() {
@Override
public StructuredGraph call() {
StructuredGraph graph = parse(snippet);
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewMultiArrayTest.java
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewMultiArrayTest.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewMultiArrayTest.java Wed Dec 19 10:01:08 2012 +0100
@@ -38,32 +38,6 @@
*/
public class NewMultiArrayTest extends GraalCompilerTest {
- @Override
- protected void assertEquals(Object expected, Object actual) {
- Assert.assertTrue(expected != null);
- Assert.assertTrue(actual != null);
- super.assertEquals(expected.getClass(), actual.getClass());
- if (expected instanceof int[]) {
- Assert.assertArrayEquals((int[]) expected, (int[]) actual);
- } else if (expected instanceof byte[]) {
- Assert.assertArrayEquals((byte[]) expected, (byte[]) actual);
- } else if (expected instanceof char[]) {
- Assert.assertArrayEquals((char[]) expected, (char[]) actual);
- } else if (expected instanceof short[]) {
- Assert.assertArrayEquals((short[]) expected, (short[]) actual);
- } else if (expected instanceof float[]) {
- Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f);
- } else if (expected instanceof long[]) {
- Assert.assertArrayEquals((long[]) expected, (long[]) actual);
- } else if (expected instanceof double[]) {
- Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d);
- } else if (expected instanceof Object[]) {
- Assert.assertArrayEquals((Object[]) expected, (Object[]) actual);
- } else {
- Assert.fail("non-array value encountered: " + expected);
- }
- }
-
private static int rank(ResolvedJavaType type) {
String name = type.getName();
int dims = 0;
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Wed Dec 19 10:01:08 2012 +0100
@@ -53,7 +53,7 @@
@Override
protected StructuredGraph parse(Method m) {
ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m);
- return installer.makeGraph(resolvedMethod, inliningPolicy.get());
+ return installer.makeGraph(resolvedMethod, inliningPolicy.get(), false);
}
@Test
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Wed Dec 19 10:01:08 2012 +0100
@@ -77,7 +77,8 @@
*/
protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
- public void lower(InstanceOfNode instanceOf, LoweringTool tool) {
+ public void lower(FloatingNode instanceOf, LoweringTool tool) {
+ assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
List usages = instanceOf.usages().snapshot();
int nUsages = usages.size();
@@ -107,7 +108,7 @@
* Gets the specific replacer object used to replace the usage of an instanceof node
* with the result of an instantiated instanceof snippet.
*/
- protected InstanceOfUsageReplacer createReplacer(InstanceOfNode instanceOf, LoweringTool tool, int nUsages, Instantiation instantiation, Node usage, final StructuredGraph graph) {
+ protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, LoweringTool tool, int nUsages, Instantiation instantiation, Node usage, final StructuredGraph graph) {
InstanceOfUsageReplacer replacer;
if (usage instanceof IfNode) {
replacer = new IfUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, (IfNode) usage, nUsages == 1, tool);
@@ -175,15 +176,16 @@
}
/**
- * Replaces a usage of an {@link InstanceOfNode}.
+ * Replaces a usage of an {@link InstanceOfNode} or {@link InstanceOfDynamicNode}.
*/
public abstract static class InstanceOfUsageReplacer implements UsageReplacer {
public final Instantiation instantiation;
- public final InstanceOfNode instanceOf;
+ public final FloatingNode instanceOf;
public final ValueNode trueValue;
public final ValueNode falseValue;
- public InstanceOfUsageReplacer(Instantiation instantiation, InstanceOfNode instanceOf, ValueNode trueValue, ValueNode falseValue) {
+ public InstanceOfUsageReplacer(Instantiation instantiation, FloatingNode instanceOf, ValueNode trueValue, ValueNode falseValue) {
+ assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
this.instantiation = instantiation;
this.instanceOf = instanceOf;
this.trueValue = trueValue;
@@ -197,7 +199,7 @@
}
/**
- * Replaces an {@link IfNode} usage of an {@link InstanceOfNode}.
+ * Replaces an {@link IfNode} usage of an {@link InstanceOfNode} or {@link InstanceOfDynamicNode}.
*/
public static class IfUsageReplacer extends InstanceOfUsageReplacer {
@@ -205,7 +207,7 @@
private final IfNode usage;
private final boolean sameBlock;
- public IfUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, InstanceOfNode instanceOf, IfNode usage, boolean solitaryUsage, LoweringTool tool) {
+ public IfUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, IfNode usage, boolean solitaryUsage, LoweringTool tool) {
super(instantiation, instanceOf, trueValue, falseValue);
this.sameBlock = tool.getBlockFor(usage) == tool.getBlockFor(instanceOf);
this.solitaryUsage = solitaryUsage;
@@ -294,13 +296,13 @@
}
/**
- * Replaces a {@link ConditionalNode} usage of an {@link InstanceOfNode}.
+ * Replaces a {@link ConditionalNode} usage of an {@link InstanceOfNode} or {@link InstanceOfDynamicNode}.
*/
public static class ConditionalUsageReplacer extends InstanceOfUsageReplacer {
public final ConditionalNode usage;
- public ConditionalUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, InstanceOfNode instanceOf, ConditionalNode usage) {
+ public ConditionalUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, ConditionalNode usage) {
super(instantiation, instanceOf, trueValue, falseValue);
this.usage = usage;
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetFrameStateCleanupPhase.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetFrameStateCleanupPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Removes frame states from {@linkplain StateSplit#hasSideEffect() non-side-effecting} nodes in a snippet.
+ */
+public class SnippetFrameStateCleanupPhase extends Phase {
+
+ @Override
+ protected void run(StructuredGraph graph) {
+ for (Node node : graph.getNodes().filterInterface(StateSplit.class)) {
+ StateSplit stateSplit = (StateSplit) node;
+ FrameState frameState = stateSplit.stateAfter();
+ if (!stateSplit.hasSideEffect()) {
+ if (frameState != null) {
+ stateSplit.setStateAfter(null);
+ if (frameState.usages().isEmpty()) {
+ GraphUtil.killWithUnusedFloatingInputs(frameState);
+ }
+ }
+ }
+ }
+ }
+}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Wed Dec 19 10:01:08 2012 +0100
@@ -93,7 +93,7 @@
}
ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method);
assert snippet.getCompilerStorage().get(Graph.class) == null : method;
- StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet));
+ StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet), false);
//System.out.println("snippet: " + graph);
snippet.getCompilerStorage().put(Graph.class, graph);
}
@@ -131,7 +131,7 @@
throw new RuntimeException("Snippet must not be abstract or native");
}
ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method);
- StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet));
+ StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet), true);
//System.out.println("snippet: " + graph);
runtime.lookupJavaMethod(originalMethod).getCompilerStorage().put(Graph.class, graph);
} catch (NoSuchMethodException e) {
@@ -156,14 +156,28 @@
}
}
- public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
- StructuredGraph graph = parseGraph(method, policy);
+ public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy, final boolean isSubstitutionSnippet) {
+ return Debug.scope("BuildSnippetGraph", new Object[] {method}, new Callable() {
+ @Override
+ public StructuredGraph call() throws Exception {
+ StructuredGraph graph = parseGraph(method, policy);
+
+ new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph);
- new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph);
+ if (isSubstitutionSnippet) {
+ // TODO (ds) remove the constraint of only processing substitution snippets
+ // once issues with the arraycopy snippets have been resolved
+ new SnippetFrameStateCleanupPhase().apply(graph);
+ new DeadCodeEliminationPhase().apply(graph);
+ }
- Debug.dump(graph, "%s: Final", method.getName());
+ new InsertStateAfterPlaceholderPhase().apply(graph);
+
+ Debug.dump(graph, "%s: Final", method.getName());
- return graph;
+ return graph;
+ }
+ });
}
private StructuredGraph parseGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
@@ -178,54 +192,47 @@
private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) {
final StructuredGraph graph = new StructuredGraph(method);
- return Debug.scope("BuildSnippetGraph", new Object[] {method, graph}, new Callable() {
- @Override
- public StructuredGraph call() throws Exception {
- GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
- GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
- graphBuilder.apply(graph);
+ GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
+ GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
+ graphBuilder.apply(graph);
- Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName());
+ Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName());
- new SnippetVerificationPhase(runtime).apply(graph);
+ new SnippetVerificationPhase(runtime).apply(graph);
- new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
+ new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
- for (Invoke invoke : graph.getInvokes()) {
- MethodCallTargetNode callTarget = invoke.methodCallTarget();
- ResolvedJavaMethod callee = callTarget.targetMethod();
- if (policy.shouldInline(callee, method)) {
- StructuredGraph targetGraph = parseGraph(callee, policy);
- InliningUtil.inline(invoke, targetGraph, true);
- Debug.dump(graph, "after inlining %s", callee);
- if (GraalOptions.OptCanonicalizer) {
- new WordTypeRewriterPhase(target.wordKind).apply(graph);
- new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
- }
- }
- }
-
- new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
-
- new WordTypeRewriterPhase(target.wordKind).apply(graph);
-
- new DeadCodeEliminationPhase().apply(graph);
+ for (Invoke invoke : graph.getInvokes()) {
+ MethodCallTargetNode callTarget = invoke.methodCallTarget();
+ ResolvedJavaMethod callee = callTarget.targetMethod();
+ if (policy.shouldInline(callee, method)) {
+ StructuredGraph targetGraph = parseGraph(callee, policy);
+ InliningUtil.inline(invoke, targetGraph, true);
+ Debug.dump(graph, "after inlining %s", callee);
if (GraalOptions.OptCanonicalizer) {
+ new WordTypeRewriterPhase(target.wordKind).apply(graph);
new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
}
+ }
+ }
- for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
- end.disableSafepoint();
- }
+ new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
- new InsertStateAfterPlaceholderPhase().apply(graph);
+ new WordTypeRewriterPhase(target.wordKind).apply(graph);
- if (GraalOptions.ProbabilityAnalysis) {
- new DeadCodeEliminationPhase().apply(graph);
- new ComputeProbabilityPhase().apply(graph);
- }
- return graph;
- }
- });
+ new DeadCodeEliminationPhase().apply(graph);
+ if (GraalOptions.OptCanonicalizer) {
+ new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+ }
+
+ for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
+ end.disableSafepoint();
+ }
+
+ if (GraalOptions.ProbabilityAnalysis) {
+ new DeadCodeEliminationPhase().apply(graph);
+ new ComputeProbabilityPhase().apply(graph);
+ }
+ return graph;
}
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -221,7 +221,7 @@
InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
invokeWithExceptionNode.killExceptionEdge();
- graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
+ graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
} else {
graph.removeFixed((InvokeNode) invokeNode);
}
@@ -381,7 +381,7 @@
InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
invokeWithExceptionNode.killExceptionEdge();
- graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
+ graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
} else {
graph.removeFixed((InvokeNode) invokeNode);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Wed Dec 19 10:01:08 2012 +0100
@@ -208,7 +208,9 @@
throw new GraalInternalError(e);
}
}
-}
+ }
+
+ private static final Object UNUSED_PARAMETER = "DEAD PARAMETER";
/**
* Determines if any parameter of a given method is annotated with {@link ConstantParameter}.
@@ -315,8 +317,12 @@
Parameter p = parameterAnnotations[i];
if (p != null) {
LocalNode local = snippetCopy.getLocal(i);
- assert local != null;
- parameters.put(p.value(), local);
+ if (local == null) {
+ // Parameter value was eliminated
+ parameters.put(p.value(), UNUSED_PARAMETER);
+ } else {
+ parameters.put(p.value(), local);
+ }
}
}
}
@@ -431,7 +437,9 @@
/**
* The named parameters of this template that must be bound to values during instantiation.
- * Each value in this map is either a {@link LocalNode} instance or a {@link LocalNode} array.
+ * For a parameter that is still live after specialization, the value in this map is either
+ * a {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter,
+ * the value is identical to the key.
*/
private final Map parameters;
@@ -477,8 +485,7 @@
Constant constant = Constant.forBoxed(kind, argument);
replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph));
}
- } else {
- assert parameter instanceof LocalNode[];
+ } else if (parameter instanceof LocalNode[]) {
LocalNode[] locals = (LocalNode[]) parameter;
Object array = argument;
assert array != null && array.getClass().isArray();
@@ -496,6 +503,8 @@
replacements.put(local, element);
}
}
+ } else {
+ assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter;
}
}
return replacements;
@@ -673,7 +682,9 @@
Object value = e.getValue();
buf.append(sep);
sep = ", ";
- if (value instanceof LocalNode) {
+ if (value == UNUSED_PARAMETER) {
+ buf.append(" ").append(name);
+ } else if (value instanceof LocalNode) {
LocalNode local = (LocalNode) value;
buf.append(local.kind().getJavaName()).append(' ').append(name);
} else {
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java Wed Dec 19 10:01:08 2012 +0100
@@ -58,6 +58,10 @@
OR,
AND,
XOR,
+ READ_INT,
+ READ_WORD,
+ READ_OBJECT,
+ READ_FINAL_OBJECT,
BELOW,
BELOW_EQUAL,
ABOVE,
@@ -237,4 +241,20 @@
return new Word(value | other.value, null);
}
+ @Operation(READ_INT)
+ public native int readInt(int offset);
+
+ @Operation(READ_WORD)
+ public native Word readWord(int offset);
+
+ @Operation(READ_OBJECT)
+ public native Object readObject(int offset);
+
+ /**
+ * Reads an object value from a location that is guaranteed not be to modified after this read.
+ *
+ * @param offset the offset from this base address of the location to be read
+ */
+ @Operation(READ_FINAL_OBJECT)
+ public native Object readFinalObject(int offset);
}
diff -r 707e9cca11de -r 64f4195d0ecf graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Tue Dec 18 15:05:58 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Wed Dec 19 10:01:08 2012 +0100
@@ -212,6 +212,18 @@
break;
}
+ case READ_INT:
+ case READ_OBJECT:
+ case READ_WORD: {
+ replaceRead(graph, arguments, invoke, LocationNode.ANY_LOCATION);
+ break;
+ }
+
+ case READ_FINAL_OBJECT: {
+ replaceRead(graph, arguments, invoke, LocationNode.FINAL_LOCATION);
+ break;
+ }
+
default: {
throw new GraalInternalError("Unknown opcode: %s", opcode);
}
@@ -220,6 +232,17 @@
}
}
+ protected void replaceRead(StructuredGraph graph, NodeInputList arguments, Invoke invoke, Object locationIdentity) {
+ assert arguments.size() == 2;
+ ValueNode base = arguments.first();
+ IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, arguments.last(), graph, false);
+ ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp()));
+ graph.addBeforeFixed(invoke.node(), read);
+ // The read must not float outside its block otherwise it may float above an explicit zero check on its base address
+ read.dependencies().add(BeginNode.prevBegin(invoke.node()));
+ replace(invoke, read);
+ }
+
protected void replace(Invoke invoke, ValueNode value) {
FixedNode next = invoke.next();
invoke.setNext(null);
diff -r 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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 707e9cca11de -r 64f4195d0ecf 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 Wed Dec 19 10:01:08 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