# HG changeset patch # User Stefan Anzinger # Date 1404122539 -7200 # Node ID 5f01f7c48d40ef59b9c78a5833be146b993f013e # Parent 51f39255712497a8faf9616d400fd6d9c99ce4e9# Parent 5cdcb94a7cf7d9782107cc582f3e4b50000d5d1f Merge with 5cdcb94a7cf7d9782107cc582f3e4b50000d5d1f diff -r 51f392557124 -r 5f01f7c48d40 .hgignore --- a/.hgignore Mon Jun 30 08:50:26 2014 +0200 +++ b/.hgignore Mon Jun 30 12:02:19 2014 +0200 @@ -88,3 +88,6 @@ agent/make/filelist agent/make/sa17.tar.gz export.json +.recommenders +syntax: regexp +test\.[0-9]+\.er diff -r 51f392557124 -r 5f01f7c48d40 CHANGELOG.md --- a/CHANGELOG.md Mon Jun 30 08:50:26 2014 +0200 +++ b/CHANGELOG.md Mon Jun 30 12:02:19 2014 +0200 @@ -9,6 +9,7 @@ ### Truffle * `truffle.jar`: strip out build-time only dependency into a seperated JAR file (`truffle-dsl-processor.jar`) +* New flag -G:+TraceTruffleCompilationAST to print the AST before compilation. * ... ## Version 0.3 diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java --- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Mon Jun 30 12:02:19 2014 +0200 @@ -38,7 +38,6 @@ public class AMD64 extends Architecture { public static final RegisterCategory CPU = new RegisterCategory("CPU"); - public static final RegisterCategory XMM = new RegisterCategory("XMM"); // @formatter:off @@ -66,6 +65,10 @@ r8, r9, r10, r11, r12, r13, r14, r15 }; + private static final int XMM_REFERENCE_MAP_SHIFT = 2; + + public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT); + // XMM registers public static final Register xmm0 = new Register(16, 0, "xmm0", XMM); public static final Register xmm1 = new Register(17, 1, "xmm1", XMM); @@ -135,7 +138,7 @@ private final EnumSet features; public AMD64(EnumSet features) { - super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, r15.encoding + 1, 8); + super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT, 8); this.features = features; assert features.contains(CPUFeature.SSE2) : "minimum config for x64"; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Mon Jun 30 12:02:19 2014 +0200 @@ -34,11 +34,11 @@ public abstract class Architecture { /** - * The number of bits required in a bit map covering all the registers that may store - * references. The bit position of a register in the map is the register's - * {@linkplain Register#number number}. + * The number of entries required in a {@link ReferenceMap} covering all the registers that may + * store references. The index of a register in the reference map is given by + * {@link Register#getReferenceMapIndex()}. */ - private final int registerReferenceMapBitCount; + private final int registerReferenceMapSize; /** * Represents the natural size of words (typically registers and pointers) of this architecture, @@ -85,7 +85,7 @@ private final int returnAddressSize; protected Architecture(String name, int wordSize, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset, - int registerReferenceMapBitCount, int returnAddressSize) { + int registerReferenceMapSize, int returnAddressSize) { this.name = name; this.registers = registers; this.wordSize = wordSize; @@ -93,13 +93,13 @@ this.unalignedMemoryAccess = unalignedMemoryAccess; this.implicitMemoryBarriers = implicitMemoryBarriers; this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset; - this.registerReferenceMapBitCount = registerReferenceMapBitCount; + this.registerReferenceMapSize = registerReferenceMapSize; this.returnAddressSize = returnAddressSize; } /** * Converts this architecture to a string. - * + * * @return the string representation of this architecture */ @Override @@ -107,8 +107,8 @@ return getName().toLowerCase(); } - public int getRegisterReferenceMapBitCount() { - return registerReferenceMapBitCount; + public int getRegisterReferenceMapSize() { + return registerReferenceMapSize; } /** @@ -163,7 +163,7 @@ /** * Determines the barriers in a given barrier mask that are explicitly required on this * architecture. - * + * * @param barriers a mask of the barrier constants * @return the value of {@code barriers} minus the barriers unnecessary on this architecture */ @@ -173,9 +173,9 @@ /** * Gets the size in bytes of the specified kind for this target. - * + * * @param kind the kind for which to get the size - * + * * @return the size in bytes of {@code kind} */ public int getSizeInBytes(PlatformKind kind) { @@ -205,7 +205,7 @@ /** * Determine whether a kind can be stored in a register of a given category. - * + * * @param category the category of the register * @param kind the kind that should be stored in the register */ @@ -213,7 +213,7 @@ /** * Return the largest kind that can be stored in a register of a given category. - * + * * @param category the category of the register * @return the largest kind that can be stored in a register {@code category} */ diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Mon Jun 30 12:02:19 2014 +0200 @@ -27,9 +27,9 @@ public interface ReferenceMap { - void setRegister(int idx, PlatformKind kind); + void setRegister(int idx, LIRKind kind); - void setStackSlot(int offset, PlatformKind kind); + void setStackSlot(int offset, LIRKind kind); boolean hasRegisterRefMap(); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -79,10 +79,23 @@ */ public static class RegisterCategory { - private String name; + private final String name; + + private final int referenceMapOffset; + private final int referenceMapShift; public RegisterCategory(String name) { + this(name, 0, 0); + } + + public RegisterCategory(String name, int referenceMapOffset) { + this(name, referenceMapOffset, 0); + } + + public RegisterCategory(String name, int referenceMapOffset, int referenceMapShift) { this.name = name; + this.referenceMapOffset = referenceMapOffset; + this.referenceMapShift = referenceMapShift; } @Override @@ -107,7 +120,7 @@ /** * Creates a {@link Register} instance. - * + * * @param number unique identifier for the register * @param encoding the target machine encoding for the register * @param name the mnemonic name for the register @@ -125,27 +138,34 @@ } /** + * Get the start index of this register in the {@link ReferenceMap}. + */ + public int getReferenceMapIndex() { + return (encoding << registerCategory.referenceMapShift) + registerCategory.referenceMapOffset; + } + + /** * Gets this register as a {@linkplain RegisterValue value} with a specified kind. - * + * * @param kind the specified kind * @return the {@link RegisterValue} */ - public RegisterValue asValue(PlatformKind kind) { + public RegisterValue asValue(LIRKind kind) { return new RegisterValue(kind, this); } /** * Gets this register as a {@linkplain RegisterValue value} with no particular kind. - * + * * @return a {@link RegisterValue} with {@link Kind#Illegal} kind. */ public RegisterValue asValue() { - return asValue(Kind.Illegal); + return asValue(LIRKind.Illegal); } /** * Determines if this is a valid register. - * + * * @return {@code true} iff this register is valid */ public boolean isValid() { @@ -154,7 +174,7 @@ /** * Gets the maximum register {@linkplain #number number} in a given set of registers. - * + * * @param registers the set of registers to process * @return the maximum register number for any register in {@code registers} */ @@ -170,7 +190,7 @@ /** * Gets the maximum register {@linkplain #encoding encoding} in a given set of registers. - * + * * @param registers the set of registers to process * @return the maximum register encoding for any register in {@code registers} */ diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -27,8 +27,8 @@ /** * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance * of {@link RegisterValue} for each ({@link Register}, {@link Kind}) pair. Use - * {@link Register#asValue(PlatformKind)} to retrieve the canonical {@link RegisterValue} instance - * for a given (register,kind) pair. + * {@link Register#asValue(LIRKind)} to retrieve the canonical {@link RegisterValue} instance for a + * given (register,kind) pair. */ public final class RegisterValue extends AllocatableValue { @@ -39,7 +39,7 @@ /** * Should only be called from {@link Register#Register} to ensure canonicalization. */ - protected RegisterValue(PlatformKind kind, Register register) { + protected RegisterValue(LIRKind kind, Register register) { super(kind); this.reg = register; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, 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 @@ -38,22 +38,22 @@ /** * Gets a {@link StackSlot} instance representing a stack slot at a given index holding a value * of a given kind. - * + * * @param kind The kind of the value stored in the stack slot. * @param offset The offset of the stack slot (in bytes) * @param addFrameSize Specifies if the offset is relative to the stack pointer, or the * beginning of the frame (stack pointer + total frame size). */ - public static StackSlot get(PlatformKind kind, int offset, boolean addFrameSize) { + public static StackSlot get(LIRKind kind, int offset, boolean addFrameSize) { assert addFrameSize || offset >= 0; return new StackSlot(kind, offset, addFrameSize); } /** - * Private constructor to enforce use of {@link #get(PlatformKind, int, boolean)} so that a - * cache can be used. + * Private constructor to enforce use of {@link #get(LIRKind, int, boolean)} so that a cache can + * be used. */ - private StackSlot(PlatformKind kind, int offset, boolean addFrameSize) { + private StackSlot(LIRKind kind, int offset, boolean addFrameSize) { super(kind); this.offset = offset; this.addFrameSize = addFrameSize; @@ -61,7 +61,7 @@ /** * Gets the offset of this stack slot, relative to the stack pointer. - * + * * @return The offset of this slot (in bytes). */ public int getOffset(int totalFrameSize) { @@ -100,7 +100,7 @@ public StackSlot asOutArg() { assert offset >= 0; if (addFrameSize) { - return get(getPlatformKind(), offset, false); + return get(getLIRKind(), offset, false); } return this; } @@ -111,7 +111,7 @@ public StackSlot asInArg() { assert offset >= 0; if (!addFrameSize) { - return get(getPlatformKind(), offset, true); + return get(getLIRKind(), offset, true); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -56,7 +56,7 @@ * The stack alignment requirement of the platform. For example, from Appendix D of Intel 64 and IA-32 Architectures * Optimization Reference Manual: - * + * *
      *     "It is important to ensure that the stack frame is aligned to a
      *      16-byte boundary upon function entry to keep local __m128 data,
@@ -86,5 +86,23 @@
         return arch.getSizeInBytes(kind);
     }
 
+    public LIRKind getLIRKind(Kind javaKind) {
+        switch (javaKind) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
+            case Int:
+            case Long:
+            case Float:
+            case Double:
+                return LIRKind.value(javaKind);
+            case Object:
+                return LIRKind.reference(javaKind);
+            default:
+                return LIRKind.Illegal;
+        }
+    }
+
     public abstract ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount);
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, 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
@@ -47,7 +47,7 @@
      * returned by {@link ResolvedJavaType#getInstanceFields(boolean) getInstanceFields(true)}. If
      * {@code type} is an array then the length of the values array determines the reallocated array
      * length.
-     * 
+     *
      * @param type the type of the object whose allocation was removed during compilation. This can
      *            be either an instance of an array type.
      * @param values an array containing all the values to be stored into the object when it is
@@ -61,7 +61,7 @@
     }
 
     private VirtualObject(ResolvedJavaType type, Value[] values, int id) {
-        super(Kind.Object);
+        super(LIRKind.reference(Kind.Object));
         this.type = type;
         this.values = values;
         this.id = id;
@@ -164,7 +164,7 @@
 
     /**
      * Overwrites the current set of values with a new one.
-     * 
+     *
      * @param values an array containing all the values to be stored into the object when it is
      *            recreated.
      */
@@ -175,7 +175,7 @@
 
     @Override
     public int hashCode() {
-        return getPlatformKind().hashCode() + type.hashCode();
+        return getLIRKind().hashCode() + type.hashCode();
     }
 
     @Override
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/ConstantTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/ConstantTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 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.api.meta.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+
+public class ConstantTest extends FieldUniverse {
+
+    @Test
+    public void testNegativeZero() {
+        Assert.assertTrue("Constant for 0.0f must be different from -0.0f", Constant.FLOAT_0 != Constant.forFloat(-0.0F));
+        Assert.assertTrue("Constant for 0.0d must be different from -0.0d", Constant.DOUBLE_0 != Constant.forDouble(-0.0d));
+    }
+
+    @Test
+    public void testNullIsNull() {
+        Assert.assertTrue(Constant.NULL_OBJECT.isNull());
+    }
+
+    @Test
+    public void testOne() {
+        for (Kind kind : Kind.values()) {
+            if (kind.isNumericInteger() || kind.isNumericFloat()) {
+                Assert.assertTrue(Constant.one(kind).getKind() == kind);
+            }
+        }
+        Assert.assertEquals(1, Constant.one(Kind.Int).asInt());
+        Assert.assertEquals(1L, Constant.one(Kind.Long).asLong());
+        Assert.assertEquals(1, Constant.one(Kind.Byte).asInt());
+        Assert.assertEquals(1, Constant.one(Kind.Short).asInt());
+        Assert.assertEquals(1, Constant.one(Kind.Char).asInt());
+        Assert.assertTrue(1F == Constant.one(Kind.Float).asFloat());
+        Assert.assertTrue(1D == Constant.one(Kind.Double).asDouble());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllegalOne() {
+        Constant.one(Kind.Illegal);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testVoidOne() {
+        Constant.one(Kind.Void);
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AllocatableValue.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AllocatableValue.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AllocatableValue.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -32,7 +32,7 @@
 
     public static final AllocatableValue[] NONE = {};
 
-    public AllocatableValue(PlatformKind platformKind) {
-        super(platformKind);
+    public AllocatableValue(LIRKind lirKind) {
+        super(lirKind);
     }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -32,38 +32,25 @@
 
     private static final long serialVersionUID = -6355452536852663986L;
 
-    private static final Constant[] INT_CONSTANT_CACHE = new Constant[100];
-    static {
-        for (int i = 0; i < INT_CONSTANT_CACHE.length; ++i) {
-            INT_CONSTANT_CACHE[i] = new PrimitiveConstant(Kind.Int, i);
-        }
-    }
-
+    /*
+     * Using a larger cache for integers leads to only a slight increase in cache hit ratio which is
+     * not enough to justify the impact on startup time.
+     */
     public static final Constant NULL_OBJECT = new NullConstant();
     public static final Constant INT_MINUS_1 = new PrimitiveConstant(Kind.Int, -1);
-    public static final Constant INT_0 = forInt(0);
-    public static final Constant INT_1 = forInt(1);
-    public static final Constant INT_2 = forInt(2);
-    public static final Constant INT_3 = forInt(3);
-    public static final Constant INT_4 = forInt(4);
-    public static final Constant INT_5 = forInt(5);
+    public static final Constant INT_0 = new PrimitiveConstant(Kind.Int, 0);
+    public static final Constant INT_1 = new PrimitiveConstant(Kind.Int, 1);
+    public static final Constant INT_2 = new PrimitiveConstant(Kind.Int, 2);
     public static final Constant LONG_0 = new PrimitiveConstant(Kind.Long, 0L);
     public static final Constant LONG_1 = new PrimitiveConstant(Kind.Long, 1L);
     public static final Constant FLOAT_0 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(0.0F));
     public static final Constant FLOAT_1 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(1.0F));
-    public static final Constant FLOAT_2 = new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(2.0F));
     public static final Constant DOUBLE_0 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(0.0D));
     public static final Constant DOUBLE_1 = new PrimitiveConstant(Kind.Double, Double.doubleToRawLongBits(1.0D));
     public static final Constant TRUE = new PrimitiveConstant(Kind.Boolean, 1L);
     public static final Constant FALSE = new PrimitiveConstant(Kind.Boolean, 0L);
 
-    static {
-        assert FLOAT_0 != forFloat(-0.0F) : "Constant for 0.0f must be different from -0.0f";
-        assert DOUBLE_0 != forDouble(-0.0d) : "Constant for 0.0d must be different from -0.0d";
-        assert NULL_OBJECT.isNull();
-    }
-
-    protected Constant(PlatformKind kind) {
+    protected Constant(LIRKind kind) {
         super(kind);
     }
 
@@ -183,9 +170,6 @@
         if (Float.compare(f, 1.0F) == 0) {
             return FLOAT_1;
         }
-        if (Float.compare(f, 2.0F) == 0) {
-            return FLOAT_2;
-        }
         return new PrimitiveConstant(Kind.Float, Float.floatToRawIntBits(f));
     }
 
@@ -196,7 +180,13 @@
      * @return a boxed copy of {@code value}
      */
     public static Constant forLong(long i) {
-        return i == 0 ? LONG_0 : i == 1 ? LONG_1 : new PrimitiveConstant(Kind.Long, i);
+        if (i == 0) {
+            return LONG_0;
+        } else if (i == 1) {
+            return LONG_1;
+        } else {
+            return new PrimitiveConstant(Kind.Long, i);
+        }
     }
 
     /**
@@ -206,13 +196,18 @@
      * @return a boxed copy of {@code value}
      */
     public static Constant forInt(int i) {
-        if (i == -1) {
-            return INT_MINUS_1;
+        switch (i) {
+            case -1:
+                return INT_MINUS_1;
+            case 0:
+                return INT_0;
+            case 1:
+                return INT_1;
+            case 2:
+                return INT_2;
+            default:
+                return new PrimitiveConstant(Kind.Int, i);
         }
-        if (i >= 0 && i < INT_CONSTANT_CACHE.length) {
-            return INT_CONSTANT_CACHE[i];
-        }
-        return new PrimitiveConstant(Kind.Int, i);
     }
 
     /**
@@ -346,6 +341,8 @@
      */
     public static Constant zero(Kind kind) {
         switch (kind) {
+            case Boolean:
+                return FALSE;
             case Byte:
                 return forByte((byte) 0);
             case Char:
@@ -370,6 +367,8 @@
      */
     public static Constant one(Kind kind) {
         switch (kind) {
+            case Boolean:
+                return TRUE;
             case Byte:
                 return forByte((byte) 1);
             case Char:
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LIRKind.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LIRKind.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2014, 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.api.meta;
+
+/**
+ * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the
+ * low level representation of the value, and a {@link #referenceMask} that describes the location
+ * of object references in the value.
+ */
+public final class LIRKind {
+
+    /**
+     * The non-type. This uses {@link #derivedReference}, so it can never be part of an oop map.
+     */
+    public static final LIRKind Illegal = derivedReference(Kind.Illegal);
+
+    private final PlatformKind platformKind;
+    private final int referenceMask;
+
+    private static final int DERIVED_REFERENCE = -1;
+
+    private LIRKind(PlatformKind platformKind, int referenceMask) {
+        this.platformKind = platformKind;
+        this.referenceMask = referenceMask;
+    }
+
+    /**
+     * Create a {@link LIRKind} of type {@code platformKind} that contains a primitive value.
+     */
+    public static LIRKind value(PlatformKind platformKind) {
+        assert platformKind != Kind.Object : "Object should always be used as reference type";
+        return new LIRKind(platformKind, 0);
+    }
+
+    /**
+     * Create a {@link LIRKind} of type {@code platformKind} that contains a single tracked oop
+     * reference.
+     */
+    public static LIRKind reference(PlatformKind platformKind) {
+        int length = platformKind.getVectorLength();
+        assert 0 < length && length < 32 : "vector of " + length + " references not supported";
+        return new LIRKind(platformKind, (1 << length) - 1);
+    }
+
+    /**
+     * Create a {@link LIRKind} of type {@code platformKind} that contains a value that is derived
+     * from a reference. Values of this {@link LIRKind} can not be live at safepoints.
+     */
+    public static LIRKind derivedReference(PlatformKind platformKind) {
+        return new LIRKind(platformKind, DERIVED_REFERENCE);
+    }
+
+    /**
+     * Create a new {@link LIRKind} with the same reference information and a new
+     * {@linkplain #getPlatformKind platform kind}. If the new kind is a longer vector than this,
+     * the new elements are marked as untracked values.
+     */
+    public LIRKind changeType(PlatformKind newPlatformKind) {
+        if (isDerivedReference()) {
+            return derivedReference(newPlatformKind);
+        } else if (referenceMask == 0) {
+            // value type
+            return new LIRKind(newPlatformKind, 0);
+        } else {
+            // reference type
+            int newLength = Math.min(32, newPlatformKind.getVectorLength());
+            int newReferenceMask = referenceMask & (0xFFFFFFFF >>> (32 - newLength));
+            assert newReferenceMask != DERIVED_REFERENCE;
+            return new LIRKind(newPlatformKind, newReferenceMask);
+        }
+    }
+
+    /**
+     * Create a new {@link LIRKind} with a new {@linkplain #getPlatformKind platform kind}. If the
+     * new kind is longer than this, the reference positions are repeated to fill the vector.
+     */
+    public LIRKind repeat(PlatformKind newPlatformKind) {
+        if (isDerivedReference()) {
+            return derivedReference(newPlatformKind);
+        } else if (referenceMask == 0) {
+            // value type
+            return new LIRKind(newPlatformKind, 0);
+        } else {
+            // reference type
+            int oldLength = platformKind.getVectorLength();
+            int newLength = newPlatformKind.getVectorLength();
+            assert oldLength <= newLength && newLength < 32 && (newLength % oldLength) == 0;
+
+            // repeat reference mask to fill new kind
+            int newReferenceMask = 0;
+            for (int i = 0; i < newLength; i += platformKind.getVectorLength()) {
+                newReferenceMask |= referenceMask << i;
+            }
+
+            assert newReferenceMask != DERIVED_REFERENCE;
+            return new LIRKind(newPlatformKind, newReferenceMask);
+        }
+    }
+
+    /**
+     * Create a new {@link LIRKind} with the same type, but marked as containing a derivedReference.
+     */
+    public LIRKind makeDerivedReference() {
+        return new LIRKind(platformKind, DERIVED_REFERENCE);
+    }
+
+    /**
+     * Get the low level type that is used in code generation.
+     */
+    public PlatformKind getPlatformKind() {
+        return platformKind;
+    }
+
+    /**
+     * Check whether this value is derived from a reference. If this returns {@code true}, this
+     * value must not be live at safepoints.
+     */
+    public boolean isDerivedReference() {
+        return referenceMask == DERIVED_REFERENCE;
+    }
+
+    /**
+     * Check whether the {@code idx}th part of this value is a reference that must be tracked at
+     * safepoints.
+     *
+     * @param idx The index into the vector if this is a vector kind. Must be 0 if this is a scalar
+     *            kind.
+     */
+    public boolean isReference(int idx) {
+        assert 0 <= idx && idx < platformKind.getVectorLength() : "invalid index " + idx + " in " + this;
+        return !isDerivedReference() && (referenceMask & 1 << idx) != 0;
+    }
+
+    /**
+     * Check whether this kind is a value type that doesn't need to be tracked at safepoints.
+     */
+    public boolean isValue() {
+        return referenceMask == 0;
+    }
+
+    @Override
+    public String toString() {
+        if (isValue()) {
+            return platformKind.name();
+        } else if (isDerivedReference()) {
+            return platformKind.name() + "[*]";
+        } else {
+            StringBuilder ret = new StringBuilder();
+            ret.append(platformKind.name());
+            ret.append('[');
+            for (int i = 0; i < platformKind.getVectorLength(); i++) {
+                if (isReference(i)) {
+                    ret.append('.');
+                } else {
+                    ret.append(' ');
+                }
+            }
+            ret.append(']');
+            return ret.toString();
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((platformKind == null) ? 0 : platformKind.hashCode());
+        result = prime * result + referenceMask;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof LIRKind)) {
+            return false;
+        }
+
+        LIRKind other = (LIRKind) obj;
+        return platformKind == other.platformKind && referenceMask == other.referenceMask;
+    }
+}
\ No newline at end of file
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NullConstant.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NullConstant.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NullConstant.java	Mon Jun 30 12:02:19 2014 +0200
@@ -30,7 +30,7 @@
     private static final long serialVersionUID = 8906209595800783961L;
 
     protected NullConstant() {
-        super(Kind.Object);
+        super(LIRKind.reference(Kind.Object));
     }
 
     @Override
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PlatformKind.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PlatformKind.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PlatformKind.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -30,4 +30,8 @@
     String name();
 
     Constant getDefaultValue();
+
+    default int getVectorLength() {
+        return 1;
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -38,7 +38,7 @@
     private final long primitive;
 
     protected PrimitiveConstant(Kind kind, long primitive) {
-        super(kind);
+        super(LIRKind.value(kind));
         this.primitive = primitive;
 
         assert kind.isPrimitive() || kind == Kind.Illegal;
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -32,7 +32,7 @@
 
     private static final long serialVersionUID = -6909397188697766469L;
 
-    @SuppressWarnings("serial") public static final AllocatableValue ILLEGAL = new AllocatableValue(Kind.Illegal) {
+    @SuppressWarnings("serial") public static final AllocatableValue ILLEGAL = new AllocatableValue(LIRKind.Illegal) {
 
         @Override
         public String toString() {
@@ -41,17 +41,17 @@
     };
 
     private final Kind kind;
-    private final PlatformKind platformKind;
+    private final LIRKind lirKind;
 
     /**
      * Initializes a new value of the specified kind.
      *
-     * @param platformKind the kind
+     * @param lirKind the kind
      */
-    protected Value(PlatformKind platformKind) {
-        this.platformKind = platformKind;
-        if (platformKind instanceof Kind) {
-            this.kind = (Kind) platformKind;
+    protected Value(LIRKind lirKind) {
+        this.lirKind = lirKind;
+        if (getPlatformKind() instanceof Kind) {
+            this.kind = (Kind) getPlatformKind();
         } else {
             this.kind = Kind.Illegal;
         }
@@ -72,23 +72,27 @@
         return kind;
     }
 
+    public final LIRKind getLIRKind() {
+        return lirKind;
+    }
+
     /**
      * Returns the platform specific kind used to store this value.
      */
     public final PlatformKind getPlatformKind() {
-        return platformKind;
+        return lirKind.getPlatformKind();
     }
 
     @Override
     public int hashCode() {
-        return 41 + platformKind.hashCode();
+        return 41 + lirKind.hashCode();
     }
 
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof Value) {
             Value that = (Value) obj;
-            return kind.equals(that.kind) && platformKind.equals(that.platformKind);
+            return kind.equals(that.kind) && lirKind.equals(that.lirKind);
         }
         return false;
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Mon Jun 30 12:02:19 2014 +0200
@@ -185,7 +185,7 @@
     }
 
     private void emitArithImm8(int op, Register dst, int imm8) {
-        int encode = prefixAndEncode(op, dst.encoding, true);
+        int encode = prefixAndEncode(op, false, dst.encoding, true);
         emitByte(0x80);
         emitByte(0xC0 | encode);
         emitByte(imm8);
@@ -560,7 +560,7 @@
     }
 
     public final void cmpb(Register dst, Register src) {
-        int encode = prefixAndEncode(dst.encoding, src.encoding, true);
+        int encode = prefixAndEncode(dst.encoding, true, src.encoding, true);
         emitByte(0x3A);
         emitByte(0xC0 | encode);
     }
@@ -1137,7 +1137,7 @@
     }
 
     public final void movsbl(Register dst, Register src) {
-        int encode = prefixAndEncode(dst.encoding, src.encoding, true);
+        int encode = prefixAndEncode(dst.encoding, false, src.encoding, true);
         emitByte(0x0F);
         emitByte(0xBE);
         emitByte(0xC0 | encode);
@@ -2042,17 +2042,17 @@
     }
 
     private int prefixAndEncode(int dstEnc, int srcEnc) {
-        return prefixAndEncode(dstEnc, srcEnc, false);
+        return prefixAndEncode(dstEnc, false, srcEnc, false);
     }
 
-    private int prefixAndEncode(int dstEncoding, int srcEncoding, boolean byteinst) {
+    private int prefixAndEncode(int dstEncoding, boolean dstIsByte, int srcEncoding, boolean srcIsByte) {
         int srcEnc = srcEncoding;
         int dstEnc = dstEncoding;
         if (dstEnc < 8) {
             if (srcEnc >= 8) {
                 emitByte(Prefix.REXB);
                 srcEnc -= 8;
-            } else if (byteinst && srcEnc >= 4) {
+            } else if ((srcIsByte && srcEnc >= 4) || (dstIsByte && dstEnc >= 4)) {
                 emitByte(Prefix.REX);
             }
         } else {
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Jun 30 12:02:19 2014 +0200
@@ -35,7 +35,6 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
@@ -482,7 +481,7 @@
             Value classRef = lirBuilder.getClassConstant(field.getDeclaringClass());
             long displacement = lirBuilder.getFieldOffset(field);
             Value address = gen.emitAddress(classRef, displacement, Value.ILLEGAL, 0);
-            PlatformKind readKind = gen.getPlatformKind(StampFactory.forKind(field.getKind()));
+            LIRKind readKind = backend.getTarget().getLIRKind(field.getKind());
             LIRFrameState state = createFrameState(frameState);
             return gen.emitLoad(readKind, address, state);
         }
@@ -506,7 +505,7 @@
         emitNullCheck(array);
         long displacement = lirBuilder.getArrayLengthOffset();
         Value address = gen.emitAddress(array, displacement, Value.ILLEGAL, 0);
-        PlatformKind readKind = gen.getPlatformKind(StampFactory.forKind(Kind.Int));
+        LIRKind readKind = backend.getTarget().getLIRKind(Kind.Int);
         LIRFrameState state = createFrameState(frameState);
         return gen.emitLoad(readKind, address, state);
     }
@@ -682,7 +681,7 @@
         for (int i = 0; i < frameState.stackSize(); i++) {
             Value src = frameState.stackAt(i);
             if (src instanceof Constant) {
-                AllocatableValue dst = gen.newVariable(src.getPlatformKind());
+                AllocatableValue dst = gen.newVariable(src.getLIRKind());
                 gen.emitMove(dst, src);
                 frameState.storeStack(i, dst);
                 Debug.log("introduce new variabe %s for stackslot %d (end of block %s", dst, i, currentBlock);
@@ -691,7 +690,7 @@
         for (int i = 0; i < frameState.localsSize(); i++) {
             Value src = frameState.localAt(i);
             if (src instanceof Constant) {
-                AllocatableValue dst = gen.newVariable(src.getPlatformKind());
+                AllocatableValue dst = gen.newVariable(src.getLIRKind());
                 gen.emitMove(dst, src);
                 frameState.storeLocal(i, dst);
                 Debug.log("introduce new variabe %s for local %d (end of block %s", dst, i, currentBlock);
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -77,11 +77,11 @@
  */
 public abstract class AMD64LIRGenerator extends LIRGenerator {
 
-    private static final RegisterValue RAX_I = AMD64.rax.asValue(Kind.Int);
-    private static final RegisterValue RAX_L = AMD64.rax.asValue(Kind.Long);
-    private static final RegisterValue RDX_I = AMD64.rdx.asValue(Kind.Int);
-    private static final RegisterValue RDX_L = AMD64.rdx.asValue(Kind.Long);
-    private static final RegisterValue RCX_I = AMD64.rcx.asValue(Kind.Int);
+    private static final RegisterValue RAX_I = AMD64.rax.asValue(LIRKind.value(Kind.Int));
+    private static final RegisterValue RAX_L = AMD64.rax.asValue(LIRKind.value(Kind.Long));
+    private static final RegisterValue RDX_I = AMD64.rdx.asValue(LIRKind.value(Kind.Int));
+    private static final RegisterValue RDX_L = AMD64.rdx.asValue(LIRKind.value(Kind.Long));
+    private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(Kind.Int));
 
     private class AMD64SpillMoveFactory implements LIR.SpillMoveFactory {
 
@@ -125,7 +125,7 @@
 
     @Override
     public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         emitMove(result, input);
         return result;
     }
@@ -208,7 +208,8 @@
             }
         }
 
-        return new AMD64AddressValue(target().wordKind, baseRegister, indexRegister, scaleEnum, displacementInt);
+        LIRKind resultKind = getAddressKind(base, displacement, index);
+        return new AMD64AddressValue(resultKind, baseRegister, indexRegister, scaleEnum, displacementInt);
     }
 
     public AMD64AddressValue asAddressValue(Value address) {
@@ -221,7 +222,7 @@
 
     @Override
     public Variable emitAddress(StackSlot address) {
-        Variable result = newVariable(target().wordKind);
+        Variable result = newVariable(LIRKind.value(target().wordKind));
         append(new StackLeaOp(result, address));
         return result;
     }
@@ -270,7 +271,7 @@
         boolean mirrored = emitCompare(cmpKind, left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
 
-        Variable result = newVariable(trueValue.getKind());
+        Variable result = newVariable(trueValue.getLIRKind());
         if (cmpKind == Kind.Float || cmpKind == Kind.Double) {
             append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
         } else {
@@ -282,7 +283,7 @@
     @Override
     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
         emitIntegerTest(left, right);
-        Variable result = newVariable(trueValue.getKind());
+        Variable result = newVariable(trueValue.getLIRKind());
         append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue)));
         return result;
     }
@@ -432,7 +433,7 @@
     @Override
     public Variable emitNegate(Value inputVal) {
         AllocatableValue input = asAllocatable(inputVal);
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind()) {
             case Int:
                 append(new Unary1Op(INEG, result, input));
@@ -455,7 +456,7 @@
     @Override
     public Variable emitNot(Value inputVal) {
         AllocatableValue input = asAllocatable(inputVal);
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind()) {
             case Int:
                 append(new Unary1Op(INOT, result, input));
@@ -492,7 +493,7 @@
             case IXOR:
             case LXOR:
                 if (NumUtil.isInt(b.asLong())) {
-                    Variable result = newVariable(a.getKind());
+                    Variable result = newVariable(a.getLIRKind());
                     append(new BinaryRegConst(op, result, a, b));
                     return result;
                 }
@@ -501,7 +502,7 @@
             case IMUL:
             case LMUL:
                 if (NumUtil.isInt(b.asLong())) {
-                    Variable result = newVariable(a.getKind());
+                    Variable result = newVariable(a.getLIRKind());
                     append(new BinaryRegStackConst(op, result, a, b));
                     return result;
                 }
@@ -512,7 +513,7 @@
     }
 
     private Variable emitBinaryVar(AMD64Arithmetic op, boolean commutative, AllocatableValue a, AllocatableValue b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         if (commutative) {
             append(new BinaryCommutative(op, result, a, b));
         } else {
@@ -601,13 +602,13 @@
     }
 
     public Value emitBinaryMemory(AMD64Arithmetic op, Kind kind, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         append(new BinaryMemory(op, kind, result, a, location, state));
         return result;
     }
 
     protected Value emitConvert2MemoryOp(PlatformKind kind, AMD64Arithmetic op, AMD64AddressValue address, LIRFrameState state) {
-        Variable result = newVariable(kind);
+        Variable result = newVariable(LIRKind.value(kind));
         append(new Unary2MemoryOp(op, result, (Kind) null, address, state));
         return result;
     }
@@ -615,13 +616,13 @@
     protected Value emitZeroExtendMemory(Kind memoryKind, int resultBits, AMD64AddressValue address, LIRFrameState state) {
         // Issue a zero extending load of the proper bit size and set the result to
         // the proper kind.
-        Variable result = newVariable(resultBits == 32 ? Kind.Int : Kind.Long);
+        Variable result = newVariable(LIRKind.value(resultBits == 32 ? Kind.Int : Kind.Long));
         append(new ZeroExtendLoadOp(memoryKind, result, address, state));
         return result;
     }
 
     private void emitDivRem(AMD64Arithmetic op, Value a, Value b, LIRFrameState state) {
-        AllocatableValue rax = AMD64.rax.asValue(a.getPlatformKind());
+        AllocatableValue rax = AMD64.rax.asValue(a.getLIRKind());
         emitMove(rax, a);
         append(new DivRemOp(op, rax, asAllocatable(b), state));
     }
@@ -649,12 +650,12 @@
                 emitDivRem(LDIV, a, b, state);
                 return emitMove(RAX_L);
             case Float: {
-                Variable result = newVariable(a.getPlatformKind());
+                Variable result = newVariable(a.getLIRKind());
                 append(new BinaryRegStack(FDIV, result, asAllocatable(a), asAllocatable(b)));
                 return result;
             }
             case Double: {
-                Variable result = newVariable(a.getPlatformKind());
+                Variable result = newVariable(a.getLIRKind());
                 append(new BinaryRegStack(DDIV, result, asAllocatable(a), asAllocatable(b)));
                 return result;
             }
@@ -673,12 +674,12 @@
                 emitDivRem(LREM, a, b, state);
                 return emitMove(RDX_L);
             case Float: {
-                Variable result = newVariable(a.getPlatformKind());
+                Variable result = newVariable(a.getLIRKind());
                 append(new FPDivRemOp(FREM, result, load(a), load(b)));
                 return result;
             }
             case Double: {
-                Variable result = newVariable(a.getPlatformKind());
+                Variable result = newVariable(a.getLIRKind());
                 append(new FPDivRemOp(DREM, result, load(a), load(b)));
                 return result;
             }
@@ -752,7 +753,7 @@
     }
 
     private Variable emitShift(AMD64Arithmetic op, Value a, Value b) {
-        Variable result = newVariable(a.getPlatformKind());
+        Variable result = newVariable(a.getLIRKind());
         AllocatableValue input = asAllocatable(a);
         if (isConstant(b)) {
             append(new BinaryRegConst(op, result, input, asConstant(b)));
@@ -821,22 +822,22 @@
         }
     }
 
-    private AllocatableValue emitConvert2RegOp(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) {
+    private AllocatableValue emitConvert2RegOp(LIRKind kind, AMD64Arithmetic op, AllocatableValue input) {
         Variable result = newVariable(kind);
         append(new Unary2RegOp(op, result, input));
         return result;
     }
 
-    private AllocatableValue emitConvert2Op(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) {
+    private AllocatableValue emitConvert2Op(LIRKind kind, AMD64Arithmetic op, AllocatableValue input) {
         Variable result = newVariable(kind);
         append(new Unary2Op(op, result, input));
         return result;
     }
 
     @Override
-    public Value emitReinterpret(PlatformKind to, Value inputVal) {
-        Kind from = inputVal.getKind();
-        if (to == from) {
+    public Value emitReinterpret(LIRKind to, Value inputVal) {
+        LIRKind from = inputVal.getLIRKind();
+        if (to.equals(from)) {
             return inputVal;
         }
 
@@ -845,27 +846,28 @@
          * Conversions between integer to floating point types require moves between CPU and FPU
          * registers.
          */
-        switch ((Kind) to) {
+        Kind fromKind = (Kind) from.getPlatformKind();
+        switch ((Kind) to.getPlatformKind()) {
             case Int:
-                switch (from) {
+                switch (fromKind) {
                     case Float:
                         return emitConvert2Op(to, MOV_F2I, input);
                 }
                 break;
             case Long:
-                switch (from) {
+                switch (fromKind) {
                     case Double:
                         return emitConvert2Op(to, MOV_D2L, input);
                 }
                 break;
             case Float:
-                switch (from) {
+                switch (fromKind) {
                     case Int:
                         return emitConvert2Op(to, MOV_I2F, input);
                 }
                 break;
             case Double:
-                switch (from) {
+                switch (fromKind) {
                     case Long:
                         return emitConvert2Op(to, MOV_L2D, input);
                 }
@@ -878,25 +880,25 @@
         AllocatableValue input = asAllocatable(inputVal);
         switch (op) {
             case D2F:
-                return emitConvert2Op(Kind.Float, D2F, input);
+                return emitConvert2Op(LIRKind.value(Kind.Float), D2F, input);
             case D2I:
-                return emitConvert2Op(Kind.Int, D2I, input);
+                return emitConvert2Op(LIRKind.value(Kind.Int), D2I, input);
             case D2L:
-                return emitConvert2Op(Kind.Long, D2L, input);
+                return emitConvert2Op(LIRKind.value(Kind.Long), D2L, input);
             case F2D:
-                return emitConvert2Op(Kind.Double, F2D, input);
+                return emitConvert2Op(LIRKind.value(Kind.Double), F2D, input);
             case F2I:
-                return emitConvert2Op(Kind.Int, F2I, input);
+                return emitConvert2Op(LIRKind.value(Kind.Int), F2I, input);
             case F2L:
-                return emitConvert2Op(Kind.Long, F2L, input);
+                return emitConvert2Op(LIRKind.value(Kind.Long), F2L, input);
             case I2D:
-                return emitConvert2Op(Kind.Double, I2D, input);
+                return emitConvert2Op(LIRKind.value(Kind.Double), I2D, input);
             case I2F:
-                return emitConvert2Op(Kind.Float, I2F, input);
+                return emitConvert2Op(LIRKind.value(Kind.Float), I2F, input);
             case L2D:
-                return emitConvert2Op(Kind.Double, L2D, input);
+                return emitConvert2Op(LIRKind.value(Kind.Double), L2D, input);
             case L2F:
-                return emitConvert2Op(Kind.Float, L2F, input);
+                return emitConvert2Op(LIRKind.value(Kind.Float), L2F, input);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -906,7 +908,7 @@
     public Value emitNarrow(Value inputVal, int bits) {
         if (inputVal.getKind() == Kind.Long && bits <= 32) {
             // TODO make it possible to reinterpret Long as Int in LIR without move
-            return emitConvert2RegOp(Kind.Int, L2I, asAllocatable(inputVal));
+            return emitConvert2RegOp(LIRKind.value(Kind.Int), L2I, asAllocatable(inputVal));
         } else {
             return inputVal;
         }
@@ -921,11 +923,11 @@
             // sign extend to 64 bits
             switch (fromBits) {
                 case 8:
-                    return emitConvert2Op(Kind.Long, B2L, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Long), B2L, asAllocatable(inputVal));
                 case 16:
-                    return emitConvert2Op(Kind.Long, S2L, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Long), S2L, asAllocatable(inputVal));
                 case 32:
-                    return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Long), I2L, asAllocatable(inputVal));
                 default:
                     throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
             }
@@ -933,9 +935,9 @@
             // sign extend to 32 bits (smaller values are internally represented as 32 bit values)
             switch (fromBits) {
                 case 8:
-                    return emitConvert2Op(Kind.Int, B2I, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Int), B2I, asAllocatable(inputVal));
                 case 16:
-                    return emitConvert2Op(Kind.Int, S2I, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Int), S2I, asAllocatable(inputVal));
                 case 32:
                     return inputVal;
                 default:
@@ -951,17 +953,17 @@
             return inputVal;
         } else if (fromBits > 32) {
             assert inputVal.getKind() == Kind.Long;
-            Variable result = newVariable(Kind.Long);
+            Variable result = newVariable(LIRKind.value(Kind.Long));
             long mask = IntegerStamp.defaultMask(fromBits);
             append(new BinaryRegConst(AMD64Arithmetic.LAND, result, asAllocatable(inputVal), Constant.forLong(mask)));
             return result;
         } else {
             assert inputVal.getKind().getStackKind() == Kind.Int;
-            Variable result = newVariable(Kind.Int);
+            Variable result = newVariable(LIRKind.value(Kind.Int));
             int mask = (int) IntegerStamp.defaultMask(fromBits);
             append(new BinaryRegConst(AMD64Arithmetic.IAND, result, asAllocatable(inputVal), Constant.forInt(mask)));
             if (toBits > 32) {
-                Variable longResult = newVariable(Kind.Long);
+                Variable longResult = newVariable(LIRKind.value(Kind.Long));
                 emitMove(longResult, result);
                 return longResult;
             } else {
@@ -991,85 +993,95 @@
     }
 
     @Override
-    public void emitBitCount(Variable result, Value value) {
+    public Value emitBitCount(Value value) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         if (value.getKind().getStackKind() == Kind.Int) {
             append(new AMD64BitManipulationOp(IPOPCNT, result, asAllocatable(value)));
         } else {
             append(new AMD64BitManipulationOp(LPOPCNT, result, asAllocatable(value)));
         }
+        return result;
     }
 
     @Override
-    public void emitBitScanForward(Variable result, Value value) {
+    public Value emitBitScanForward(Value value) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         append(new AMD64BitManipulationOp(BSF, result, asAllocatable(value)));
+        return result;
     }
 
     @Override
-    public void emitBitScanReverse(Variable result, Value value) {
+    public Value emitBitScanReverse(Value value) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         if (value.getKind().getStackKind() == Kind.Int) {
             append(new AMD64BitManipulationOp(IBSR, result, asAllocatable(value)));
         } else {
             append(new AMD64BitManipulationOp(LBSR, result, asAllocatable(value)));
         }
+        return result;
     }
 
     @Override
     public Value emitMathAbs(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new BinaryRegConst(DAND, result, asAllocatable(input), Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL))));
         return result;
     }
 
     @Override
     public Value emitMathSqrt(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new Unary2Op(SQRT, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathLog(Value input, boolean base10) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new AMD64MathIntrinsicOp(base10 ? LOG10 : LOG, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathCos(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new AMD64MathIntrinsicOp(COS, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathSin(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new AMD64MathIntrinsicOp(SIN, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathTan(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new AMD64MathIntrinsicOp(TAN, result, asAllocatable(input)));
         return result;
     }
 
     @Override
-    public void emitByteSwap(Variable result, Value input) {
+    public Value emitByteSwap(Value input) {
+        Variable result = newVariable(input.getLIRKind());
         append(new AMD64ByteSwapOp(result, input));
+        return result;
     }
 
     @Override
-    public void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length) {
+    public Value emitArrayEquals(Kind kind, Value array1, Value array2, Value length) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length)));
+        return result;
     }
 
     @Override
     public void emitReturn(Value input) {
         AllocatableValue operand = Value.ILLEGAL;
         if (input != null) {
-            operand = resultOperandFor(input.getKind());
+            operand = resultOperandFor(input.getLIRKind());
             emitMove(operand, input);
         }
         append(new ReturnOp(operand));
@@ -1079,12 +1091,12 @@
     public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         // a temp is needed for loading object constants
         boolean needsTemp = key.getKind() == Kind.Object;
-        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL));
+        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getLIRKind()) : Value.ILLEGAL));
     }
 
     @Override
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
-        append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(target().wordKind), newVariable(key.getPlatformKind())));
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().wordKind)), newVariable(key.getLIRKind())));
     }
 
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -64,8 +64,8 @@
                 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node;
                 if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
                     FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
-                    if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && !hasOperand(otherDivRem)) {
-                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), state((DeoptimizingNode) valueNode));
+                    if (otherDivRem.getX() == divRem.getX() && otherDivRem.getY() == divRem.getY() && !hasOperand(otherDivRem)) {
+                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.getX()), operand(divRem.getY()), state((DeoptimizingNode) valueNode));
                         if (divRem instanceof IntegerDivNode) {
                             setResult(divRem, results[0]);
                             setResult(otherDivRem, results[1]);
@@ -90,7 +90,7 @@
     }
 
     protected Kind getMemoryKind(Access access) {
-        return (Kind) gen.getPlatformKind(access.asNode().stamp());
+        return (Kind) gen.getLIRKind(access.asNode().stamp()).getPlatformKind();
     }
 
     protected AMD64AddressValue makeAddress(Access access) {
@@ -133,33 +133,27 @@
             }
         }
 
-        PlatformKind cmpKind = gen.getPlatformKind(compare.x().stamp());
-        if (cmpKind instanceof Kind) {
-            // emitCompareBranchMemory expects the memory on the right, so mirror the condition if
-            // that's not true. It might be mirrored again the actual compare is emitted but that's
-            // ok.
-            Condition finalCondition = uncast(compare.x()) == access ? cond.mirror() : cond;
-            return new ComplexMatchResult() {
-                public Value evaluate(NodeLIRBuilder builder) {
-                    LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor());
-                    LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor());
-                    boolean unorderedIsTrue = compare.unorderedIsTrue();
-                    double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor());
-                    Value other;
-                    if (value.isConstant()) {
-                        other = value.asConstant();
-                    } else {
-                        other = operand(value);
-                    }
+        // emitCompareBranchMemory expects the memory on the right, so mirror the condition if
+        // that's not true. It might be mirrored again the actual compare is emitted but that's
+        // ok.
+        Condition finalCondition = uncast(compare.getX()) == access ? cond.mirror() : cond;
+        return new ComplexMatchResult() {
+            public Value evaluate(NodeLIRBuilder builder) {
+                LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor());
+                LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor());
+                boolean unorderedIsTrue = compare.unorderedIsTrue();
+                double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor());
+                Value other;
+                if (value.isConstant()) {
+                    other = value.asConstant();
+                } else {
+                    other = operand(value);
+                }
 
-                    getLIRGeneratorTool().emitCompareBranchMemory((Kind) cmpKind, other, makeAddress(access), getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel,
-                                    trueLabelProbability);
-                    return null;
-                }
-            };
-        }
-        return null;
-
+                getLIRGeneratorTool().emitCompareBranchMemory(kind, other, makeAddress(access), getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability);
+                return null;
+            }
+        };
     }
 
     private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) {
@@ -273,7 +267,7 @@
         return null;
     }
 
-    private Value emitReinterpretMemory(PlatformKind to, Access access) {
+    private Value emitReinterpretMemory(LIRKind to, Access access) {
         AMD64AddressValue address = makeAddress(access);
         LIRFrameState state = getState(access);
         return getLIRGeneratorTool().emitLoad(to, address, state);
@@ -370,8 +364,8 @@
 
     @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))")
     public ComplexMatchResult rotateLeftConstant(LeftShiftNode lshift, UnsignedRightShiftNode rshift) {
-        if ((lshift.getShiftAmountMask() & (lshift.y().asConstant().asInt() + rshift.y().asConstant().asInt())) == 0) {
-            return builder -> getLIRGeneratorTool().emitRol(operand(lshift.x()), operand(lshift.y()));
+        if ((lshift.getShiftAmountMask() & (lshift.getY().asConstant().asInt() + rshift.getY().asConstant().asInt())) == 0) {
+            return builder -> getLIRGeneratorTool().emitRol(operand(lshift.getX()), operand(lshift.getY()));
         }
         return null;
     }
@@ -421,9 +415,9 @@
     @MatchRule("(Write Narrow=narrow location value)")
     public ComplexMatchResult writeNarrow(WriteNode root, NarrowNode narrow) {
         return builder -> {
-            PlatformKind writeKind = getLIRGeneratorTool().getPlatformKind(root.value().stamp());
+            LIRKind writeKind = getLIRGeneratorTool().getLIRKind(root.value().stamp());
             Value address = root.location().generateAddress(builder, getLIRGeneratorTool(), operand(root.object()));
-            Value v = operand(narrow.getInput());
+            Value v = operand(narrow.getValue());
             getLIRGeneratorTool().emitStore(writeKind, address, v, state(root));
             return null;
         };
@@ -461,7 +455,7 @@
     @MatchRule("(Reinterpret FloatingRead=access)")
     public ComplexMatchResult reinterpret(ReinterpretNode root, Access access) {
         return builder -> {
-            PlatformKind kind = getLIRGeneratorTool().getPlatformKind(root.stamp());
+            LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp());
             return emitReinterpretMemory(kind, access);
         };
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java	Mon Jun 30 12:02:19 2014 +0200
@@ -64,6 +64,7 @@
      * True if block {@code a} dominates block {@code b}.
      */
     static boolean dominates(AbstractBlock a, AbstractBlock b) {
+        assert a != null;
         return isDominatedBy(b, a);
     }
 
@@ -71,6 +72,7 @@
      * True if block {@code a} is dominated by block {@code b}.
      */
     static boolean isDominatedBy(AbstractBlock a, AbstractBlock b) {
+        assert a != null;
         if (a == b) {
             return true;
         }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/LIRKindTool.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/LIRKindTool.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 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.compiler.common.spi;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * This interface can be used to access platform and VM specific kinds.
+ */
+public interface LIRKindTool {
+
+    LIRKind getIntegerKind(int bits);
+
+    LIRKind getFloatingKind(int bits);
+
+    LIRKind getObjectKind();
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/PlatformKindTool.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/PlatformKindTool.java	Mon Jun 30 08:50:26 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2014, 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.compiler.common.spi;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * This interface can be used to access platform and VM specific kinds.
- */
-public interface PlatformKindTool {
-
-    PlatformKind getIntegerKind(int bits);
-
-    PlatformKind getFloatingKind(int bits);
-
-    PlatformKind getObjectKind();
-}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java	Mon Jun 30 12:02:19 2014 +0200
@@ -74,7 +74,7 @@
     }
 
     @Override
-    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+    public LIRKind getLIRKind(LIRKindTool tool) {
         return tool.getFloatingKind(getBits());
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java	Mon Jun 30 12:02:19 2014 +0200
@@ -40,7 +40,7 @@
     }
 
     @Override
-    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+    public LIRKind getLIRKind(LIRKindTool tool) {
         throw GraalInternalError.shouldNotReachHere("illegal stamp should not reach backend");
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Mon Jun 30 12:02:19 2014 +0200
@@ -84,7 +84,7 @@
     }
 
     @Override
-    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+    public LIRKind getLIRKind(LIRKindTool tool) {
         return tool.getIntegerKind(getBits());
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java	Mon Jun 30 12:02:19 2014 +0200
@@ -42,7 +42,7 @@
     }
 
     @Override
-    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+    public LIRKind getLIRKind(LIRKindTool tool) {
         return tool.getObjectKind();
     }
 
@@ -64,4 +64,13 @@
         }
         return false;
     }
+
+    @Override
+    public Constant asConstant() {
+        if (alwaysNull()) {
+            return Constant.NULL_OBJECT;
+        } else {
+            return null;
+        }
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java	Mon Jun 30 12:02:19 2014 +0200
@@ -51,10 +51,9 @@
     public abstract Kind getStackKind();
 
     /**
-     * Gets a platform dependent {@link PlatformKind} that can be used to store a value of this
-     * stamp.
+     * Gets a platform dependent {@link LIRKind} that can be used to store a value of this stamp.
      */
-    public abstract PlatformKind getPlatformKind(PlatformKindTool tool);
+    public abstract LIRKind getLIRKind(LIRKindTool tool);
 
     /**
      * Returns the union of this stamp and the given stamp. Typically used to create stamps for phi
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java	Mon Jun 30 12:02:19 2014 +0200
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public PlatformKind getPlatformKind(PlatformKindTool tool) {
+    public LIRKind getLIRKind(LIRKindTool tool) {
         throw GraalInternalError.shouldNotReachHere("void stamp has no value");
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java	Mon Jun 30 12:02:19 2014 +0200
@@ -152,13 +152,17 @@
         return true;
     }
 
+    HotSpotNmethod installedCode;
+
     @Override
     protected void dispatchKernelOkra(int range, Object... args) {
         HSAILHotSpotBackend backend = getHSAILBackend();
         if (backend.isDeviceInitialized()) {
             try {
-                HotSpotNmethod code = backend.compileAndInstallKernel(testMethod);
-                backend.executeKernel(code, range, args);
+                if (installedCode == null) {
+                    installedCode = backend.compileAndInstallKernel(testMethod);
+                }
+                backend.executeKernel(installedCode, range, args);
             } catch (InvalidInstalledCodeException e) {
                 Debug.log("WARNING:Invalid installed code: " + e);
                 e.printStackTrace();
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -45,11 +45,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -45,11 +45,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -45,11 +45,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -45,11 +45,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchMost20000StressGCTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchMost20000StressGCTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 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.graal.compiler.hsail.test;
+
+import org.junit.*;
+
+/**
+ * A version which is likely to get a GC while running the never_rans, and so is good for oops_do
+ * testing.
+ */
+public class BoundsCatchMost20000StressGCTest extends BoundsCatchManyBase {
+
+    @Override
+    int getGlobalSize() {
+        return 20000;
+    }
+
+    boolean isMyDeoptGid(int gid) {
+        return (gid > 100 && gid % 100 != 1);
+    }
+
+    int[] dummyArray;
+
+    // copied run routine here because otherwise polymorphic calls to isDeoptGid
+    @Override
+    public void run(int gid) {
+        int outval = getOutval(gid);
+        try {
+            int index = (isMyDeoptGid(gid) ? num + 1 : gid);
+            outArray[index] = outval;
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // set up so we can detect if we go thru here twice
+            outArray[gid] += outval;
+            // note: cannot record the exceptiongid here for many deopts in parallel
+
+            // allocate something so GCs happen more often
+            dummyArray = new int[1000];
+        }
+    }
+
+    @Override
+    public void runTest() {
+        setupArrays();
+
+        for (int i = 0; i < 10; i++) {
+            // we should not get an exception escaping from the kernel
+            dispatchMethodKernel(num);
+        }
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringConcatTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringConcatTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringConcatTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -50,8 +50,7 @@
         myOutArray[gid] = inArray[(gid + NUM / 2) % NUM] + inArray[gid];
     }
 
-    // Node implementing Lowerable not handled in HSAIL Backend: 6274|MonitorEnter
-    @Ignore
+    @Ignore("emitDirectCall unimplemented")
     @Test
     public void test() {
         try (DebugConfigScope s = disableIntercept()) {
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListGetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListGetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListGetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -23,14 +23,11 @@
 
 package com.oracle.graal.compiler.hsail.test.lambda;
 
-import static com.oracle.graal.debug.Debug.*;
-
 import java.util.*;
 
 import org.junit.*;
 
 import com.oracle.graal.compiler.hsail.test.infra.*;
-import com.oracle.graal.debug.*;
 
 /**
  * Tests calling ArrayList.get().
@@ -58,13 +55,10 @@
         });
     }
 
-    // NYI emitForeignCall charAlignedDisjointArraycopy
-    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
-    @Ignore
+    @Ignore("emitDirectCall unimplemented")
+    @Test
     public void testUsingLambdaMethod() {
-        try (DebugConfigScope s = disableIntercept()) {
-            testGeneratedHsailUsingLambdaMethod();
-        }
+        testGeneratedHsailUsingLambdaMethod();
     }
 
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListSetTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListSetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+import java.util.*;
+
+/**
+ * Tests calling ArrayList.set().
+ */
+public class ArrayListSetTest extends GraalKernelTester {
+
+    final static int NUM = 50;
+    ArrayList aryList = new ArrayList<>();
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < NUM; i++) {
+            aryList.add(-1);
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            aryList.set(gid, gid);
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
+    @Test
+    @Ignore
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -47,11 +47,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -46,11 +46,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -44,11 +44,6 @@
     }
 
     @Override
-    protected boolean supportsRequiredCapabilities() {
-        return (canDeoptimize());
-    }
-
-    @Override
     public void runTest() {
         setupArrays();
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ByteArrayCopyConjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ByteArrayCopyConjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a byte array where src and dest overlap.
+ */
+public class ByteArrayCopyConjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result byte[][] outArray = new byte[NUM][MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < NUM; i++) {
+            for (int j = 0; j < outArray[i].length; j++) {
+                outArray[i][j] = (byte) (i + j);
+            }
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(outArray[gid], 0, outArray[gid], gid % NUM, NUM);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ByteArrayCopyDisjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ByteArrayCopyDisjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a byte array where src and dest do not overlap.
+ */
+public class ByteArrayCopyDisjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result byte[][] outArray = new byte[NUM][MAXOUTSIZ];
+    byte[] inArray = new byte[NUM + MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < inArray.length; i++) {
+            inArray[i] = (byte) i;
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(inArray, gid, outArray[gid], 0, MAXOUTSIZ);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/CharArrayCopyConjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/CharArrayCopyConjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a char array where src and dest overlap.
+ */
+public class CharArrayCopyConjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result char[][] outArray = new char[NUM][MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < NUM; i++) {
+            for (int j = 0; j < outArray[i].length; j++) {
+                outArray[i][j] = (char) (i + j);
+            }
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(outArray[gid], 0, outArray[gid], gid % NUM, NUM);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/CharArrayCopyDisjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/CharArrayCopyDisjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a char array where src and dest do not overlap.
+ */
+public class CharArrayCopyDisjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result char[][] outArray = new char[NUM][MAXOUTSIZ];
+    char[] inArray = new char[NUM + MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < inArray.length; i++) {
+            inArray[i] = (char) i;
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(inArray, gid, outArray[gid], 0, MAXOUTSIZ);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntArrayCopyConjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntArrayCopyConjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a int array where src and dest overlap.
+ */
+public class IntArrayCopyConjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result int[][] outArray = new int[NUM][MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < NUM; i++) {
+            for (int j = 0; j < outArray[i].length; j++) {
+                outArray[i][j] = i + j;
+            }
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(outArray[gid], 0, outArray[gid], gid % NUM, NUM);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntArrayCopyDisjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntArrayCopyDisjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a int array where src and dest do not overlap.
+ */
+public class IntArrayCopyDisjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result int[][] outArray = new int[NUM][MAXOUTSIZ];
+    int[] inArray = new int[NUM + MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < inArray.length; i++) {
+            inArray[i] = i;
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(inArray, gid, outArray[gid], 0, MAXOUTSIZ);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongArrayCopyConjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongArrayCopyConjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a long array where src and dest overlap.
+ */
+public class LongArrayCopyConjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result long[][] outArray = new long[NUM][MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < NUM; i++) {
+            for (int j = 0; j < outArray[i].length; j++) {
+                outArray[i][j] = i + j;
+            }
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(outArray[gid], 0, outArray[gid], gid % NUM, NUM);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongArrayCopyDisjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongArrayCopyDisjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests copying a long array where src and dest do not overlap.
+ */
+public class LongArrayCopyDisjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result long[][] outArray = new long[NUM][MAXOUTSIZ];
+    long[] inArray = new long[NUM + MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < inArray.length; i++) {
+            inArray[i] = i;
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(inArray, gid, outArray[gid], 0, MAXOUTSIZ);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringEqualsTest.java
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringEqualsTest.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringEqualsTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -52,6 +52,12 @@
         setupArrays();
         String base = "ABCDEFGHIJ";
 
+        // Resolving StringIndexOutOfBoundsException causes compilation of the
+        // lambda to fail as. Combined with use of InlineEverything and RemoveNeverExecutedCode
+        // the inlining budget is blown before String.equals can be inlined leaving
+        // a DirectCallTargetNode in the graph which cannot be lowered by HSAIL.
+        new StringIndexOutOfBoundsException().fillInStackTrace();
+
         dispatchLambdaKernel(NUM, (gid) -> {
             outArray[gid] = new String(chars, 0, 10 + (gid % 3)).equals(base);
         });
@@ -63,8 +69,7 @@
         return (canHandleObjectAllocation());
     }
 
-    // NYI emitForeignCall charAlignedDisjointArraycopy
-    @Ignore
+    @Ignore("see comment in runTest")
     @Test
     public void test() {
         try (DebugConfigScope s = disableIntercept()) {
@@ -72,7 +77,7 @@
         }
     }
 
-    @Ignore
+    @Ignore("see comment in runTest")
     @Test
     public void testUsingLambdaMethod() {
         try (DebugConfigScope s = disableIntercept()) {
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjArrayCopyConjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjArrayCopyConjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests {@link System#arraycopy} for object arrays where dest and src type are same, and overlap.
+ */
+public class ObjArrayCopyConjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result String[][] outArray = new String[NUM][MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < NUM; i++) {
+            for (int j = 0; j < outArray[i].length; j++) {
+                outArray[i][j] = Integer.toString(i * 100 + j);
+            }
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(outArray[gid], 0, outArray[gid], gid % NUM, NUM);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjArrayCopyDisjointNonExactTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjArrayCopyDisjointNonExactTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests {@link System#arraycopy} for object arrays where dest is a superclass of src.
+ */
+public class ObjArrayCopyDisjointNonExactTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result Object[][] outArray = new Object[NUM][MAXOUTSIZ];
+    String[] inArray = new String[NUM + MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < inArray.length; i++) {
+            inArray[i] = Integer.toString(i * 1111);
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(inArray, gid, outArray[gid], 0, MAXOUTSIZ);
+        });
+    }
+
+    // this fails because we do not have a pure java snippet for this case
+    // see ArrayCopySnippets.arrayCopy(Object, int, Object, int, int)
+    @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class)
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjArrayCopyDisjointTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjArrayCopyDisjointTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests {@link System#arraycopy} for object arrays where dest and src type are same, no overlap.
+ */
+public class ObjArrayCopyDisjointTest extends GraalKernelTester {
+
+    final static int MAXOUTSIZ = 100;
+    final static int NUM = 20;
+
+    @Result String[][] outArray = new String[NUM][MAXOUTSIZ];
+    String[] inArray = new String[NUM + MAXOUTSIZ];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < inArray.length; i++) {
+            inArray[i] = Integer.toString(i * 1111);
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            System.arraycopy(inArray, gid, outArray[gid], 0, MAXOUTSIZ);
+        });
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ReduceMaxTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ReduceMaxTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.runtime;
+import com.oracle.graal.hotspot.HotSpotVMConfig;
+import static org.junit.Assert.*;
+import org.junit.*;
+
+import java.util.*;
+import java.util.stream.IntStream;
+
+public class ReduceMaxTest {
+    // The length of the input array
+    static int jobSize = 1027 * 1023 * 13;
+    static int loops = 1;
+
+    // The source array
+    int bigArray[] = null;
+
+    // result for baseline single threaded stream
+    int resultStream = 0;
+    // result for parallel CPU and offloaded streams
+    int resultOffload = 0;
+
+    int evaluate(boolean doParallelStream) {
+        int result = 0;
+        for (int i = 0; i < loops; i++) {
+            IntStream s = Arrays.stream(bigArray);
+            if (doParallelStream == true) {
+                OptionalInt resultParallel = s.parallel().reduce(Integer::max);
+                result = resultParallel.getAsInt();
+            } else {
+                result = s.reduce(Integer::max).getAsInt();
+            }
+        }
+        return result;
+    }
+
+    int evaluateWithIdentity(boolean doParallelStream) {
+        int result = 0;
+        for (int i = 0; i < loops; i++) {
+            IntStream s = Arrays.stream(bigArray);
+            if (doParallelStream == true) {
+                result = s.parallel().reduce(0, Integer::max);
+            } else {
+                result = s.reduce(0, Integer::max);
+            }
+        }
+        return result;
+    }
+
+    @Test
+    public void testReduce() {
+        // Handmade reduce does not support +UseCompressedOops
+        HotSpotVMConfig config = runtime().getConfig();
+        if (config.useCompressedOops == true || config.useHSAILDeoptimization == true) {
+            return;
+        }
+
+        bigArray = new int[jobSize];
+        for (int i = 0; i < jobSize; i++) {
+            // bigArray[i] = i + 1;
+            bigArray[i] = -1024 + i + 1;
+        }
+
+        // Get non parallel baseline
+        resultStream = evaluate(false);
+
+        // Get OptionalInt version kernel
+        resultOffload = evaluate(true);
+        assertTrue(resultStream == resultOffload);
+
+        // Do identity version kernel
+        // Get non parallel baseline
+        resultStream = evaluateWithIdentity(false);
+
+        resultOffload = evaluateWithIdentity(true);
+        assertTrue(resultStream == resultOffload);
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ReduceMinTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ReduceMinTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.runtime;
+import com.oracle.graal.hotspot.HotSpotVMConfig;
+import static org.junit.Assert.*;
+import org.junit.*;
+
+import java.util.*;
+import java.util.stream.IntStream;
+
+public class ReduceMinTest {
+    // The length of the input array
+    static int jobSize = 1027 * 1023 * 13;
+    static int loops = 1;
+
+    // The input array to the kernel
+    int bigArray[] = null;
+
+    // result for baseline single threaded stream
+    int resultStream = 0;
+    // result for parallel CPU and offloaded streams
+    int resultOffload = 0;
+
+    int evaluate(boolean doParallelStream) {
+        int result = 0;
+        for (int i = 0; i < loops; i++) {
+            IntStream s = Arrays.stream(bigArray);
+            if (doParallelStream == true) {
+                OptionalInt resultParallel = s.parallel().reduce(Integer::min);
+                result = resultParallel.getAsInt();
+            } else {
+                result = s.reduce(Integer::min).getAsInt();
+            }
+        }
+        return result;
+    }
+
+    int evaluateWithIdentity(boolean doParallelStream) {
+        int result = 0;
+        for (int i = 0; i < loops; i++) {
+            IntStream s = Arrays.stream(bigArray);
+            if (doParallelStream == true) {
+                result = s.parallel().reduce(0, Integer::min);
+            } else {
+                result = s.reduce(0, Integer::min);
+            }
+        }
+        return result;
+    }
+
+    @Test
+    public void testReduce() {
+        // Handmade reduce does not support +UseCompressedOops
+        HotSpotVMConfig config = runtime().getConfig();
+        if (config.useCompressedOops == true || config.useHSAILDeoptimization == true) {
+            return;
+        }
+
+        bigArray = new int[jobSize];
+        for (int i = 0; i < jobSize; i++) {
+            bigArray[i] = -1024 + i + 1;
+        }
+
+        // Get non parallel baseline
+        resultStream = evaluate(false);
+
+        // Get OptionalInt version kernel
+        resultOffload = evaluate(true);
+        assertTrue(resultStream == resultOffload);
+
+        // Do identity version kernel
+        // Get non parallel baseline
+        resultStream = evaluateWithIdentity(false);
+
+        resultOffload = evaluateWithIdentity(true);
+        assertTrue(resultStream == resultOffload);
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ReduceSumTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ReduceSumTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+//import com.oracle.graal.compiler.common.GraalInternalError;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.runtime;
+import com.oracle.graal.hotspot.HotSpotVMConfig;
+import org.junit.*;
+
+import java.util.*;
+import java.util.stream.IntStream;
+
+public class ReduceSumTest {
+    // The length of the input array
+    static int jobSize = 1027 * 1023 * 13;
+    static int loops = 1;
+
+    // The array to be summed
+    int bigArray[] = null;
+
+    // sum for baseline single threaded stream
+    int sumStream = 0;
+    // sum for parallel CPU and offloaded streams
+    int sumOffload = 0;
+
+    int evaluate(boolean doParallelStream) {
+        int sum = 0;
+        for (int i = 0; i < loops; i++) {
+            IntStream s = Arrays.stream(bigArray);
+            if (doParallelStream == true) {
+                OptionalInt resultParallel = s.parallel().reduce(Integer::sum);
+                sum = resultParallel.getAsInt();
+            } else {
+                OptionalInt resultStream = s.reduce(Integer::sum);
+                sum = resultStream.getAsInt();
+            }
+        }
+        return sum;
+    }
+
+    int evaluateWithIdentity(boolean doParallelStream) {
+        int sum = 0;
+        for (int i = 0; i < loops; i++) {
+            IntStream s = Arrays.stream(bigArray);
+            if (doParallelStream == true) {
+                sum = s.parallel().reduce(0, Integer::sum);
+            } else {
+                sum = s.reduce(0, Integer::sum);
+            }
+        }
+        return sum;
+    }
+
+    @Test
+    public void testReduce() {
+        // Handmade reduce does not support +UseCompressedOops
+        HotSpotVMConfig config = runtime().getConfig();
+        if (config.useCompressedOops == true || config.useHSAILDeoptimization == true) {
+            return;
+        }
+
+        bigArray = new int[jobSize];
+        for (int i = 0; i < jobSize; i++) {
+            bigArray[i] = -1024 + i + 1;
+        }
+
+        // Get non parallel baseline
+        sumStream = evaluate(false);
+
+        // Get OptionalInt version kernel
+        sumOffload = evaluate(true);
+        assert sumStream == sumOffload : "Offload sum is wrong, stream:" + sumStream + " != offload:" + sumOffload;
+
+        // Get identity version kernel
+        sumOffload = evaluateWithIdentity(true);
+        assert sumStream == sumOffload : "Offload sum is wrong, stream:" + sumStream + " != offload:" + sumOffload;
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringBuilderTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringBuilderTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests creating a new String using StringBuilder (relies on {@link System#arraycopy}).
+ */
+public class StringBuilderTest extends GraalKernelTester {
+
+    final static int NUM = 20;
+    StringBuilder[] builders = new StringBuilder[NUM];
+    @Result String[] resultString = new String[NUM];
+
+    @Override
+    public void runTest() {
+        for (int i = 0; i < NUM; i++) {
+            builders[i] = new StringBuilder().append(i).append("abc");
+        }
+        dispatchLambdaKernel(NUM, (gid) -> {
+            resultString[gid] = builders[gid].append(gid * 1234).toString();
+        });
+    }
+
+    @Override
+    protected boolean supportsRequiredCapabilities() {
+        return (canHandleObjectAllocation());
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringSubsequenceTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringSubsequenceTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests creating a new {@link CharSequence} using {@link String#subSequence(int, int)}.
+ */
+public class StringSubsequenceTest extends GraalKernelTester {
+
+    final static int NUM = 50;
+    String inputString;
+    @Result CharSequence[] resultSequence = new String[NUM];
+
+    @Override
+    public void runTest() {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < NUM + 10; i++) {
+            builder.append(i);
+        }
+        inputString = builder.toString();
+        dispatchLambdaKernel(NUM, (gid) -> {
+            resultSequence[gid] = inputString.subSequence(gid, gid + 10);
+        });
+
+        // for (int i = 0; i < NUM; i++) {
+        // System.out.println(resultSequence[i]);
+        // }
+    }
+
+    @Ignore("emitDirectCall unimplemented")
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringSubstringTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringSubstringTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+import org.junit.*;
+
+/**
+ * Tests creating a new String using {@link String#substring(int, int)}.
+ */
+public class StringSubstringTest extends GraalKernelTester {
+
+    final static int NUM = 50;
+    String inputString;
+    @Result String[] resultString = new String[NUM];
+
+    @Override
+    public void runTest() {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < NUM + 10; i++) {
+            builder.append(i);
+        }
+        inputString = builder.toString();
+        dispatchLambdaKernel(NUM, (gid) -> {
+            resultString[gid] = inputString.substring(gid, gid + 10);
+        });
+    }
+
+    @Ignore("emitDirectCall unimplemented")
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/CompileAndDispatch.java
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/CompileAndDispatch.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/CompileAndDispatch.java	Mon Jun 30 12:02:19 2014 +0200
@@ -32,4 +32,12 @@
     Object createKernel(Class consumerClass);
 
     boolean dispatchKernel(Object kernel, int jobSize, Object[] args);
+
+    Object createKernelFromHsailString(String code, String methodName);
+
+    String getIntegerReduceIntrinsic(String reducerName);
+
+    Integer offloadIntReduceImpl(Object kernel, int identity, int[] streamSource);
+
+    String getIntReduceTargetName(Class opClass);
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jun 30 12:02:19 2014 +0200
@@ -81,7 +81,7 @@
 
     @Override
     public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         emitMove(result, input);
         return result;
     }
@@ -149,7 +149,9 @@
                 }
             }
         }
-        return new HSAILAddressValue(target().wordKind, baseRegister, finalDisp);
+
+        LIRKind resultKind = getAddressKind(base, displacement, index);
+        return new HSAILAddressValue(resultKind, baseRegister, finalDisp);
     }
 
     @Override
@@ -184,7 +186,7 @@
                     double trueDestinationProbability) {
         // We don't have to worry about mirroring the condition on HSAIL.
         Condition finalCondition = cond;
-        Variable result = newVariable(left.getKind());
+        Variable result = newVariable(left.getLIRKind());
         Kind kind = left.getKind().getStackKind();
         switch (kind) {
             case Int:
@@ -209,14 +211,14 @@
     @Override
     public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
         Variable result = emitAnd(left, right);
-        Variable dummyResult = newVariable(left.getKind());
+        Variable dummyResult = newVariable(left.getLIRKind());
         append(new CompareBranchOp(mapKindToCompareOp(left.getKind()), Condition.EQ, result, Constant.forInt(0), dummyResult, dummyResult, trueDestination, falseDestination, false));
     }
 
     @Override
     public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
         Condition finalCondition = cond;
-        Variable result = newVariable(trueValue.getKind());
+        Variable result = newVariable(trueValue.getLIRKind());
         Kind kind = left.getKind().getStackKind();
         switch (kind) {
             case Int:
@@ -247,7 +249,7 @@
      */
     @Override
     public Variable emitNegate(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind()) {
             case Int:
                 // Note: The Int case also handles the negation of shorts, bytes, and chars because
@@ -278,7 +280,7 @@
      */
     @Override
     public Variable emitNot(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind()) {
             case Int:
                 // Note: The Int case also covers other primitive integral types smaller than an int
@@ -296,7 +298,7 @@
     }
 
     public Variable emitTestAddressAdd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IADD, result, a, loadNonConst(b)));
@@ -321,7 +323,7 @@
 
     @Override
     public Variable emitAdd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IADD, result, a, loadNonConst(b)));
@@ -346,7 +348,7 @@
 
     @Override
     public Variable emitSub(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(ISUB, result, a, loadNonConst(b)));
@@ -368,7 +370,7 @@
 
     @Override
     public Variable emitMul(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
@@ -389,7 +391,7 @@
     }
 
     public Variable emitUMul(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(LUMUL, result, a, loadNonConst(b)));
@@ -415,7 +417,7 @@
 
     @Override
     public Value emitDiv(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
@@ -438,7 +440,7 @@
 
     @Override
     public Value emitRem(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IREM, result, a, loadNonConst(b)));
@@ -470,7 +472,7 @@
 
     @Override
     public Variable emitAnd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IAND, result, a, loadNonConst(b)));
@@ -486,7 +488,7 @@
 
     @Override
     public Variable emitOr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IOR, result, a, loadNonConst(b)));
@@ -502,7 +504,7 @@
 
     @Override
     public Variable emitXor(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IXOR, result, a, loadNonConst(b)));
@@ -525,7 +527,7 @@
      */
     @Override
     public Variable emitShl(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 // Note: The Int case also covers the shifting of bytes, shorts and chars because
@@ -550,7 +552,7 @@
      */
     @Override
     public Variable emitShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 // Note: The Int case also covers the shifting of bytes, shorts and chars because
@@ -575,7 +577,7 @@
      */
     @Override
     public Variable emitUShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new ShiftOp(IUSHR, result, a, b));
@@ -623,24 +625,24 @@
             case D2I:
             case F2I:
                 to = "s32";
-                result = newVariable(Kind.Int);
+                result = newVariable(LIRKind.value(Kind.Int));
                 break;
             case D2L:
             case F2L:
                 to = "s64";
-                result = newVariable(Kind.Long);
+                result = newVariable(LIRKind.value(Kind.Long));
                 break;
             case F2D:
             case I2D:
             case L2D:
                 to = "f64";
-                result = newVariable(Kind.Double);
+                result = newVariable(LIRKind.value(Kind.Double));
                 break;
             case D2F:
             case I2F:
             case L2F:
                 to = "f32";
-                result = newVariable(Kind.Float);
+                result = newVariable(LIRKind.value(Kind.Float));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -653,7 +655,7 @@
     @Override
     public Value emitNarrow(Value inputVal, int bits) {
         Variable input = load(inputVal);
-        Variable result = newVariable(bits > 32 ? Kind.Long : Kind.Int);
+        Variable result = newVariable(LIRKind.value(bits > 32 ? Kind.Long : Kind.Int));
         append(new ConvertOp(result, input, "s" + bits, input.getKind() == Kind.Long ? "s64" : "s32"));
         return result;
     }
@@ -661,7 +663,7 @@
     @Override
     public Value emitSignExtend(Value inputVal, int fromBits, int toBits) {
         Variable input = load(inputVal);
-        Variable result = newVariable(toBits > 32 ? Kind.Long : Kind.Int);
+        Variable result = newVariable(LIRKind.value(toBits > 32 ? Kind.Long : Kind.Int));
         append(new ConvertOp(result, input, "s" + toBits, "s" + fromBits));
         return result;
     }
@@ -669,13 +671,13 @@
     @Override
     public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) {
         Variable input = load(inputVal);
-        Variable result = newVariable(toBits > 32 ? Kind.Long : Kind.Int);
+        Variable result = newVariable(LIRKind.value(toBits > 32 ? Kind.Long : Kind.Int));
         append(new ConvertOp(result, input, "u" + toBits, "u" + fromBits));
         return result;
     }
 
     @Override
-    public Value emitReinterpret(PlatformKind to, Value inputVal) {
+    public Value emitReinterpret(LIRKind to, Value inputVal) {
         Variable result = newVariable(to);
         emitMove(result, inputVal);
         return result;
@@ -693,21 +695,23 @@
     }
 
     @Override
-    public void emitBitCount(Variable result, Value value) {
+    public Value emitBitCount(Value value) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         if (value.getKind().getStackKind() == Kind.Int) {
             append(new HSAILBitManipulationOp(IPOPCNT, result, value));
         } else {
             append(new HSAILBitManipulationOp(LPOPCNT, result, value));
         }
+        return result;
     }
 
     @Override
-    public void emitBitScanForward(Variable result, Value value) {
+    public Value emitBitScanForward(Value value) {
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    public void emitBitScanReverse(Variable result, Value value) {
+    public Value emitBitScanReverse(Value value) {
         throw GraalInternalError.unimplemented();
     }
 
@@ -719,7 +723,7 @@
      */
     @Override
     public Value emitMathAbs(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new Op1Reg(ABS, result, input));
         return result;
     }
@@ -731,7 +735,7 @@
      * @return Value representing the result of the operation
      */
     public Value emitMathCeil(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new Op1Reg(CEIL, result, input));
         return result;
     }
@@ -743,7 +747,7 @@
      * @return Value representing the result of the operation
      */
     public Value emitMathFloor(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new Op1Reg(FLOOR, result, input));
         return result;
     }
@@ -755,7 +759,7 @@
      * @return Value representing the result of the operation
      */
     public Value emitMathRint(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new Op1Reg(RINT, result, input));
         return result;
     }
@@ -768,7 +772,7 @@
      */
     @Override
     public Value emitMathSqrt(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new Op1Reg(SQRT, result, input));
         return result;
     }
@@ -794,12 +798,12 @@
     }
 
     @Override
-    public void emitByteSwap(Variable result, Value input) {
+    public Value emitByteSwap(Value input) {
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    public void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length) {
+    public Value emitArrayEquals(Kind kind, Value array1, Value array2, Value length) {
         // TODO Auto-generated method stub
         throw GraalInternalError.unimplemented();
     }
@@ -808,7 +812,7 @@
     public void emitReturn(Value input) {
         AllocatableValue operand = Value.ILLEGAL;
         if (input != null) {
-            operand = resultOperandFor(input.getKind());
+            operand = resultOperandFor(input.getLIRKind());
             emitMove(operand, input);
         }
         append(new ReturnOp(operand));
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java	Mon Jun 30 12:02:19 2014 +0200
@@ -47,12 +47,12 @@
 
     @Override
     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented();
+        throw GraalInternalError.unimplemented(MetaUtil.format("direct call to %H.%n(%p)", callTarget.target()));
     }
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw GraalInternalError.unimplemented();
+        throw GraalInternalError.unimplemented(MetaUtil.format("direct call to %H.%n(%p)", callTarget.target()));
     }
 
     @Override
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Jun 30 12:02:19 2014 +0200
@@ -24,7 +24,6 @@
 package com.oracle.graal.compiler.ptx;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.ptx.PTXArithmetic.*;
 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.ptx.PTXCompare.*;
@@ -112,24 +111,9 @@
         }
     }
 
-    protected static AllocatableValue toParamKind(AllocatableValue value) {
-        if (value.getKind().getStackKind() != value.getKind()) {
-            // We only have stack-kinds in the LIR, so convert the operand kind for values from the
-            // calling convention.
-            if (isRegister(value)) {
-                return asRegister(value).asValue(value.getKind().getStackKind());
-            } else if (isStackSlot(value)) {
-                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
-            } else {
-                throw GraalInternalError.shouldNotReachHere();
-            }
-        }
-        return value;
-    }
-
     public Variable emitWarpParam(Kind kind, Warp annotation) {
-        Variable result = newVariable(kind);
-        Variable tid = newVariable(Kind.Char);
+        Variable result = newVariable(target().getLIRKind(kind));
+        Variable tid = newVariable(LIRKind.value(Kind.Char));
 
         switch (annotation.dimension()) {
             case X:
@@ -149,7 +133,7 @@
 
     @Override
     public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         emitMove(result, input);
         return result;
     }
@@ -208,14 +192,15 @@
                 if (baseRegister.equals(Value.ILLEGAL)) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
-                    Variable longBaseRegister = newVariable(Kind.Long);
+                    Variable longBaseRegister = newVariable(LIRKind.value(Kind.Long));
                     emitMove(longBaseRegister, baseRegister);
                     baseRegister = emitAdd(longBaseRegister, indexRegister);
                 }
             }
         }
 
-        return new PTXAddressValue(target().wordKind, baseRegister, finalDisp);
+        LIRKind resultKind = getAddressKind(base, displacement, index);
+        return new PTXAddressValue(resultKind, baseRegister, finalDisp);
     }
 
     private PTXAddressValue asAddress(Value address) {
@@ -229,18 +214,18 @@
     }
 
     @Override
-    public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) {
+    public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) {
         PTXAddressValue loadAddress = asAddress(address);
         Variable result = newVariable(kind);
-        append(new LoadOp((Kind) kind, result, loadAddress, state));
+        append(new LoadOp((Kind) kind.getPlatformKind(), result, loadAddress, state));
         return result;
     }
 
     @Override
-    public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) {
+    public void emitStore(LIRKind kind, Value address, Value inputVal, LIRFrameState state) {
         PTXAddressValue storeAddress = asAddress(address);
         Variable input = load(inputVal);
-        append(new StoreOp((Kind) kind, storeAddress, input, state));
+        append(new StoreOp((Kind) kind.getPlatformKind(), storeAddress, input, state));
     }
 
     @Override
@@ -301,7 +286,7 @@
 
         emitCompare(finalCondition, left, right);
 
-        Variable result = newVariable(trueValue.getKind());
+        Variable result = newVariable(trueValue.getLIRKind());
         switch (left.getKind().getStackKind()) {
             case Int:
             case Long:
@@ -366,7 +351,7 @@
     @Override
     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
         emitIntegerTest(left, right);
-        Variable result = newVariable(trueValue.getKind());
+        Variable result = newVariable(trueValue.getLIRKind());
         append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue), nextPredRegNum));
         nextPredRegNum++;
 
@@ -385,7 +370,7 @@
 
     @Override
     public Variable emitNegate(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind()) {
             case Int:
                 append(new Op1Stack(INEG, result, input));
@@ -404,7 +389,7 @@
 
     @Override
     public Variable emitNot(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind()) {
             case Int:
                 append(new Op1Stack(INOT, result, input));
@@ -420,7 +405,7 @@
 
     @Override
     public Variable emitAdd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Stack(IADD, result, a, loadNonConst(b)));
@@ -442,7 +427,7 @@
 
     @Override
     public Variable emitSub(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
@@ -464,7 +449,7 @@
 
     @Override
     public Variable emitMul(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
@@ -496,7 +481,7 @@
 
     @Override
     public Value emitDiv(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
@@ -518,7 +503,7 @@
 
     @Override
     public Value emitRem(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Reg(IREM, result, a, loadNonConst(b)));
@@ -544,7 +529,7 @@
 
     @Override
     public Variable emitAnd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
@@ -560,7 +545,7 @@
 
     @Override
     public Variable emitOr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Stack(IOR, result, a, loadNonConst(b)));
@@ -576,7 +561,7 @@
 
     @Override
     public Variable emitXor(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
@@ -592,7 +577,7 @@
 
     @Override
     public Variable emitShl(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
@@ -608,7 +593,7 @@
 
     @Override
     public Variable emitShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
@@ -624,7 +609,7 @@
 
     @Override
     public Variable emitUShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind()) {
             case Int:
                 append(new ShiftOp(IUSHR, result, a, b));
@@ -640,7 +625,7 @@
 
     public Variable emitConvertOp(Kind from, Kind to, Value inputVal) {
         Variable input = load(inputVal);
-        Variable result = newVariable(to);
+        Variable result = newVariable(LIRKind.value(to));
         append(new ConvertOp(result, input, to, from));
         return result;
     }
@@ -723,17 +708,17 @@
             return inputVal;
         } else if (fromBits > 32) {
             assert inputVal.getKind() == Kind.Long;
-            Variable result = newVariable(Kind.Long);
+            Variable result = newVariable(LIRKind.value(Kind.Long));
             long mask = IntegerStamp.defaultMask(fromBits);
             append(new Op2Stack(LAND, result, inputVal, Constant.forLong(mask)));
             return result;
         } else {
             assert inputVal.getKind() == Kind.Int;
-            Variable result = newVariable(Kind.Int);
+            Variable result = newVariable(LIRKind.value(Kind.Int));
             int mask = (int) IntegerStamp.defaultMask(fromBits);
             append(new Op2Stack(IAND, result, inputVal, Constant.forInt(mask)));
             if (toBits > 32) {
-                Variable longResult = newVariable(Kind.Long);
+                Variable longResult = newVariable(LIRKind.value(Kind.Long));
                 emitMove(longResult, result);
                 return longResult;
             } else {
@@ -743,7 +728,7 @@
     }
 
     @Override
-    public Value emitReinterpret(PlatformKind to, Value inputVal) {
+    public Value emitReinterpret(LIRKind to, Value inputVal) {
         Variable result = newVariable(to);
         emitMove(result, inputVal);
         return result;
@@ -765,21 +750,23 @@
     }
 
     @Override
-    public void emitBitCount(Variable result, Value value) {
+    public Value emitBitCount(Value value) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         if (value.getKind().getStackKind() == Kind.Int) {
             append(new PTXBitManipulationOp(IPOPCNT, result, value));
         } else {
             append(new PTXBitManipulationOp(LPOPCNT, result, value));
         }
+        return result;
     }
 
     @Override
-    public void emitBitScanForward(Variable result, Value value) {
+    public Value emitBitScanForward(Value value) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitBitScanForward()");
     }
 
     @Override
-    public void emitBitScanReverse(Variable result, Value value) {
+    public Value emitBitScanReverse(Value value) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitBitScanReverse()");
     }
 
@@ -814,12 +801,12 @@
     }
 
     @Override
-    public void emitByteSwap(Variable result, Value input) {
+    public Value emitByteSwap(Value input) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitByteSwap()");
     }
 
     @Override
-    public void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length) {
+    public Value emitArrayEquals(Kind kind, Value array1, Value array2, Value length) {
         // TODO Auto-generated method stub
         throw GraalInternalError.unimplemented();
     }
@@ -827,7 +814,7 @@
     @Override
     public void emitReturn(Value input) {
         if (input != null) {
-            AllocatableValue operand = resultOperandFor(input.getKind());
+            AllocatableValue operand = resultOperandFor(input.getLIRKind());
             // Load the global memory address from return parameter
             Variable loadVar = emitLoadReturnAddress(operand.getKind(), operand, null);
             // Store input in global memory whose location is loadVar
@@ -843,7 +830,7 @@
     @Override
     public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         boolean needsTemp = key.getKind() == Kind.Object;
-        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL, nextPredRegNum++));
+        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getLIRKind()) : Value.ILLEGAL, nextPredRegNum++));
     }
 
     @Override
@@ -851,7 +838,7 @@
         // Making a copy of the switch value is necessary because jump table destroys the input
         // value
         Variable tmp = emitMove(key);
-        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target().wordKind), nextPredRegNum++));
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(LIRKind.value(target().wordKind)), nextPredRegNum++));
     }
 
     @Override
@@ -862,7 +849,7 @@
     public Variable emitLoadParam(Kind kind, Value address, LIRFrameState state) {
 
         PTXAddressValue loadAddress = asAddress(address);
-        Variable result = newVariable(kind);
+        Variable result = newVariable(target().getLIRKind(kind));
         append(new LoadParamOp(kind, result, loadAddress, state));
 
         return result;
@@ -873,13 +860,13 @@
         Variable result;
         switch (kind) {
             case Float:
-                result = newVariable(Kind.Int);
+                result = newVariable(LIRKind.value(Kind.Int));
                 break;
             case Double:
-                result = newVariable(Kind.Long);
+                result = newVariable(LIRKind.value(Kind.Long));
                 break;
             default:
-                result = newVariable(kind);
+                result = newVariable(target().getLIRKind(kind));
         }
         append(new LoadReturnAddrOp(kind, result, loadAddress, state));
 
@@ -893,10 +880,7 @@
     }
 
     @Override
-    public AllocatableValue resultOperandFor(Kind kind) {
-        if (kind == Kind.Void) {
-            return ILLEGAL;
-        }
+    public AllocatableValue resultOperandFor(LIRKind kind) {
         return (new Variable(kind, 0));
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jun 30 12:02:19 2014 +0200
@@ -90,7 +90,7 @@
 
     @Override
     public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         emitMove(result, input);
         return result;
     }
@@ -177,14 +177,15 @@
                 if (finalDisp == 0) {
                     // Nothing to do. Just use the base register.
                 } else {
-                    Variable longBaseRegister = newVariable(Kind.Long);
+                    Variable longBaseRegister = newVariable(LIRKind.derivedReference(Kind.Long));
                     emitMove(longBaseRegister, baseRegister);
                     baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp));
                 }
             }
         }
 
-        return new SPARCAddressValue(target().wordKind, baseRegister, indexRegister, displacementInt);
+        LIRKind resultKind = getAddressKind(base, displacement, index);
+        return new SPARCAddressValue(resultKind, baseRegister, indexRegister, displacementInt);
     }
 
     protected SPARCAddressValue asAddressValue(Value address) {
@@ -197,7 +198,7 @@
 
     @Override
     public Value emitAddress(StackSlot address) {
-        Variable result = newVariable(target().wordKind);
+        Variable result = newVariable(LIRKind.value(target().wordKind));
         append(new StackLoadAddressOp(result, address));
         return result;
     }
@@ -206,7 +207,7 @@
     public void emitReturn(Value input) {
         AllocatableValue operand = Value.ILLEGAL;
         if (input != null) {
-            operand = resultOperandFor(input.getKind());
+            operand = resultOperandFor(input.getLIRKind());
             emitMove(operand, input);
         }
         append(new ReturnOp(operand));
@@ -268,7 +269,7 @@
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
 
-        Variable result = newVariable(trueValue.getKind());
+        Variable result = newVariable(trueValue.getLIRKind());
         Kind kind = left.getKind().getStackKind();
         switch (kind) {
             case Int:
@@ -332,7 +333,7 @@
     @Override
     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
         emitIntegerTest(left, right);
-        Variable result = newVariable(trueValue.getKind());
+        Variable result = newVariable(trueValue.getLIRKind());
         Kind kind = left.getKind().getStackKind();
         append(new CondMoveOp(kind, result, Condition.EQ, load(trueValue), loadNonConst(falseValue)));
         return result;
@@ -352,7 +353,7 @@
     public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         // a temp is needed for loading long and object constants
         boolean needsTemp = key.getKind() == Kind.Long || key.getKind() == Kind.Object;
-        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL));
+        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getLIRKind()) : Value.ILLEGAL));
     }
 
     @Override
@@ -360,88 +361,96 @@
         // Making a copy of the switch value is necessary because jump table destroys the input
         // value
         Variable tmp = emitMove(key);
-        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target().wordKind)));
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(LIRKind.value(target().wordKind))));
     }
 
     @Override
-    public void emitBitCount(Variable result, Value operand) {
+    public Value emitBitCount(Value operand) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         if (operand.getKind().getStackKind() == Kind.Int) {
             append(new SPARCBitManipulationOp(IPOPCNT, result, asAllocatable(operand), this));
         } else {
             append(new SPARCBitManipulationOp(LPOPCNT, result, asAllocatable(operand), this));
         }
+        return result;
     }
 
     @Override
-    public void emitBitScanForward(Variable result, Value operand) {
+    public Value emitBitScanForward(Value operand) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         append(new SPARCBitManipulationOp(BSF, result, asAllocatable(operand), this));
+        return result;
     }
 
     @Override
-    public void emitBitScanReverse(Variable result, Value operand) {
+    public Value emitBitScanReverse(Value operand) {
+        Variable result = newVariable(LIRKind.value(Kind.Int));
         if (operand.getKind().getStackKind() == Kind.Int) {
             append(new SPARCBitManipulationOp(IBSR, result, asAllocatable(operand), this));
         } else {
             append(new SPARCBitManipulationOp(LBSR, result, asAllocatable(operand), this));
         }
+        return result;
     }
 
     @Override
     public Value emitMathAbs(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new BinaryRegConst(DAND, result, asAllocatable(input), Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL))));
         return result;
     }
 
     @Override
     public Value emitMathSqrt(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new SPARCMathIntrinsicOp(SQRT, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathLog(Value input, boolean base10) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new SPARCMathIntrinsicOp(LOG, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathCos(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new SPARCMathIntrinsicOp(COS, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathSin(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new SPARCMathIntrinsicOp(SIN, result, asAllocatable(input)));
         return result;
     }
 
     @Override
     public Value emitMathTan(Value input) {
-        Variable result = newVariable(input.getPlatformKind());
+        Variable result = newVariable(input.getLIRKind());
         append(new SPARCMathIntrinsicOp(TAN, result, asAllocatable(input)));
         return result;
     }
 
     @Override
-    public void emitByteSwap(Variable result, Value input) {
+    public Value emitByteSwap(Value input) {
+        Variable result = newVariable(input.getLIRKind());
         append(new SPARCByteSwapOp(result, input));
+        return result;
     }
 
     @Override
-    public void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length) {
+    public Value emitArrayEquals(Kind kind, Value array1, Value array2, Value length) {
         // TODO Auto-generated method stub
         throw GraalInternalError.unimplemented();
     }
 
     @Override
     public Value emitNegate(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind().getStackKind()) {
             case Long:
                 append(new Op1Stack(LNEG, result, input));
@@ -463,7 +472,7 @@
 
     @Override
     public Value emitNot(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getLIRKind());
         switch (input.getKind().getStackKind()) {
             case Int:
                 append(new Op1Stack(INOT, result, input));
@@ -502,7 +511,7 @@
             case IMUL:
             case LMUL:
                 if (NumUtil.isInt(b.asLong())) {
-                    Variable result = newVariable(a.getKind());
+                    Variable result = newVariable(a.getLIRKind());
                     append(new BinaryRegConst(op, result, a, b));
                     return result;
                 }
@@ -513,7 +522,7 @@
     }
 
     private Variable emitBinaryVar(SPARCArithmetic op, boolean commutative, AllocatableValue a, AllocatableValue b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         if (commutative) {
             append(new BinaryCommutative(op, result, a, b));
         } else {
@@ -540,7 +549,7 @@
 
     @Override
     public Variable emitSub(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
@@ -562,7 +571,7 @@
 
     @Override
     public Variable emitMul(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind().getStackKind()) {
             case Int:
                 append(new BinaryRegReg(IMUL, result, a, loadNonConst(b)));
@@ -594,13 +603,13 @@
 
     @Override
     public Value emitDiv(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind().getStackKind()) {
             case Int:
                 append(new BinaryRegReg(IDIV, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new BinaryRegReg(LDIV, result, a, loadNonConst(b), state));
+                append(new BinaryRegReg(LDIV, result, a, loadNonConst(b)));
                 break;
             case Float:
                 append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
@@ -616,7 +625,7 @@
 
     @Override
     public Value emitRem(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         Variable q = null;
         switch (a.getKind().getStackKind()) {
             case Int:
@@ -626,7 +635,7 @@
                 append(new RemOp(LREM, result, a, loadNonConst(b), state, this));
                 break;
             case Float:
-                q = newVariable(Kind.Float);
+                q = newVariable(LIRKind.value(Kind.Float));
                 append(new Op2Stack(FDIV, q, a, b));
                 append(new Unary2Op(F2I, q, q));
                 append(new Unary2Op(I2F, q, q));
@@ -634,7 +643,7 @@
                 append(new Op2Stack(FSUB, result, a, q));
                 break;
             case Double:
-                q = newVariable(Kind.Double);
+                q = newVariable(LIRKind.value(Kind.Double));
                 append(new Op2Stack(DDIV, q, a, b));
                 append(new Unary2Op(D2L, q, q));
                 append(new Unary2Op(L2D, q, q));
@@ -679,7 +688,7 @@
 
     @Override
     public Variable emitAnd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
@@ -696,7 +705,7 @@
 
     @Override
     public Variable emitOr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(IOR, result, a, loadNonConst(b)));
@@ -712,7 +721,7 @@
 
     @Override
     public Variable emitXor(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
+        Variable result = newVariable(a.getLIRKind());
         switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
@@ -727,7 +736,7 @@
     }
 
     private Variable emitShift(SPARCArithmetic op, Value a, Value b) {
-        Variable result = newVariable(a.getPlatformKind());
+        Variable result = newVariable(a.getLIRKind());
         AllocatableValue input = asAllocatable(a);
         if (isConstant(b)) {
             append(new BinaryRegConst(op, result, input, asConstant(b)));
@@ -773,13 +782,13 @@
         }
     }
 
-    private AllocatableValue emitConvertMove(PlatformKind kind, AllocatableValue input) {
+    private AllocatableValue emitConvertMove(LIRKind kind, AllocatableValue input) {
         Variable result = newVariable(kind);
         emitMove(result, input);
         return result;
     }
 
-    private AllocatableValue emitConvert2Op(PlatformKind kind, SPARCArithmetic op, AllocatableValue input) {
+    private AllocatableValue emitConvert2Op(LIRKind kind, SPARCArithmetic op, AllocatableValue input) {
         Variable result = newVariable(kind);
         append(new Unary2Op(op, result, input));
         return result;
@@ -793,14 +802,14 @@
         SPARCArithmetic conversionInstruction = null;
         switch (op) {
             case D2F:
-                return emitConvert2Op(Kind.Float, D2F, input);
+                return emitConvert2Op(LIRKind.value(Kind.Float), D2F, input);
             case D2I:
                 fromRegisterKind = Kind.Double;
                 toRegisterKind = Kind.Int;
                 conversionInstruction = D2I;
                 break;
             case F2L:
-                Variable v = newVariable(Kind.Double);
+                Variable v = newVariable(LIRKind.value(Kind.Double));
                 emitMove(v, input);
                 input = v;
             case D2L:
@@ -809,26 +818,26 @@
                 conversionInstruction = D2L;
                 break;
             case F2D:
-                return emitConvert2Op(Kind.Double, F2D, input);
+                return emitConvert2Op(LIRKind.value(Kind.Double), F2D, input);
             case F2I:
                 fromRegisterKind = Kind.Float;
                 toRegisterKind = Kind.Int;
                 conversionInstruction = F2I;
                 break;
             case I2D:
-                return emitConvert2Op(Kind.Double, L2D, emitConvert2Op(Kind.Long, I2L, input));
+                return emitConvert2Op(LIRKind.value(Kind.Double), I2D, input);
             case I2F:
-                return emitConvert2Op(Kind.Float, I2F, input);
+                return emitConvert2Op(LIRKind.value(Kind.Float), I2F, input);
             case L2D:
-                return emitConvert2Op(Kind.Double, L2D, input);
+                return emitConvert2Op(LIRKind.value(Kind.Double), L2D, input);
             case L2F:
-                return emitConvert2Op(Kind.Float, D2F, emitConvert2Op(Kind.Double, L2D, input));
+                return emitConvert2Op(LIRKind.value(Kind.Float), L2F, input);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
         if (fromRegisterKind != null) {
-            AllocatableValue var = newVariable(toRegisterKind);
-            emitMove(var, emitConvert2Op(fromRegisterKind, conversionInstruction, input));
+            AllocatableValue var = newVariable(LIRKind.value(toRegisterKind));
+            emitMove(var, emitConvert2Op(LIRKind.value(fromRegisterKind), conversionInstruction, input));
             return var;
         } else {
             throw GraalInternalError.shouldNotReachHere();
@@ -838,7 +847,7 @@
     @Override
     public Value emitNarrow(Value inputVal, int bits) {
         if (inputVal.getKind() == Kind.Long && bits <= 32) {
-            return emitConvert2Op(Kind.Int, L2I, asAllocatable(inputVal));
+            return emitConvert2Op(LIRKind.value(Kind.Int), L2I, asAllocatable(inputVal));
         } else {
             return inputVal;
         }
@@ -853,11 +862,11 @@
             // sign extend to 64 bits
             switch (fromBits) {
                 case 8:
-                    return emitConvert2Op(Kind.Long, B2L, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Long), B2L, asAllocatable(inputVal));
                 case 16:
-                    return emitConvert2Op(Kind.Long, S2L, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Long), S2L, asAllocatable(inputVal));
                 case 32:
-                    return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Long), I2L, asAllocatable(inputVal));
                 default:
                     throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
             }
@@ -865,9 +874,9 @@
             // sign extend to 32 bits (smaller values are internally represented as 32 bit values)
             switch (fromBits) {
                 case 8:
-                    return emitConvert2Op(Kind.Int, B2I, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Int), B2I, asAllocatable(inputVal));
                 case 16:
-                    return emitConvert2Op(Kind.Int, S2I, asAllocatable(inputVal));
+                    return emitConvert2Op(LIRKind.value(Kind.Int), S2I, asAllocatable(inputVal));
                 case 32:
                     return inputVal;
                 default:
@@ -882,25 +891,25 @@
         if (fromBits == toBits) {
             return inputVal;
         } else if (fromBits > 32) {
-            assert inputVal.getKind() == Kind.Long : inputVal.getKind();
-            Variable result = newVariable(Kind.Long);
+            assert inputVal.getKind() == Kind.Long;
+            Variable result = newVariable(LIRKind.value(Kind.Long));
             long mask = IntegerStamp.defaultMask(fromBits);
             append(new BinaryRegConst(SPARCArithmetic.LAND, result, asAllocatable(inputVal), Constant.forLong(mask)));
             return result;
         } else {
             assert inputVal.getKind() == Kind.Int || inputVal.getKind() == Kind.Short || inputVal.getKind() == Kind.Byte : inputVal.getKind();
-            Variable result = newVariable(Kind.Int);
+            Variable result = newVariable(LIRKind.value(Kind.Int));
             int mask = (int) IntegerStamp.defaultMask(fromBits);
             Constant constant = Constant.forInt(mask);
             if (canInlineConstant(constant)) {
                 append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), constant));
             } else {
-                Variable maskVar = newVariable(Kind.Int);
+                Variable maskVar = newVariable(LIRKind.value(Kind.Int));
                 emitMove(maskVar, constant);
                 append(new BinaryRegReg(IAND, result, maskVar, (inputVal)));
             }
             if (toBits > 32) {
-                Variable longResult = newVariable(Kind.Long);
+                Variable longResult = newVariable(LIRKind.value(Kind.Long));
                 emitMove(longResult, result);
                 return longResult;
             } else {
@@ -910,12 +919,12 @@
     }
 
     @Override
-    public AllocatableValue emitReinterpret(PlatformKind to, Value inputVal) {
+    public AllocatableValue emitReinterpret(LIRKind to, Value inputVal) {
         Kind from = inputVal.getKind();
         AllocatableValue input = asAllocatable(inputVal);
 
         // These cases require a move between CPU and FPU registers:
-        switch ((Kind) to) {
+        switch ((Kind) to.getPlatformKind()) {
             case Int:
                 switch (from) {
                     case Float:
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java	Mon Jun 30 12:02:19 2014 +0200
@@ -39,11 +39,11 @@
  * trace is governed by the value of the "AllocSpy.ContextSize" system property (default is 5).
  * 

* Using this facility requires using -javaagent on the command line. For example: - * + * *

  * mx --vm server unittest -javaagent:lib/java-allocation-instrumenter.jar -dsa -DAllocSpy.ContextSize=6 BC_iadd2
  * 
- * + * * @see #SampleBytes * @see #SampleInstances * @see #HistogramLimit @@ -237,8 +237,8 @@ } else { if (!excludeFrame(className)) { sb.append("type=").append(desc); - if (count != 1) { - sb.append("[]"); + if (count != -1) { + sb.append('[').append(count).append(']'); } append(sb.append('\n'), e); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Mon Jun 30 12:02:19 2014 +0200 @@ -27,6 +27,7 @@ import java.io.*; import java.lang.reflect.*; import java.util.*; +import java.util.concurrent.*; import java.util.zip.*; import org.junit.*; @@ -34,6 +35,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess; import com.oracle.graal.debug.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; @@ -42,6 +45,7 @@ import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.phases.verify.*; +import com.oracle.graal.printer.*; import com.oracle.graal.runtime.*; import com.oracle.graal.test.*; @@ -97,7 +101,15 @@ String property = System.getProperty(CheckGraalInvariants.class.getName() + ".filters"); String[] filters = property == null ? null : property.split(","); - List errors = new ArrayList<>(); + CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread", new DebugConfigAccess() { + public GraalDebugConfig getDebugConfig() { + return DebugEnvironment.initialize(System.out); + } + }); + int availableProcessors = Runtime.getRuntime().availableProcessors(); + ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); + + List errors = Collections.synchronizedList(new ArrayList<>()); for (String className : classNames) { try { Class c = Class.forName(className, false, CheckGraalInvariants.class.getClassLoader()); @@ -107,22 +119,24 @@ } else { String methodName = className + "." + m.getName(); if (matches(filters, methodName)) { - StructuredGraph graph = new StructuredGraph(metaAccess.lookupJavaMethod(m)); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { - graphBuilderSuite.apply(graph, context); - checkGraph(context, graph); - } catch (VerificationError e) { - errors.add(e.getMessage()); - } catch (LinkageError e) { - // suppress linkages errors resulting from eager resolution - } catch (BailoutException e) { - // Graal bail outs on certain patterns in Java bytecode (e.g., - // unbalanced monitors introduced by jacoco). - } catch (Throwable e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - errors.add(String.format("Error while checking %s:%n%s", methodName, sw)); - } + executor.execute(() -> { + StructuredGraph graph = new StructuredGraph(metaAccess.lookupJavaMethod(m)); + try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { + graphBuilderSuite.apply(graph, context); + checkGraph(context, graph); + } catch (VerificationError e) { + errors.add(e.getMessage()); + } catch (LinkageError e) { + // suppress linkages errors resulting from eager resolution + } catch (BailoutException e) { + // Graal bail outs on certain patterns in Java bytecode (e.g., + // unbalanced monitors introduced by jacoco). + } catch (Throwable e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + errors.add(String.format("Error while checking %s:%n%s", methodName, sw)); + } + }); } } } @@ -131,6 +145,13 @@ e.printStackTrace(); } } + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.HOURS); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } + if (!errors.isEmpty()) { StringBuilder msg = new StringBuilder(); String nl = String.format("%n"); @@ -153,6 +174,7 @@ new VerifyUsageWithEquals(JavaType.class).apply(graph, context); new VerifyUsageWithEquals(JavaMethod.class).apply(graph, context); new VerifyUsageWithEquals(JavaField.class).apply(graph, context); + new VerifyUsageWithEquals(LIRKind.class).apply(graph, context); new VerifyDebugUsage().apply(graph, context); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -103,7 +103,7 @@ IntegerTestNode test = (IntegerTestNode) conditional.condition(); ParameterNode param0 = graph.getParameter(0); ParameterNode param1 = graph.getParameter(1); - assertTrue((test.x() == param0 && test.y() == param1) || (test.x() == param1 && test.y() == param0)); + assertTrue((test.getX() == param0 && test.getY() == param1) || (test.getX() == param1 && test.getY() == param0)); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatOptimizationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatOptimizationTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, 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.compiler.test; + +import org.junit.*; + +/** + * Check for incorrect elimination of 0.0 and -0.0 from computations. They can affect the sign of + * the result of an add or substract. + */ +public class FloatOptimizationTest extends GraalCompilerTest { + + @Test + public void test1() { + test("test1Snippet", -0.0); + } + + @SuppressWarnings("all") + public static double test1Snippet(double x) { + return x + 0.0; + } + + @Test + public void test2() { + test("test2Snippet", -0.0f); + } + + @SuppressWarnings("all") + public static double test2Snippet(float x) { + return x + 0.0f; + } + + @Test + public void test3() { + test("test3Snippet", -0.0); + } + + @SuppressWarnings("all") + public static double test3Snippet(double x) { + return x - -0.0; + } + + @Test + public void test4() { + test("test4Snippet", -0.0f); + } + + @SuppressWarnings("all") + public static double test4Snippet(float x) { + return x - -0.0f; + } + + @Override + protected void assertDeepEquals(String message, Object expected, Object actual, double delta) { + if (expected instanceof Double && actual instanceof Double) { + double e = (double) expected; + double a = (double) actual; + if (Double.doubleToRawLongBits(a) != Double.doubleToRawLongBits(e)) { + Assert.fail((message == null ? "" : message) + "raw double bits not equal " + Double.doubleToRawLongBits(a) + " != " + Double.doubleToRawLongBits(e)); + } + } else { + super.assertDeepEquals(message, expected, actual, delta); + } + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -384,7 +384,7 @@ public StructuredGraph visualize(StructuredGraph graph, String title) { DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { Debug.dump(graph, title); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -148,9 +148,7 @@ new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); for (ConstantNode constant : getConstantNodes(graph)) { - if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); - } + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); } } @@ -186,9 +184,7 @@ new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), null)); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); for (ConstantNode constant : getConstantNodes(graph)) { - if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); - } + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); } } diff -r 51f392557124 -r 5f01f7c48d40 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 Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -213,14 +213,8 @@ protected int countUnusedConstants(StructuredGraph graph) { int total = 0; for (ConstantNode node : getConstantNodes(graph)) { - if (!ConstantNodeRecordsUsages) { - if (node.gatherUsages(graph).isEmpty()) { - total++; - } - } else { - if (node.usages().isEmpty()) { - total++; - } + if (node.usages().isEmpty()) { + total++; } } return total; @@ -275,7 +269,7 @@ } result.append("\n"); for (Node node : schedule.getBlockToNodesMap().get(block)) { - if (node.recordsUsages()) { + if (node.isAlive() && node.recordsUsages()) { if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) { int id; if (canonicalId.get(node) != null) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -651,7 +651,7 @@ MidTierContext midContext = new MidTierContext(getProviders(), assumptions, getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); SchedulePhase schedule = new SchedulePhase(schedulingStrategy, memsched); schedule.apply(graph); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -85,9 +85,11 @@ private StructuredGraph parseAndProcess(String snippet) { StructuredGraph graph = parse(snippet); ParameterNode param = graph.getNodes(ParameterNode.class).first(); - ConstantNode constant = ConstantNode.forInt(0, graph); - for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) { - n.replaceFirstInput(param, constant); + if (param != null) { + ConstantNode constant = ConstantNode.forInt(0, graph); + for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) { + n.replaceFirstInput(param, constant); + } } Map hints = new HashMap<>(); for (Invoke invoke : graph.getInvokes()) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -80,18 +80,20 @@ } } - private void collectStats(final LIRInstruction instr) { - instr.forEachOutput(new ValueProcedure() { + private ValueProcedure collectStatsProc = new ValueProcedure() { - @Override - public Value doValue(Value value) { - if (ValueUtil.isRegister(value)) { - final Register reg = ValueUtil.asRegister(value); - registers.add(reg); - } - return value; + @Override + public Value doValue(Value value) { + if (ValueUtil.isRegister(value)) { + final Register reg = ValueUtil.asRegister(value); + registers.add(reg); } - }); + return value; + } + }; + + private void collectStats(final LIRInstruction instr) { + instr.forEachOutput(collectStatsProc); if (instr instanceof MoveOp) { MoveOp move = (MoveOp) instr; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -25,10 +25,9 @@ import org.junit.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.loop.phases.*; -import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; @@ -279,7 +278,7 @@ @SuppressWarnings("unused") public static void testNewNodeSnippet() { - new IntegerAddNode(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null); + new ValueAnchorNode(null); } /** diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -42,6 +42,8 @@ public static final OptionValue Dump = new OptionValue<>(null); @Option(help = "Pattern for scope(s) to in which metering is enabled (see DebugFilter and Debug.metric)") public static final OptionValue Meter = new OptionValue<>(null); + @Option(help = "Pattern for scope(s) to in which verification is enabled (see DebugFilter and Debug.verify)") + public static final OptionValue Verify = new OptionValue<>(null); @Option(help = "Pattern for scope(s) to in which memory use tracking is enabled (see DebugFilter and Debug.metric)") public static final OptionValue TrackMemUse = new OptionValue<>(null); @Option(help = "Pattern for scope(s) to in which timing is enabled (see DebugFilter and Debug.timer)") @@ -89,18 +91,21 @@ private final DebugFilter trackMemUseFilter; private final DebugFilter timerFilter; private final DebugFilter dumpFilter; + private final DebugFilter verifyFilter; private final MethodFilter[] methodFilter; private final List dumpHandlers; + private final List verifyHandlers; private final PrintStream output; private final Set extraFilters = new HashSet<>(); - public GraalDebugConfig(String logFilter, String meterFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output, - List dumpHandlers) { + public GraalDebugConfig(String logFilter, String meterFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, PrintStream output, + List dumpHandlers, List verifyHandlers) { this.logFilter = DebugFilter.parse(logFilter); this.meterFilter = DebugFilter.parse(meterFilter); this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); this.timerFilter = DebugFilter.parse(timerFilter); this.dumpFilter = DebugFilter.parse(dumpFilter); + this.verifyFilter = DebugFilter.parse(verifyFilter); if (methodFilter == null || methodFilter.isEmpty()) { this.methodFilter = null; } else { @@ -112,6 +117,7 @@ // TTY.println(Thread.currentThread().getName() + ": " + toString()); } this.dumpHandlers = dumpHandlers; + this.verifyHandlers = verifyHandlers; this.output = output; } @@ -127,10 +133,6 @@ return isEnabled(meterFilter); } - public boolean isMetderEnabled() { - return isEnabled(meterFilter); - } - public boolean isMemUseTrackingEnabled() { return isEnabled(trackMemUseFilter); } @@ -143,6 +145,14 @@ return isEnabledForMethod(dumpFilter); } + public boolean isVerifyEnabled() { + return isEnabled(verifyFilter); + } + + public boolean isVerifyEnabledForMethod() { + return isEnabledForMethod(verifyFilter); + } + public boolean isTimeEnabled() { return isEnabled(timerFilter); } @@ -231,7 +241,7 @@ if (e instanceof BailoutException) { return null; } - Debug.setConfig(Debug.fixedConfig(true, true, false, false, false, dumpHandlers, output)); + Debug.setConfig(Debug.fixedConfig(true, true, false, false, false, false, dumpHandlers, verifyHandlers, output)); Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope())); for (Object o : Debug.context()) { if (o instanceof Graph) { @@ -269,6 +279,11 @@ } @Override + public Collection verifyHandlers() { + return verifyHandlers; + } + + @Override public void addToContext(Object o) { extraFilters.add(o); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -451,7 +451,7 @@ /** * The kind of this interval. */ - private PlatformKind kind; + private LIRKind kind; /** * The head of the list of ranges describing this interval. This list is sorted by @@ -533,7 +533,7 @@ void assignLocation(AllocatableValue newLocation) { if (isRegister(newLocation)) { assert this.location == null : "cannot re-assign location for " + this; - if (newLocation.getPlatformKind() == Kind.Illegal && kind != Kind.Illegal) { + if (newLocation.getLIRKind().equals(LIRKind.Illegal) && !kind.equals(LIRKind.Illegal)) { this.location = asRegister(newLocation).asValue(kind); return; } @@ -542,8 +542,8 @@ } else { assert this.location == null || isRegister(this.location) : "cannot re-assign location for " + this; assert isStackSlot(newLocation); - assert newLocation.getPlatformKind() != Kind.Illegal; - assert newLocation.getPlatformKind() == this.kind; + assert !newLocation.getLIRKind().equals(LIRKind.Illegal); + assert newLocation.getLIRKind().equals(this.kind); } this.location = newLocation; } @@ -556,13 +556,13 @@ return location; } - public PlatformKind kind() { + public LIRKind kind() { assert !isRegister(operand) : "cannot access type for fixed interval"; return kind; } - void setKind(PlatformKind kind) { - assert isRegister(operand) || this.kind() == Kind.Illegal || this.kind() == kind : "overwriting existing type"; + void setKind(LIRKind kind) { + assert isRegister(operand) || this.kind().equals(LIRKind.Illegal) || this.kind().equals(kind) : "overwriting existing type"; this.kind = kind; } @@ -715,7 +715,7 @@ } else { assert isIllegal(operand) || isVariable(operand); } - this.kind = Kind.Illegal; + this.kind = LIRKind.Illegal; this.first = Range.EndMarker; this.usePosList = new UsePosList(4); this.current = Range.EndMarker; @@ -774,7 +774,7 @@ Interval i1 = splitChildren.get(i); assert i1.splitParent() == this : "not a split child of this interval"; - assert i1.kind() == kind() : "must be equal for all split children"; + assert i1.kind().equals(kind()) : "must be equal for all split children"; assert (i1.spillSlot() == null && spillSlot == null) || i1.spillSlot().equals(spillSlot()) : "must be equal for all split children"; for (int j = i + 1; j < splitChildren.size(); j++) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -41,6 +41,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.LIRInstruction.StateProcedure; @@ -959,13 +960,13 @@ } } - void addUse(AllocatableValue operand, int from, int to, RegisterPriority registerPriority, PlatformKind kind) { + void addUse(AllocatableValue operand, int from, int to, RegisterPriority registerPriority, LIRKind kind) { if (!isProcessed(operand)) { return; } Interval interval = getOrCreateInterval(operand); - if (kind != Kind.Illegal) { + if (!kind.equals(LIRKind.Illegal)) { interval.setKind(kind); } @@ -977,13 +978,13 @@ Debug.log("add use: %s, from %d to %d (%s)", interval, from, to, registerPriority.name()); } - void addTemp(AllocatableValue operand, int tempPos, RegisterPriority registerPriority, PlatformKind kind) { + void addTemp(AllocatableValue operand, int tempPos, RegisterPriority registerPriority, LIRKind kind) { if (!isProcessed(operand)) { return; } Interval interval = getOrCreateInterval(operand); - if (kind != Kind.Illegal) { + if (!kind.equals(LIRKind.Illegal)) { interval.setKind(kind); } @@ -998,14 +999,14 @@ return !isRegister(operand) || attributes(asRegister(operand)).isAllocatable(); } - void addDef(AllocatableValue operand, LIRInstruction op, RegisterPriority registerPriority, PlatformKind kind) { + void addDef(AllocatableValue operand, LIRInstruction op, RegisterPriority registerPriority, LIRKind kind) { if (!isProcessed(operand)) { return; } int defPos = op.id(); Interval interval = getOrCreateInterval(operand); - if (kind != Kind.Illegal) { + if (!kind.equals(LIRKind.Illegal)) { interval.setKind(kind); } @@ -1123,6 +1124,70 @@ void buildIntervals() { try (Indent indent = Debug.logAndIndent("build intervals")) { + InstructionValueProcedure outputProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getLIRKind()); + addRegisterHint(op, operand, mode, flags, true); + } + return operand; + } + }; + + InstructionValueProcedure tempProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + addTemp((AllocatableValue) operand, op.id(), RegisterPriority.MustHaveRegister, operand.getLIRKind()); + addRegisterHint(op, operand, mode, flags, false); + } + return operand; + } + }; + + InstructionValueProcedure aliveProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + RegisterPriority p = registerPriorityOfInputOperand(flags); + final int opId = op.id(); + final int blockFrom = getFirstLirInstructionId((blockForId(opId))); + addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getLIRKind()); + addRegisterHint(op, operand, mode, flags, false); + } + return operand; + } + }; + + InstructionValueProcedure inputProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + final int opId = op.id(); + final int blockFrom = getFirstLirInstructionId((blockForId(opId))); + RegisterPriority p = registerPriorityOfInputOperand(flags); + addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getLIRKind()); + addRegisterHint(op, operand, mode, flags, false); + } + return operand; + } + }; + + InstructionValueProcedure stateProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand) { + final int opId = op.id(); + final int blockFrom = getFirstLirInstructionId((blockForId(opId))); + addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getLIRKind()); + return operand; + } + }; // create a list with all caller-save registers (cpu, fpu, xmm) Register[] callerSaveRegs = frameMap.registerConfig.getCallerSaveRegisters(); @@ -1147,7 +1212,7 @@ AllocatableValue operand = intervalFor(operandNum).operand; Debug.log("live in %d: %s", operandNum, operand); - addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, Kind.Illegal); + addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, LIRKind.Illegal); // add special use positions for loop-end blocks when the // interval is used anywhere inside this loop. It's possible @@ -1171,72 +1236,23 @@ if (op.destroysCallerSavedRegisters()) { for (Register r : callerSaveRegs) { if (attributes(r).isAllocatable()) { - addTemp(r.asValue(), opId, RegisterPriority.None, Kind.Illegal); + addTemp(r.asValue(), opId, RegisterPriority.None, LIRKind.Illegal); } } Debug.log("operation destroys all caller-save registers"); } - op.forEachOutput(new ValueProcedure() { - - @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { - if (isVariableOrRegister(operand)) { - addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getPlatformKind()); - addRegisterHint(op, operand, mode, flags, true); - } - return operand; - } - }); - op.forEachTemp(new ValueProcedure() { - - @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { - if (isVariableOrRegister(operand)) { - addTemp((AllocatableValue) operand, opId, RegisterPriority.MustHaveRegister, operand.getPlatformKind()); - addRegisterHint(op, operand, mode, flags, false); - } - return operand; - } - }); - op.forEachAlive(new ValueProcedure() { - - @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { - if (isVariableOrRegister(operand)) { - RegisterPriority p = registerPriorityOfInputOperand(flags); - addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getPlatformKind()); - addRegisterHint(op, operand, mode, flags, false); - } - return operand; - } - }); - op.forEachInput(new ValueProcedure() { - - @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { - if (isVariableOrRegister(operand)) { - RegisterPriority p = registerPriorityOfInputOperand(flags); - addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getPlatformKind()); - addRegisterHint(op, operand, mode, flags, false); - } - return operand; - } - }); + op.forEachOutput(outputProc); + op.forEachTemp(tempProc); + op.forEachAlive(aliveProc); + op.forEachInput(inputProc); // Add uses of live locals from interpreter's point of view for proper // debug information generation // Treat these operands as temp values (if the live range is extended // to a call site, the value would be in a register at // the call otherwise) - op.forEachState(new ValueProcedure() { - - @Override - public Value doValue(Value operand) { - addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getPlatformKind()); - return operand; - } - }); + op.forEachState(stateProc); // special steps for some instructions (especially moves) handleMethodArguments(op); @@ -1682,42 +1698,44 @@ return attributes(asRegister(operand)).isCallerSave(); } + private InstructionValueProcedure debugInfoProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand) { + int tempOpId = op.id(); + OperandMode mode = OperandMode.USE; + AbstractBlock block = blockForId(tempOpId); + if (block.getSuccessorCount() == 1 && tempOpId == getLastLirInstructionId(block)) { + // generating debug information for the last instruction of a block. + // if this instruction is a branch, spill moves are inserted before this branch + // and so the wrong operand would be returned (spill moves at block boundaries + // are not + // considered in the live ranges of intervals) + // Solution: use the first opId of the branch target block instead. + final LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1); + if (instr instanceof StandardOp.JumpOp) { + if (blockData.get(block).liveOut.get(operandNumber(operand))) { + tempOpId = getFirstLirInstructionId(block.getSuccessors().iterator().next()); + mode = OperandMode.DEF; + } + } + } + + // Get current location of operand + // The operand must be live because debug information is considered when building + // the intervals + // if the interval is not live, colorLirOperand will cause an assert on failure + Value result = colorLirOperand((Variable) operand, tempOpId, mode); + assert !hasCall(tempOpId) || isStackSlot(result) || isConstant(result) || !isCallerSave(result) : "cannot have caller-save register operands at calls"; + return result; + } + }; + private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) { info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !callKillsRegisters); markFrameLocations(iw, op, info); - info.forEachState(new ValueProcedure() { - - @Override - public Value doValue(Value operand) { - int tempOpId = op.id(); - OperandMode mode = OperandMode.USE; - AbstractBlock block = blockForId(tempOpId); - if (block.getSuccessorCount() == 1 && tempOpId == getLastLirInstructionId(block)) { - // generating debug information for the last instruction of a block. - // if this instruction is a branch, spill moves are inserted before this branch - // and so the wrong operand would be returned (spill moves at block boundaries - // are not - // considered in the live ranges of intervals) - // Solution: use the first opId of the branch target block instead. - final LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1); - if (instr instanceof StandardOp.JumpOp) { - if (blockData.get(block).liveOut.get(operandNumber(operand))) { - tempOpId = getFirstLirInstructionId(block.getSuccessors().iterator().next()); - mode = OperandMode.DEF; - } - } - } - - // Get current location of operand - // The operand must be live because debug information is considered when building - // the intervals - // if the interval is not live, colorLirOperand will cause an assert on failure - Value result = colorLirOperand((Variable) operand, tempOpId, mode); - assert !hasCall(tempOpId) || isStackSlot(result) || isConstant(result) || !isCallerSave(result) : "cannot have caller-save register operands at calls"; - return result; - } - }); + info.forEachState(op, debugInfoProc); info.finish(op, frameMap); } @@ -1725,6 +1743,17 @@ int numInst = instructions.size(); boolean hasDead = false; + InstructionValueProcedure assignProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + if (isVariable(operand)) { + return colorLirOperand((Variable) operand, op.id(), mode); + } + return operand; + } + }; + for (int j = 0; j < numInst; j++) { final LIRInstruction op = instructions.get(j); if (op == null) { // this can happen when spill-moves are removed in eliminateSpillMoves @@ -1749,17 +1778,6 @@ } } - ValueProcedure assignProc = new ValueProcedure() { - - @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { - if (isVariable(operand)) { - return colorLirOperand((Variable) operand, op.id(), mode); - } - return operand; - } - }; - op.forEachInput(assignProc); op.forEachAlive(assignProc); op.forEachTemp(assignProc); @@ -1918,7 +1936,7 @@ throw new GraalInternalError(""); } - if (isVariable(i1.operand) && i1.kind() == Kind.Illegal) { + if (isVariable(i1.operand) && i1.kind().equals(LIRKind.Illegal)) { Debug.log("Interval %d has no type assigned", i1.operandNumber); Debug.log(i1.logString(this)); throw new GraalInternalError(""); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -773,7 +773,7 @@ } void initVarsForAlloc(Interval interval) { - availableRegs = allocator.frameMap.registerConfig.getAllocatableRegisters(interval.kind()); + availableRegs = allocator.frameMap.registerConfig.getAllocatableRegisters(interval.kind().getPlatformKind()); } static boolean isMove(LIRInstruction op, Interval from, Interval to) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -197,7 +197,7 @@ private void insertMove(Interval fromInterval, Interval toInterval) { assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; - assert fromInterval.kind() == toInterval.kind() : "move between different types"; + assert fromInterval.kind().equals(toInterval.kind()) : "move between different types"; assert insertIdx != -1 : "must setup insert position first"; AllocatableValue fromOpr = fromInterval.operand; @@ -209,7 +209,7 @@ } private void insertMove(Value fromOpr, Interval toInterval) { - assert fromOpr.getPlatformKind() == toInterval.kind() : "move between different types"; + assert fromOpr.getLIRKind().equals(toInterval.kind()) : "move between different types"; assert insertIdx != -1 : "must setup insert position first"; AllocatableValue toOpr = toInterval.operand; @@ -339,7 +339,7 @@ Debug.log("add move mapping from %s to %s", fromInterval, toInterval); assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; - assert fromInterval.kind() == toInterval.kind(); + assert fromInterval.kind().equals(toInterval.kind()); mappingFrom.add(fromInterval); mappingFromOpr.add(Value.ILLEGAL); mappingTo.add(toInterval); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,9 +32,9 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.phases.util.*; /** @@ -187,6 +187,38 @@ } void processOperations(List ops, final Interval[] inputState) { + InstructionValueProcedure useProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { + Interval interval = intervalAt(operand); + if (op.id() != -1) { + interval = interval.getSplitChildAtOpId(op.id(), mode, allocator); + } + + assert checkState(inputState, interval.location(), interval.splitParent()); + } + return operand; + } + }; + + InstructionValueProcedure defProc = new InstructionValueProcedure() { + + @Override + public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet flags) { + if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { + Interval interval = intervalAt(operand); + if (op.id() != -1) { + interval = interval.getSplitChildAtOpId(op.id(), mode, allocator); + } + + statePut(inputState, interval.location(), interval.splitParent()); + } + return operand; + } + }; + // visit all instructions of the block for (int i = 0; i < ops.size(); i++) { final LIRInstruction op = ops.get(i); @@ -195,38 +227,6 @@ Debug.log("%s", op.toStringWithIdPrefix()); } - ValueProcedure useProc = new ValueProcedure() { - - @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { - if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { - Interval interval = intervalAt(operand); - if (op.id() != -1) { - interval = interval.getSplitChildAtOpId(op.id(), mode, allocator); - } - - assert checkState(inputState, interval.location(), interval.splitParent()); - } - return operand; - } - }; - - ValueProcedure defProc = new ValueProcedure() { - - @Override - public Value doValue(Value operand, OperandMode mode, EnumSet flags) { - if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { - Interval interval = intervalAt(operand); - if (op.id() != -1) { - interval = interval.getSplitChildAtOpId(op.id(), mode, allocator); - } - - statePut(inputState, interval.location(), interval.splitParent()); - } - return operand; - } - }; - // check if input operands are correct op.forEachInput(useProc); // invalidate all caller save registers at calls diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -26,7 +26,6 @@ import static com.oracle.graal.compiler.GraalDebugConfig.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.lir.LIR.*; -import static com.oracle.graal.nodes.ConstantNode.*; import java.util.*; import java.util.Map.Entry; @@ -44,7 +43,6 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.gen.*; -import com.oracle.graal.lir.gen.LIRGenerator.LoadConstant; import com.oracle.graal.lir.gen.LIRGenerator.Options; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -57,19 +55,19 @@ * This class traverses the HIR instructions and generates LIR instructions from them. */ @MatchableNode(nodeClass = ConstantNode.class, shareable = true) -@MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"value"}) @MatchableNode(nodeClass = FloatSubNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = FloatingReadNode.class, inputs = {"object", "location"}) @MatchableNode(nodeClass = IfNode.class, inputs = {"condition"}) @MatchableNode(nodeClass = IntegerSubNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = LeftShiftNode.class, inputs = {"x", "y"}) -@MatchableNode(nodeClass = NarrowNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = NarrowNode.class, inputs = {"value"}) @MatchableNode(nodeClass = ReadNode.class, inputs = {"object", "location"}) @MatchableNode(nodeClass = ReinterpretNode.class, inputs = {"value"}) -@MatchableNode(nodeClass = SignExtendNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = SignExtendNode.class, inputs = {"value"}) @MatchableNode(nodeClass = UnsignedRightShiftNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = WriteNode.class, inputs = {"object", "location", "value"}) -@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"}) @MatchableNode(nodeClass = AndNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatAddNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true) @@ -135,48 +133,7 @@ if (nodeOperands == null) { return null; } - Value operand = nodeOperands.get(node); - if (operand == null) { - operand = getConstantOperand(node); - } - return operand; - } - - private Value getConstantOperand(ValueNode node) { - if (!ConstantNodeRecordsUsages) { - Constant value = node.asConstant(); - if (value != null) { - if (gen.canInlineConstant(value)) { - return setResult(node, value); - } else { - Variable loadedValue; - if (gen.getConstantLoads() == null) { - gen.setConstantLoads(new HashMap<>()); - } - LoadConstant load = gen.getConstantLoads().get(value); - assert gen.getCurrentBlock() instanceof Block; - if (load == null) { - int index = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); - loadedValue = gen.emitMove(value); - LIRInstruction op = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).get(index); - gen.getConstantLoads().put(value, new LoadConstant(loadedValue, gen.getCurrentBlock(), index, op)); - } else { - AbstractBlock dominator = ControlFlowGraph.commonDominator((Block) load.getBlock(), (Block) gen.getCurrentBlock()); - loadedValue = load.getVariable(); - if (dominator != load.getBlock()) { - load.unpin(gen.getResult().getLIR()); - } else { - assert load.getBlock() != gen.getCurrentBlock() || load.getIndex() < gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); - } - load.setBlock(dominator); - } - return loadedValue; - } - } - } else { - // Constant is loaded by ConstantNode.generate() - } - return null; + return nodeOperands.get(node); } public ValueNode valueForOperand(Value value) { @@ -252,10 +209,7 @@ if (Options.TraceLIRGeneratorLevel.getValue() >= 3) { TTY.println("LIRGen for " + instr); } - if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) { - // Loading of constants is done lazily by operand() - - } else if (instr instanceof ValueNode) { + if (instr instanceof ValueNode) { ValueNode valueNode = (ValueNode) instr; Value operand = getOperand(valueNode); if (operand == null) { @@ -418,8 +372,8 @@ append(new JumpOp(getLIRBlock(merge))); } - protected PlatformKind getPhiKind(PhiNode phi) { - return gen.getPlatformKind(phi.stamp()); + protected LIRKind getPhiKind(PhiNode phi) { + return gen.getLIRKind(phi.stamp()); } private Value operandForPhi(ValuePhiNode phi) { @@ -454,17 +408,17 @@ } private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - PlatformKind kind = gen.getPlatformKind(node.object().stamp()); - gen.emitCompareBranch(kind, operand(node.object()), kind.getDefaultValue(), Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability); + PlatformKind kind = gen.getLIRKind(node.getValue().stamp()).getPlatformKind(); + gen.emitCompareBranch(kind, operand(node.getValue()), kind.getDefaultValue(), Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability); } public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - PlatformKind kind = gen.getPlatformKind(compare.x().stamp()); - gen.emitCompareBranch(kind, operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability); + PlatformKind kind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind(); + gen.emitCompareBranch(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability); } public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - gen.emitIntegerTestBranch(operand(test.x()), operand(test.y()), trueSuccessor, falseSuccessor, trueSuccessorProbability); + gen.emitIntegerTestBranch(operand(test.getX()), operand(test.getY()), trueSuccessor, falseSuccessor, trueSuccessorProbability); } public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) { @@ -482,17 +436,17 @@ public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) { if (node instanceof IsNullNode) { IsNullNode isNullNode = (IsNullNode) node; - PlatformKind kind = gen.getPlatformKind(isNullNode.object().stamp()); - return gen.emitConditionalMove(kind, operand(isNullNode.object()), kind.getDefaultValue(), Condition.EQ, false, trueValue, falseValue); + PlatformKind kind = gen.getLIRKind(isNullNode.getValue().stamp()).getPlatformKind(); + return gen.emitConditionalMove(kind, operand(isNullNode.getValue()), kind.getDefaultValue(), Condition.EQ, false, trueValue, falseValue); } else if (node instanceof CompareNode) { CompareNode compare = (CompareNode) node; - PlatformKind kind = gen.getPlatformKind(compare.x().stamp()); - return gen.emitConditionalMove(kind, operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); + PlatformKind kind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind(); + return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); } else if (node instanceof LogicConstantNode) { return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue); } else if (node instanceof IntegerTestNode) { IntegerTestNode test = (IntegerTestNode) node; - return gen.emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue); + return gen.emitIntegerTestMove(operand(test.getX()), operand(test.getY()), trueValue, falseValue); } else { throw GraalInternalError.unimplemented(node.toString()); } @@ -573,7 +527,7 @@ if (keyCount == 1) { assert defaultTarget != null; double probability = x.probability(x.keySuccessor(0)); - PlatformKind kind = gen.getPlatformKind(x.value().stamp()); + PlatformKind kind = gen.getLIRKind(x.value().stamp()).getPlatformKind(); gen.emitCompareBranch(kind, gen.load(operand(x.value())), x.keyAt(0), Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability); } else { LabelRef[] keyTargets = new LabelRef[keyCount]; @@ -647,26 +601,6 @@ gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability); } - public final void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length) { - gen.emitArrayEquals(kind, result, array1, array2, length); - } - - public final Variable newVariable(Kind i) { - return gen.newVariable(i); - } - - public final void emitBitCount(Variable result, Value operand) { - gen.emitBitCount(result, operand); - } - - public final void emitBitScanForward(Variable result, Value operand) { - gen.emitBitScanForward(result, operand); - } - - final void emitBitScanReverse(Variable result, Value operand) { - gen.emitBitScanReverse(result, operand); - } - @Override public LIRGeneratorTool getLIRGeneratorTool() { return gen; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -231,7 +231,7 @@ private void moveToTemp(Value src) { assert isIllegal(temp); - temp = gen.newVariable(src.getPlatformKind()); + temp = gen.newVariable(src.getLIRKind()); emitMove(temp, src); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -37,7 +37,7 @@ * This is the Value of a node which was matched as part of a complex match. The value isn't * actually useable but this marks it as having been evaluated. */ - @SuppressWarnings("serial") public static Value INTERIOR_MATCH = new Value(Kind.Illegal) { + @SuppressWarnings("serial") public static final Value INTERIOR_MATCH = new Value(LIRKind.Illegal) { @Override public String toString() { @@ -54,7 +54,7 @@ final ComplexMatchResult result; public ComplexMatchValue(ComplexMatchResult result) { - super(Kind.Illegal); + super(LIRKind.Illegal); this.result = result; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Mon Jun 30 12:02:19 2014 +0200 @@ -219,18 +219,20 @@ */ private static final boolean DEBUG = false; - private static final String LOGFILE = new File(System.getProperty("java.io.tmpdir"), "matchprocessor.log").getPath(); - - private static PrintWriter log; + private PrintWriter log; /** - * Logging facility for the debugging the annotation processor. + * Logging facility for debugging the annotation processor. */ - private static synchronized PrintWriter getLog() { + private PrintWriter getLog() { if (log == null) { try { - log = new PrintWriter(new FileWriter(LOGFILE, true)); + // Create the log file within the generated source directory so it's easy to find. + // /tmp isn't platform independent and java.io.tmpdir can map anywhere, particularly + // on the mac. + FileObject file = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", getClass().getSimpleName() + "log"); + log = new PrintWriter(new FileWriter(file.toUri().getPath(), true)); } catch (IOException e) { // Do nothing } @@ -238,7 +240,7 @@ return log; } - private static synchronized void logMessage(String format, Object... args) { + private void logMessage(String format, Object... args) { if (!DEBUG) { return; } @@ -249,7 +251,7 @@ } } - private static synchronized void logException(Throwable t) { + private void logException(Throwable t) { if (!DEBUG) { return; } @@ -265,9 +267,11 @@ * throws as errors. */ private void reportExceptionThrow(Element element, Throwable t) { - logMessage("throw for %s:\n", element); + if (element != null) { + logMessage("throw for %s:\n", element); + } logException(t); - processingEnv.getMessager().printMessage(Kind.ERROR, "Exception throw during processing: " + t.toString() + " " + Arrays.toString(Arrays.copyOf(t.getStackTrace(), 4)), element); + errorMessage(element, "Exception throw during processing: %s %s", t, Arrays.toString(Arrays.copyOf(t.getStackTrace(), 4))); } static class TypeDescriptor { @@ -334,7 +338,7 @@ * The mapping between elements with MatchRules and the wrapper class used invoke the code * generation after the match. */ - private Map invokers = new LinkedHashMap<>(); + private Map invokers = new LinkedHashMap<>(); private TypeDescriptor valueType; @@ -564,7 +568,7 @@ try { createProviderFile(pkg, matchStatementClassName, originatingElements); } catch (IOException e) { - processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType); + reportExceptionThrow(info.topDeclaringType, e); } } @@ -608,7 +612,7 @@ * @return a string which will construct the MatchStatement instance to match this pattern. */ public String ruleBuilder() { - return String.format("new MatchStatement(\"%s\", %s, %s.instance, %s)", invoker.name, matchPattern, invoker.wrapperClass(), invoker.argumentsListName()); + return String.format("new MatchStatement(\"%s\", %s, %s.instance, %s)", invoker.methodName, matchPattern, invoker.wrapperClass(), invoker.argumentsListName()); } } @@ -616,15 +620,15 @@ * Used to generate the wrapper class to invoke the code generation method. */ static class MethodInvokerItem { - final String name; + final String methodName; final String nodeLIRBuilderClass; - final String methodName; + final ExecutableElement method; final List fields; - MethodInvokerItem(String name, String nodeLIRBuilderClass, String methodName, List fields) { - this.name = name; + MethodInvokerItem(String methodName, String nodeLIRBuilderClass, ExecutableElement method, List fields) { + this.methodName = methodName; this.nodeLIRBuilderClass = nodeLIRBuilderClass; - this.methodName = methodName; + this.method = method; this.fields = fields; } @@ -672,6 +676,7 @@ if (roundEnv.processingOver()) { return true; } + logMessage("Starting round %s\n", roundEnv); matchRulesTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchRules.class.getCanonicalName()).asType(); matchRuleTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchRule.class.getCanonicalName()).asType(); @@ -679,7 +684,16 @@ matchableNodeTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchableNode.class.getCanonicalName()).asType(); matchableNodesTypeMirror = processingEnv.getElementUtils().getTypeElement(MatchableNodes.class.getCanonicalName()).asType(); + Element currentElement = null; try { + for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNode.class)) { + logMessage("%s\n", element); + processMatchableNode(element); + } + for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNodes.class)) { + logMessage("%s\n", element); + processMatchableNode(element); + } // Define a TypeDescriptor for the generic node but don't enter it into the nodeTypes // table since it shouldn't be mentioned in match rules. TypeMirror valueTypeMirror = processingEnv.getElementUtils().getTypeElement(ValueNode.class.getName()).asType(); @@ -688,18 +702,21 @@ Map map = new LinkedHashMap<>(); for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) { + currentElement = element; processMatchRule(map, element, findAnnotationMirror(element, matchRuleTypeMirror)); } for (Element element : roundEnv.getElementsAnnotatedWith(MatchRules.class)) { + currentElement = element; processMatchRule(map, element, findAnnotationMirror(element, matchRulesTypeMirror)); } + currentElement = null; for (MatchRuleDescriptor info : map.values()) { createFiles(info); } } catch (Throwable t) { - processingEnv.getMessager().printMessage(Kind.ERROR, "Exception throw during processing: " + t.toString() + " " + Arrays.toString(Arrays.copyOf(t.getStackTrace(), 2))); + reportExceptionThrow(currentElement, t); } return true; @@ -754,7 +771,12 @@ } else { nodeClass = nodeClassMirror.toString(); } - nodePackage = findPackage(processingEnv.getElementUtils().getTypeElement(nodeClass)); + TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(nodeClass); + if (typeElement == null) { + errorMessage(element, mirror, "Class \"%s\" cannot be resolved to a type", nodeClass); + return; + } + nodePackage = findPackage(typeElement); assert nodeClass.startsWith(nodePackage); nodeClass = nodeClass.substring(nodePackage.length() + 1); assert nodeClass.endsWith("Node"); @@ -776,8 +798,7 @@ current = (TypeElement) typeUtils.asElement(theSuper); } if (!ok) { - String msg = String.format("Input named \"%s\" doesn't exist in %s", input, nodeClassElement.getSimpleName()); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, element, mirror); + errorMessage(element, mirror, "Input named \"%s\" doesn't exist in %s", input, nodeClassElement.getSimpleName()); } } @@ -853,21 +874,18 @@ Types typeUtils = typeUtils(); if (!method.getModifiers().contains(Modifier.PUBLIC)) { - String msg = String.format("MatchRule method %s must be public", method.getSimpleName()); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, method); + errorMessage(method, "MatchRule method %s must be public", method.getSimpleName()); return; } if (method.getModifiers().contains(Modifier.STATIC)) { - String msg = String.format("MatchRule method %s must be non-static", method.getSimpleName()); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, method); + errorMessage(method, "MatchRule method %s must be non-static", method.getSimpleName()); return; } try { TypeMirror returnType = method.getReturnType(); if (!typeUtils.isSameType(returnType, processingEnv.getElementUtils().getTypeElement(ComplexMatchResult.class.getName()).asType())) { - String msg = String.format("MatchRule method return type must be %s", ComplexMatchResult.class.getName()); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, method); + errorMessage(method, "MatchRule method return type must be %s", ComplexMatchResult.class.getName()); return; } @@ -877,8 +895,7 @@ ArrayList expectedNames = parser.capturedNames(); List actualParameters = method.getParameters(); if (expectedTypes.size() + 1 < actualParameters.size()) { - String msg = String.format("Too many arguments for match method %s %s", expectedTypes.size() + 1, actualParameters.size()); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, method); + errorMessage(method, "Too many arguments for match method %s != %s", expectedTypes.size() + 1, actualParameters.size()); return; } @@ -889,22 +906,26 @@ String name = parameter.getSimpleName().toString(); int nameIndex = expectedNames.indexOf(name); if (nameIndex == -1) { - String msg = String.format("Argument \"%s\" isn't captured in the match rule", name); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, method); + errorMessage(method, "Argument \"%s\" isn't captured in the match rule", name); return; } TypeMirror type = parameter.asType(); if (!typeUtils.isAssignable(expectedTypes.get(nameIndex).mirror, type)) { - String msg = String.format("Captured value \"%s\" of type %s is not assignable to argument of type %s", name, expectedTypes.get(nameIndex).mirror, type); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, method); + errorMessage(method, "Captured value \"%s\" of type %s is not assignable to argument of type %s", name, expectedTypes.get(nameIndex).mirror, type); return; } } - MethodInvokerItem invoker = invokers.get(method); + String methodName = method.getSimpleName().toString(); + MethodInvokerItem invoker = invokers.get(methodName); if (invoker == null) { - invoker = new MethodInvokerItem(method.getSimpleName().toString(), topDeclaringType(method).getSimpleName().toString(), method.getSimpleName().toString(), actualParameters); - invokers.put(method, invoker); + invoker = new MethodInvokerItem(methodName, topDeclaringType(method).getSimpleName().toString(), method, actualParameters); + invokers.put(methodName, invoker); + } else if (invoker.method != method) { + // This could be supported but it's easier if they are unique since the names + // are used in log output and snippet counters. + errorMessage(method, "Use unique method names for match methods."); + return; } Element enclosing = method.getEnclosingElement(); @@ -915,8 +936,7 @@ while (enclosing != null) { if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { if (enclosing.getModifiers().contains(Modifier.PRIVATE)) { - String msg = String.format("MatchRule cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing); - processingEnv.getMessager().printMessage(Kind.ERROR, msg, method); + errorMessage(method, "MatchRule cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing); return; } originatingElementsList.add(enclosing); @@ -938,10 +958,18 @@ info.matchRules.add(new MatchRuleItem(match, invoker)); } } catch (RuleParseError e) { - processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), method, mirror); + errorMessage(method, mirror, e.getMessage()); } } + private void errorMessage(Element element, String format, Object... args) { + processingEnv.getMessager().printMessage(Kind.ERROR, String.format(format, args), element); + } + + private void errorMessage(Element element, AnnotationMirror mirror, String format, Object... args) { + processingEnv.getMessager().printMessage(Kind.ERROR, String.format(format, args), element, mirror); + } + // TODO borrowed from com.oracle.truffle.dsl.processor.Utils @SuppressWarnings("unchecked") private static List getAnnotationValueList(Class expectedListType, AnnotationMirror mirror, String name) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Mon Jun 30 12:02:19 2014 +0200 @@ -68,9 +68,6 @@ for (int i = 0; i < names.length; i++) { for (NodeClass.Position position : nodeClass.getFirstLevelInputPositions()) { String name = nodeClass.getName(position); - if (name.endsWith("#NDF")) { - name = name.substring(0, name.length() - 4); - } if (name.equals(names[i])) { result[i] = position; break; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Jun 30 12:02:19 2014 +0200 @@ -86,6 +86,33 @@ return ENABLED && DebugScope.getInstance().isDumpEnabled(); } + /** + * Determines if verification is enabled in the current method, regardless of the + * {@linkplain Debug#currentScope() current debug scope}. + * + * @see Debug#verify(Object, Object) + */ + public static boolean isVerifyEnabledForMethod() { + if (!ENABLED) { + return false; + } + DebugConfig config = DebugScope.getConfig(); + if (config == null) { + return false; + } + return config.isVerifyEnabledForMethod(); + } + + /** + * Determines if verification is enabled in the {@linkplain Debug#currentScope() current debug + * scope}. + * + * @see Debug#verify(Object, Object) + */ + public static boolean isVerifyEnabled() { + return ENABLED && DebugScope.getInstance().isVerifyEnabled(); + } + public static boolean isMeterEnabled() { return ENABLED && DebugScope.getInstance().isMeterEnabled(); } @@ -460,6 +487,51 @@ } /** + * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig() + * config} to perform verification on a given object. + * + * @param object object to verify + * @param context object describing the context of verification + * + * @see DebugVerifyHandler#verify(Object, Object...) + */ + public static void verify(Object object, Object context) { + if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { + DebugScope.getInstance().verify(object, context); + } + } + + /** + * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig() + * config} to perform verification on a given object. + * + * @param object object to verify + * @param context1 first object describing the context of verification + * @param context2 second object describing the context of verification + * + * @see DebugVerifyHandler#verify(Object, Object...) + */ + public static void verify(Object object, Object context1, Object context2) { + if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { + DebugScope.getInstance().verify(object, context1, context2); + } + } + + /** + * This override exists to catch cases when {@link #verify(Object, Object)} is called with one + * argument bound to a varargs method parameter. It will bind to this method instead of the + * single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public static void verify(Object object, Object[] args) { + assert false : "shouldn't use this"; + if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { + DebugScope.getInstance().verify(object, args); + } + } + + /** * Opens a new indentation level (by adding some spaces) based on the current indentation level. * This should be used in a {@linkplain Indent try-with-resources} pattern. * @@ -773,11 +845,11 @@ } public static DebugConfig silentConfig() { - return fixedConfig(false, false, false, false, false, Collections. emptyList(), System.out); + return fixedConfig(false, false, false, false, false, false, Collections. emptyList(), Collections. emptyList(), System.out); } public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled, - final Collection dumpHandlers, final PrintStream output) { + final boolean isVerifyEnabled, final Collection dumpHandlers, final Collection verifyHandlers, final PrintStream output) { return new DebugConfig() { @Override @@ -809,6 +881,15 @@ } @Override + public boolean isVerifyEnabled() { + return isVerifyEnabled; + } + + public boolean isVerifyEnabledForMethod() { + return isVerifyEnabled; + } + + @Override public boolean isTimeEnabled() { return isTimerEnabled; } @@ -824,6 +905,11 @@ } @Override + public Collection verifyHandlers() { + return verifyHandlers; + } + + @Override public PrintStream output() { return output; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -69,6 +69,16 @@ boolean isDumpEnabledForMethod(); /** + * @see Debug#isVerifyEnabled() + */ + boolean isVerifyEnabled(); + + /** + * @see Debug#isVerifyEnabledForMethod() + */ + boolean isVerifyEnabledForMethod(); + + /** * Adds an object the context used by this configuration to do filtering. */ void addToContext(Object o); @@ -94,9 +104,14 @@ RuntimeException interceptException(Throwable e); /** - * Gets the modifiable collection dump handlers registered with this configuration. + * Gets the modifiable collection of dump handlers registered with this configuration. */ Collection dumpHandlers(); PrintStream output(); + + /** + * Gets the modifiable collection of verify handlers registered with this configuration. + */ + Collection verifyHandlers(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugVerifyHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugVerifyHandler.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,55 @@ +/* + * 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.graal.debug; + +/** + * Performs some kind of verification on an object. + */ +public interface DebugVerifyHandler { + + /** + * Verifies that a given object satisfies some invariants. + * + * @param object object to verify + * @param context object(s) describing the context of verification + */ + void verify(Object object, Object... context); + + /** + * Extracts the first object of a given type from a verification input object. + */ + default T extract(Class type, Object input) { + if (type.isInstance(input)) { + return type.cast(input); + } + if (input instanceof Object[]) { + for (Object nestedContext : (Object[]) input) { + T object = extract(type, nestedContext); + if (object != null) { + return object; + } + } + } + return null; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -55,6 +55,14 @@ */ DUMP_METHOD, /** + * @see Debug#isVerifyEnabled() + */ + VERIFY, + /** + * @see Debug#isVerifyEnabledForMethod() + */ + VERIFY_METHOD, + /** * @see Debug#isMeterEnabled() */ METER, @@ -155,6 +163,23 @@ } @Override + public boolean isVerifyEnabled() { + Boolean fs = featureState.get(Feature.VERIFY); + if (fs == null) { + return delegate.isVerifyEnabled(); + } + return fs.booleanValue(); + } + + public boolean isVerifyEnabledForMethod() { + Boolean fs = featureState.get(Feature.VERIFY_METHOD); + if (fs == null) { + return delegate.isVerifyEnabledForMethod(); + } + return fs.booleanValue(); + } + + @Override public boolean isTimeEnabled() { Boolean fs = featureState.get(Feature.TIME); if (fs == null) { @@ -178,6 +203,11 @@ } @Override + public Collection verifyHandlers() { + return delegate.verifyHandlers(); + } + + @Override public PrintStream output() { return delegate.output(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Mon Jun 30 12:02:19 2014 +0200 @@ -95,6 +95,7 @@ private boolean timeEnabled; private boolean memUseTrackingEnabled; private boolean dumpEnabled; + private boolean verifyEnabled; private boolean logEnabled; private PrintStream output; @@ -158,6 +159,10 @@ return dumpEnabled; } + public boolean isVerifyEnabled() { + return verifyEnabled; + } + public boolean isLogEnabled() { return logEnabled; } @@ -213,6 +218,20 @@ } /** + * @see Debug#verify(Object, Object) + */ + public void verify(Object object, Object... ctx) { + if (isVerifyEnabled()) { + DebugConfig config = getConfig(); + if (config != null) { + for (DebugVerifyHandler handler : config.verifyHandlers()) { + handler.verify(object, ctx); + } + } + } + } + + /** * Creates and enters a new debug scope which is either a child of the current scope or a * disjoint top level scope. * @@ -269,6 +288,7 @@ memUseTrackingEnabled = false; timeEnabled = false; dumpEnabled = false; + verifyEnabled = false; // Be pragmatic: provide a default log stream to prevent a crash if the stream is not // set while logging @@ -278,6 +298,7 @@ memUseTrackingEnabled = config.isMemUseTrackingEnabled(); timeEnabled = config.isTimeEnabled(); dumpEnabled = config.isDumpEnabled(); + verifyEnabled = config.isVerifyEnabled(); logEnabled = config.isLogEnabled(); output = config.output(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Mon Jun 30 12:02:19 2014 +0200 @@ -57,8 +57,8 @@ private final DebugValue flat; public MemUseTrackerImpl(String name) { - super(name + "_Accm", false); - this.flat = new DebugValue(name + "_Flat", false) { + super(name + "_Accm", true); + this.flat = new DebugValue(name + "_Flat", true) { @Override public String toString(long value) { @@ -69,7 +69,7 @@ @Override public Closeable start() { - if (!isConditional() || Debug.isTimeEnabled()) { + if (!isConditional() || Debug.isMemUseTrackingEnabled()) { CloseableImpl result = new CloseableImpl(); currentTracker.set(result); return result; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java --- a/graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java Mon Jun 30 12:02:19 2014 +0200 @@ -44,6 +44,7 @@ private StructuredGraph hostGraph; private int[] oopMapArray; + private boolean usesAllocation; /** * Set the address for the point of entry to the external compilation result. @@ -86,4 +87,12 @@ return oopMapArray; } + public void setUsesAllocationFlag(boolean val) { + usesAllocation = val; + } + + public boolean getUsesAllocationFlag() { + return usesAllocation; + } + } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,6 +28,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.GraphEvent.NodeEvent; import com.oracle.graal.graph.Node.ValueNumberable; +import com.oracle.graal.graph.NodeClass.NodeClassIterator; +import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.graph.iterators.*; /** @@ -72,8 +74,7 @@ */ int compressions; - NodeChangedListener inputChangedListener; - NodeChangedListener usagesDroppedToZeroListener; + NodeEventListener nodeEventListener; private final HashMap cachedNodes = new HashMap<>(); /* @@ -279,64 +280,118 @@ return add(node); } + public T addOrUniqueWithInputs(T node) { + NodeClassIterator iterator = node.inputs().iterator(); + while (iterator.hasNext()) { + Position pos = iterator.nextPosition(); + Node input = pos.get(node); + if (input != null && !input.isAlive()) { + assert !input.isDeleted(); + pos.initialize(node, addOrUniqueWithInputs(input)); + } + } + if (node.getNodeClass().valueNumberable()) { + return uniqueHelper(node, true); + } + return add(node); + } + private T addHelper(T node) { node.initialize(this); return node; } - public interface NodeChangedListener { + /** + * Client interested in one or more node related events. + */ + public interface NodeEventListener { + + /** + * Notifies this listener of a change in a node's inputs. + * + * @param node a node who has had one of its inputs changed + */ + default void inputChanged(Node node) { + } - void nodeChanged(Node node); + /** + * Notifies this listener of a node becoming unused. + * + * @param node a node whose {@link Node#usages()} just became empty + */ + default void usagesDroppedToZero(Node node) { + } + + /** + * Notifies this listener of an added node. + * + * @param node a node that was just added to the graph + */ + default void nodeAdded(Node node) { + } } - private static class ChainedNodeChangedListener implements NodeChangedListener { + /** + * Registers a given {@link NodeEventListener} with the enclosing graph until this object is + * {@linkplain #close() closed}. + */ + public final class NodeEventScope implements AutoCloseable { + NodeEventScope(NodeEventListener listener) { + if (nodeEventListener == null) { + nodeEventListener = listener; + } else { + nodeEventListener = new ChainedNodeEventListener(listener, nodeEventListener); + } + } - NodeChangedListener head; - NodeChangedListener next; + public void close() { + assert nodeEventListener != null; + if (nodeEventListener instanceof ChainedNodeEventListener) { + nodeEventListener = ((ChainedNodeEventListener) nodeEventListener).next; + } else { + nodeEventListener = null; + } + } + } - ChainedNodeChangedListener(NodeChangedListener head, NodeChangedListener next) { + private static class ChainedNodeEventListener implements NodeEventListener { + + NodeEventListener head; + NodeEventListener next; + + ChainedNodeEventListener(NodeEventListener head, NodeEventListener next) { this.head = head; this.next = next; } - public void nodeChanged(Node node) { - head.nodeChanged(node); - next.nodeChanged(node); + public void nodeAdded(Node node) { + head.nodeAdded(node); + next.nodeAdded(node); } - } - public void trackInputChange(NodeChangedListener listener) { - if (inputChangedListener == null) { - inputChangedListener = listener; - } else { - inputChangedListener = new ChainedNodeChangedListener(listener, inputChangedListener); + public void inputChanged(Node node) { + head.inputChanged(node); + next.inputChanged(node); + } + + public void usagesDroppedToZero(Node node) { + head.inputChanged(node); + next.inputChanged(node); } } - public void stopTrackingInputChange() { - assert inputChangedListener != null; - if (inputChangedListener instanceof ChainedNodeChangedListener) { - inputChangedListener = ((ChainedNodeChangedListener) inputChangedListener).next; - } else { - inputChangedListener = null; - } - } - - public void trackUsagesDroppedZero(NodeChangedListener listener) { - if (usagesDroppedToZeroListener == null) { - usagesDroppedToZeroListener = listener; - } else { - usagesDroppedToZeroListener = new ChainedNodeChangedListener(listener, usagesDroppedToZeroListener); - } - } - - public void stopTrackingUsagesDroppedZero() { - assert usagesDroppedToZeroListener != null; - if (usagesDroppedToZeroListener instanceof ChainedNodeChangedListener) { - usagesDroppedToZeroListener = ((ChainedNodeChangedListener) usagesDroppedToZeroListener).next; - } else { - usagesDroppedToZeroListener = null; - } + /** + * Registers a given {@link NodeEventListener} with this graph. This should be used in + * conjunction with try-with-resources statement as follows: + * + *
+     * try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
+     *     // make changes to the graph
+     * }
+     * 
+ */ + public NodeEventScope trackNodeEvents(NodeEventListener listener) { + return new NodeEventScope(listener); } /** @@ -461,6 +516,14 @@ int getValue() { return value; } + + /** + * Determines if this mark still represents the {@linkplain Graph#getNodeCount() live node + * count} of the graph. + */ + public boolean isCurrent() { + return value == graph.nodeIdCount(); + } } /** @@ -785,6 +848,9 @@ } node.id = id; + if (nodeEventListener != null) { + nodeEventListener.nodeAdded(node); + } logNodeAdded(node); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Jun 30 12:02:19 2014 +0200 @@ -27,7 +27,6 @@ import java.lang.annotation.*; import java.util.*; -import com.oracle.graal.graph.Graph.NodeChangedListener; import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.graph.iterators.*; @@ -559,12 +558,13 @@ assert assertTrue(result, "not found in usages, old input: %s", oldInput); } } + maybeNotifyInputChanged(this); if (newInput != null) { if (newInput.recordsUsages()) { - maybeNotifyChanged(this); newInput.addUsage(this); } - } else if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) { + } + if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) { maybeNotifyZeroInputs(oldInput); } } @@ -628,7 +628,7 @@ boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); assert assertTrue(result, "not found in inputs, usage: %s", usage); if (other != null) { - maybeNotifyChanged(usage); + maybeNotifyInputChanged(usage); if (other.recordsUsages()) { other.addUsage(usage); } @@ -650,7 +650,7 @@ boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); assert assertTrue(result, "not found in inputs, usage: %s", usage); if (other != null) { - maybeNotifyChanged(usage); + maybeNotifyInputChanged(usage); if (other.recordsUsages()) { other.addUsage(usage); } @@ -684,22 +684,22 @@ } } - private void maybeNotifyChanged(Node usage) { + private void maybeNotifyInputChanged(Node node) { if (graph != null) { assert !graph.isFrozen(); - NodeChangedListener listener = graph.inputChangedListener; + NodeEventListener listener = graph.nodeEventListener; if (listener != null) { - listener.nodeChanged(usage); + listener.inputChanged(node); } } } - private void maybeNotifyZeroInputs(Node oldInput) { + private void maybeNotifyZeroInputs(Node node) { if (graph != null) { assert !graph.isFrozen(); - NodeChangedListener listener = graph.usagesDroppedToZeroListener; + NodeEventListener listener = graph.nodeEventListener; if (listener != null) { - listener.nodeChanged(oldInput); + listener.usagesDroppedToZero(node); } } } @@ -735,9 +735,7 @@ } } - public void clearInputs() { - assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); - + private void unregisterInputs() { for (Node input : inputs()) { if (input.recordsUsages()) { removeThisFromUsages(input); @@ -746,6 +744,12 @@ } } } + } + + public void clearInputs() { + assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); + + unregisterInputs(); getNodeClass().clearInputs(this); } @@ -753,13 +757,17 @@ return n.removeUsage(this); } - public void clearSuccessors() { - assert assertFalse(isDeleted(), "cannot clear successors of deleted node"); - + private void unregisterSuccessors() { for (Node successor : successors()) { assert assertTrue(successor.predecessor == this, "wrong predecessor in old successor (%s): %s", successor, successor.predecessor); successor.predecessor = null; } + } + + public void clearSuccessors() { + assert assertFalse(isDeleted(), "cannot clear successors of deleted node"); + + unregisterSuccessors(); getNodeClass().clearSuccessors(this); } @@ -777,8 +785,8 @@ */ public void safeDelete() { assert checkDeletion(); - clearInputs(); - clearSuccessors(); + unregisterInputs(); + unregisterSuccessors(); graph.unregister(this); id = DELETED_ID_START - id; assert isDeleted(); @@ -801,17 +809,6 @@ } /** - * Must be overridden by subclasses that implement {@link Canonicalizable}. The implementation - * in {@link Node} exists to obviate the need to cast a node before invoking - * {@link Canonicalizable#canonical(CanonicalizerTool)}. - * - * @param tool - */ - public Node canonical(CanonicalizerTool tool) { - throw new UnsupportedOperationException(); - } - - /** * Must be overridden by subclasses that implement {@link Simplifiable}. The implementation in * {@link Node} exists to obviate the need to cast a node before invoking * {@link Simplifiable#simplify(SimplifierTool)}. diff -r 51f392557124 -r 5f01f7c48d40 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 Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -116,7 +116,12 @@ public NodeClass(Class clazz, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { super(clazz); assert NODE_CLASS.isAssignableFrom(clazz); + this.isCanonicalizable = Canonicalizable.class.isAssignableFrom(clazz); + if (Canonicalizable.Unary.class.isAssignableFrom(clazz) || Canonicalizable.Binary.class.isAssignableFrom(clazz)) { + assert Canonicalizable.Unary.class.isAssignableFrom(clazz) ^ Canonicalizable.Binary.class.isAssignableFrom(clazz) : clazz + " should implement either Unary or Binary, not both"; + } + this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz); FieldScanner scanner = new FieldScanner(calcOffset); @@ -298,9 +303,6 @@ } types.put(offset, inputAnnotation.value()); names.put(offset, field.getName()); - if (inputAnnotation.value() != InputType.Value) { - fieldNames.put(offset, field.getName() + "#NDF"); - } } else if (field.isAnnotationPresent(Node.Successor.class)) { if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) { GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should be final", field); @@ -380,6 +382,10 @@ node.getNodeClass().set(node, this, value); } + void initialize(Node node, Node value) { + node.getNodeClass().initializePosition(node, this, value); + } + public boolean isValidFor(Node node, Node from) { return node.getNodeClass().isValid(this, from.getNodeClass()); } @@ -1069,6 +1075,20 @@ } } + public void initializePosition(Node node, Position pos, Node x) { + long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; + if (pos.getSubIndex() == NOT_ITERABLE) { + assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")"; + putNode(node, offset, x); + } else { + NodeList list = getNodeList(node, offset); + while (list.size() <= pos.getSubIndex()) { + list.add(null); + } + list.initialize(pos.getSubIndex(), x); + } + } + public NodeClassIterable getInputIterable(final Node node) { assert getClazz().isInstance(node); return new NodeClassIterable() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,6 +49,12 @@ this.self = self; } + public NodeInputList(Node self, Collection elements) { + super(elements); + assert self.usages().isEmpty(); + this.self = self; + } + @Override protected void update(T oldNode, T newNode) { self.updateUsages(oldNode, newNode); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Mon Jun 30 12:02:19 2014 +0200 @@ -77,6 +77,24 @@ } } + protected NodeList(Collection elements) { + if (elements == null || elements.isEmpty()) { + this.size = 0; + this.nodes = EMPTY_NODE_ARRAY; + this.initialSize = 0; + } else { + this.size = elements.size(); + this.initialSize = elements.size(); + this.nodes = new Node[elements.size()]; + int i = 0; + for (NodeInterface n : elements) { + this.nodes[i] = n.asNode(); + assert this.nodes[i] == null || !this.nodes[i].isDeleted(); + i++; + } + } + } + protected abstract void update(T oldNode, T newNode); @Override @@ -136,6 +154,12 @@ return oldValue; } + void initialize(int index, T node) { + incModCount(); + assert index < size(); + nodes[index] = node; + } + void copy(NodeList other) { incModCount(); nodes = Arrays.copyOf(other.nodes, other.size); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java Mon Jun 30 12:02:19 2014 +0200 @@ -50,6 +50,8 @@ public abstract void add(Node node); + public abstract boolean contains(Node node); + private abstract class QueueConsumingIterator implements Iterator { protected void dropDeleted() { @@ -140,6 +142,20 @@ } } + @Override + public boolean contains(Node node) { + if (inQueue != null) { + return inQueue.isMarked(node); + } else { + for (Node queuedNode : worklist) { + if (queuedNode == node) { + return true; + } + } + return false; + } + } + private boolean checkInfiniteWork(Node node) { if (lastPull == node) { if (firstNoChange == null) { @@ -186,6 +202,11 @@ } @Override + public boolean contains(Node node) { + return visited.isMarked(node); + } + + @Override public Iterator iterator() { return new QueueConsumingIterator() { @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -22,9 +22,110 @@ */ package com.oracle.graal.graph.spi; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +/** + * Nodes can implement {@link Canonicalizable} or one of the two sub-interfaces {@link Unary} and + * {@link Binary} to provide local optimizations like constant folding and strength reduction. + * Implementations should return a replacement that is always semantically correct for the given + * inputs, or "this" if they do not see an opportunity for improvement.
+ *
+ * Implementations of {@link Canonicalizable#canonical(CanonicalizerTool)} or the equivalent + * methods of the two sub-interfaces must not have any side effects.
+ * They are not allowed to change inputs, successors or properties of any node (including the + * current one) and they also cannot add new nodes to the graph.
+ *
+ * In addition to pre-existing nodes they can return newly created nodes, which will be added to the + * graph automatically if (and only if) the effects of the canonicalization are committed. + * Non-cyclic graphs (DAGs) of newly created nodes (i.e., one newly created node with an input to + * another newly created node) will be handled correctly. + */ public interface Canonicalizable { + /** + * Implementations of this method can provide local optimizations like constant folding and + * strength reduction. Implementations should look at the properties and inputs of the current + * node and determine if there is a more optimal and always semantically correct replacement.
+ * The return value determines the effect that the canonicalization will have: + *
    + *
  • Returning an pre-existing node will replace the current node with the given one.
  • + *
  • Returning a newly created node (that was not yet added to the graph) will replace the + * current node with the given one, after adding it to the graph. If both the replacement and + * the replacee are anchored in control flow (fixed nodes), the replacement will be added to the + * control flow. It is invalid to replace a non-fixed node with a newly created fixed node + * (because its placement in the control flow cannot be determined without scheduling).
  • + *
  • Returning {@code null} will delete the current node and replace it with {@code null} at + * all usages. Note that it is not necessary to delete floating nodes that have no more usages + * this way - they will be deleted automatically.
  • + *
+ * + * @param tool provides access to runtime interfaces like {@link MetaAccessProvider} + */ Node canonical(CanonicalizerTool tool); + + /** + * This sub-interface of {@link Canonicalizable} is intended for nodes that have exactly one + * input. It has an additional {@link #canonical(CanonicalizerTool, Node)} method that looks at + * the given input instead of the current input of the node - which can be used to ask + * "what if this input is change to this node" - questions. + * + * @param the common supertype of all inputs of this node + */ + public interface Unary extends Canonicalizable { + + /** + * Similar to {@link Canonicalizable#canonical(CanonicalizerTool)}, except that + * implementations should act as if the current input of the node was the given one, i.e., + * they should never look at the inputs via the this pointer. + */ + Node canonical(CanonicalizerTool tool, T forValue); + + /** + * Gets the current value of the input, so that calling + * {@link #canonical(CanonicalizerTool, Node)} with the value returned from this method + * should behave exactly like {@link Canonicalizable#canonical(CanonicalizerTool)}. + */ + T getValue(); + + default Node canonical(CanonicalizerTool tool) { + return canonical(tool, getValue()); + } + } + + /** + * This sub-interface of {@link Canonicalizable} is intended for nodes that have exactly two + * inputs. It has an additional {@link #canonical(CanonicalizerTool, Node, Node)} method that + * looks at the given inputs instead of the current inputs of the node - which can be used to + * ask "what if this input is change to this node" - questions. + * + * @param the common supertype of all inputs of this node + */ + public interface Binary extends Canonicalizable { + + /** + * Similar to {@link Canonicalizable#canonical(CanonicalizerTool)}, except that + * implementations should act as if the current input of the node was the given one, i.e., + * they should never look at the inputs via the this pointer. + */ + Node canonical(CanonicalizerTool tool, T forX, T forY); + + /** + * Gets the current value of the input, so that calling + * {@link #canonical(CanonicalizerTool, Node, Node)} with the value returned from this + * method should behave exactly like {@link Canonicalizable#canonical(CanonicalizerTool)}. + */ + T getX(); + + /** + * Gets the current value of the input, so that calling + * {@link #canonical(CanonicalizerTool, Node, Node)} with the value returned from this + * method should behave exactly like {@link Canonicalizable#canonical(CanonicalizerTool)}. + */ + T getY(); + + default Node canonical(CanonicalizerTool tool) { + return canonical(tool, getX(), getY()); + } + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/CanonicalizerTool.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/CanonicalizerTool.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/CanonicalizerTool.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -24,7 +24,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; public interface CanonicalizerTool { @@ -35,6 +34,4 @@ ConstantReflectionProvider getConstantReflection(); boolean canonicalizeReads(); - - void removeIfUnused(Node node); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/DefaultCanonicalizerTool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/DefaultCanonicalizerTool.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011, 2014, 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.graph.spi; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +public class DefaultCanonicalizerTool implements CanonicalizerTool { + + private final Assumptions assumptions; + private final MetaAccessProvider metaAccess; + private final ConstantReflectionProvider constantReflection; + private final boolean canonicalizeReads; + + public DefaultCanonicalizerTool(Assumptions assumptions, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean canonicalizeReads) { + this.assumptions = assumptions; + this.metaAccess = metaAccess; + this.constantReflection = constantReflection; + this.canonicalizeReads = canonicalizeReads; + } + + public Assumptions assumptions() { + return assumptions; + } + + public MetaAccessProvider getMetaAccess() { + return metaAccess; + } + + public ConstantReflectionProvider getConstantReflection() { + return constantReflection; + } + + public boolean canonicalizeReads() { + return canonicalizeReads; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/SimplifierTool.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/SimplifierTool.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/SimplifierTool.java Mon Jun 30 12:02:19 2014 +0200 @@ -35,4 +35,8 @@ * Adds a node to the worklist independent of whether it has already been on the worklist. */ void addToWorkList(Node node); + + void addToWorkList(Iterable nodes); + + void removeIfUnused(Node node); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -92,7 +92,7 @@ final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; final boolean inlineObjects = true; - return new HotSpotTargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); + return new HotSpotTargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java Mon Jun 30 12:02:19 2014 +0200 @@ -64,7 +64,7 @@ } } } - params[params.length - 1] = rbp.asValue(Kind.Long); + params[params.length - 1] = rbp.asValue(LIRKind.value(Kind.Long)); gen.emitIncomingValues(params); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Move.MemOp; @@ -38,33 +37,6 @@ public class AMD64HotSpotCompare { - @Opcode("NCMP") - public static class HotSpotCompareNarrowOp extends AMD64LIRInstruction { - - @Use({REG}) protected AllocatableValue x; - @Use({REG, STACK}) protected AllocatableValue y; - - public HotSpotCompareNarrowOp(AllocatableValue x, AllocatableValue y) { - this.x = x; - this.y = y; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (isRegister(y)) { - masm.cmpl(asRegister(x), asRegister(y)); - } else { - assert isStackSlot(y); - masm.cmpl(asRegister(x), (AMD64Address) crb.asAddress(y)); - } - } - - @Override - protected void verify() { - assert x.getPlatformKind() == NarrowOopStamp.NarrowOop && y.getPlatformKind() == NarrowOopStamp.NarrowOop; - } - } - @Opcode("CMP") public static class HotSpotCompareConstantOp extends AMD64LIRInstruction { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -43,7 +43,7 @@ * initial LIR generation is finished. Until then, we use a placeholder variable so that LIR * verification is successful. */ - private static final Variable PLACEHOLDER = new Variable(Kind.Long, Integer.MAX_VALUE); + private static final Variable PLACEHOLDER = new Variable(LIRKind.value(Kind.Long), Integer.MAX_VALUE); @Use({REG, STACK}) protected AllocatableValue savedRbp = PLACEHOLDER; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -56,8 +56,8 @@ // The calling convention for the exception handler stub is (only?) defined in // TemplateInterpreterGenerator::generate_throw_exception() // in templateInterpreter_x86_64.cpp around line 1923 - RegisterValue exception = rax.asValue(Kind.Object); - RegisterValue exceptionPc = rdx.asValue(word); + RegisterValue exception = rax.asValue(LIRKind.reference(Kind.Object)); + RegisterValue exceptionPc = rdx.asValue(LIRKind.value(word)); CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, null, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, ANY_LOCATION)); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -26,37 +26,30 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import java.util.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.HotSpotStoreConstantOp; -import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.NoOp; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp; import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; -import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; -import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.gen.*; /** @@ -92,7 +85,7 @@ public SaveRbp(NoOp placeholder) { this.placeholder = placeholder; - this.reservedSlot = getResult().getFrameMap().allocateSpillSlot(Kind.Long); + this.reservedSlot = getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long)); assert reservedSlot.getRawOffset() == -16 : reservedSlot.getRawOffset(); } @@ -107,10 +100,10 @@ dst = reservedSlot; } else { getResult().getFrameMap().freeSpillSlot(reservedSlot); - dst = newVariable(Kind.Long); + dst = newVariable(LIRKind.value(Kind.Long)); } - placeholder.replace(getResult().getLIR(), new MoveFromRegOp(Kind.Long, dst, rbp.asValue(Kind.Long))); + placeholder.replace(getResult().getLIR(), new MoveFromRegOp(Kind.Long, dst, rbp.asValue(LIRKind.value(Kind.Long)))); return dst; } } @@ -161,7 +154,7 @@ public void emitReturn(Value input) { AllocatableValue operand = Value.ILLEGAL; if (input != null) { - operand = resultOperandFor(input.getKind()); + operand = resultOperandFor(input.getLIRKind()); emitMove(operand, input); } if (pollOnReturnScratchRegister == null) { @@ -235,7 +228,7 @@ for (int i = 0; i < savedRegisters.length; i++) { PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); assert kind != Kind.Illegal; - StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); + StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(LIRKind.value(kind)); savedRegisterLocations[i] = spillSlot; } return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); @@ -311,7 +304,7 @@ Register thread = getProviders().getRegisters().getThreadRegister(); append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(Kind.Long), trapRequest); + Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(Kind.Long)), trapRequest); append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); Map calleeSaveInfo = ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo(); @@ -326,7 +319,7 @@ Register thread = getProviders().getRegisters().getThreadRegister(); append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(Kind.Long)); + Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(Kind.Long))); append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); Map calleeSaveInfo = ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo(); @@ -393,10 +386,10 @@ } private void moveValueToThread(Value v, int offset) { - Kind wordKind = getProviders().getCodeCache().getTarget().wordKind; + LIRKind wordKind = LIRKind.value(getProviders().getCodeCache().getTarget().wordKind); RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind); - AMD64AddressValue address = new AMD64AddressValue(v.getKind(), thread, offset); - emitStore(v.getKind(), address, v, null); + AMD64AddressValue address = new AMD64AddressValue(wordKind, thread, offset); + emitStore(v.getLIRKind(), address, v, null); } @Override @@ -417,7 +410,7 @@ boolean hasDebugInfo = getResult().getLIR().hasDebugInfo(); AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo); if (hasDebugInfo) { - ((AMD64HotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMap().allocateSpillSlot(Kind.Long)); + ((AMD64HotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long))); } for (AMD64HotSpotEpilogueOp op : epilogueOps) { @@ -441,17 +434,10 @@ } } - private static Kind getMemoryKind(PlatformKind kind) { - if (kind == NarrowOopStamp.NarrowOop) { - return Kind.Int; - } else { - return (Kind) kind; - } - } - - private static PlatformKind toStackKind(PlatformKind kind) { - if (kind instanceof Kind) { - return ((Kind) kind).getStackKind(); + private static LIRKind toStackKind(LIRKind kind) { + if (kind.getPlatformKind() instanceof Kind) { + Kind stackKind = ((Kind) kind.getPlatformKind()).getStackKind(); + return kind.changeType(stackKind); } else { return kind; } @@ -466,36 +452,39 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { + public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) { AMD64AddressValue loadAddress = asAddressValue(address); Variable result = newVariable(toStackKind(kind)); - append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); + append(new LoadOp((Kind) kind.getPlatformKind(), result, loadAddress, state)); return result; } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { + public void emitStore(LIRKind kind, Value address, Value inputVal, LIRFrameState state) { AMD64AddressValue storeAddress = asAddressValue(address); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); if (canStoreConstant(c)) { - append(new HotSpotStoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); + append(new HotSpotStoreConstantOp((Kind) kind.getPlatformKind(), storeAddress, c, state)); return; } } Variable input = load(inputVal); - append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); + append(new StoreOp((Kind) kind.getPlatformKind(), storeAddress, input, state)); } @Override public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { - if (pointer.getPlatformKind() == Kind.Object) { - Variable result = newVariable(NarrowOopStamp.NarrowOop); + LIRKind inputKind = pointer.getLIRKind(); + assert inputKind.getPlatformKind() == Kind.Long || inputKind.getPlatformKind() == Kind.Object; + if (inputKind.isReference(0)) { + // oop + Variable result = newVariable(LIRKind.reference(Kind.Int)); append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); return result; } else { - assert pointer.getPlatformKind() == Kind.Long; - Variable result = newVariable(Kind.Int); + // metaspace pointer + Variable result = newVariable(LIRKind.value(Kind.Int)); AllocatableValue base = Value.ILLEGAL; if (encoding.base != 0) { base = emitMove(Constant.forLong(encoding.base)); @@ -507,13 +496,16 @@ @Override public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) { - if (pointer.getPlatformKind() == NarrowOopStamp.NarrowOop) { - Variable result = newVariable(Kind.Object); + LIRKind inputKind = pointer.getLIRKind(); + assert inputKind.getPlatformKind() == Kind.Int; + if (inputKind.isReference(0)) { + // oop + Variable result = newVariable(LIRKind.reference(Kind.Object)); append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull)); return result; } else { - assert pointer.getPlatformKind() == Kind.Int; - Variable result = newVariable(Kind.Long); + // metaspace pointer + Variable result = newVariable(LIRKind.value(Kind.Long)); AllocatableValue base = Value.ILLEGAL; if (encoding.base != 0) { base = emitMove(Constant.forLong(encoding.base)); @@ -527,115 +519,45 @@ protected AMD64LIRInstruction createMove(AllocatableValue dst, Value src) { if (src instanceof Constant) { return new AMD64HotSpotMove.HotSpotLoadConstantOp(dst, (Constant) src); - } else if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) { - if (isRegister(src) || isStackSlot(dst)) { - return new MoveFromRegOp(Kind.Int, dst, src); - } else { - return new MoveToRegOp(Kind.Int, dst, src); - } } else { return super.createMove(dst, src); } } public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { - PlatformKind kind = newValue.getPlatformKind(); - assert kind == expectedValue.getPlatformKind(); - Kind memKind = getMemoryKind(kind); + LIRKind kind = newValue.getLIRKind(); + assert kind.equals(expectedValue.getLIRKind()); + Kind memKind = (Kind) kind.getPlatformKind(); AMD64AddressValue addressValue = asAddressValue(address); RegisterValue raxRes = AMD64.rax.asValue(kind); emitMove(raxRes, expectedValue); append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue))); - assert trueValue.getPlatformKind() == falseValue.getPlatformKind(); - Variable result = newVariable(trueValue.getPlatformKind()); + assert trueValue.getLIRKind().equals(falseValue.getLIRKind()); + Variable result = newVariable(trueValue.getLIRKind()); append(new CondMoveOp(result, Condition.EQ, asAllocatable(trueValue), falseValue)); return result; } public Value emitAtomicReadAndAdd(Value address, Value delta) { - PlatformKind kind = delta.getPlatformKind(); - Kind memKind = getMemoryKind(kind); + LIRKind kind = delta.getLIRKind(); + Kind memKind = (Kind) kind.getPlatformKind(); Variable result = newVariable(kind); AMD64AddressValue addressValue = asAddressValue(address); append(new AMD64Move.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta))); return result; } - public static Register asNarrowReg(Value value) { - if (value.getPlatformKind() != NarrowOopStamp.NarrowOop) { - throw new InternalError("needed NarrowOop got: " + value.getKind()); - } else { - return asRegister(value); - } - } - public Value emitAtomicReadAndWrite(Value address, Value newValue) { - PlatformKind kind = newValue.getPlatformKind(); - Kind memKind = getMemoryKind(kind); + LIRKind kind = newValue.getLIRKind(); + Kind memKind = (Kind) kind.getPlatformKind(); Variable result = newVariable(kind); AMD64AddressValue addressValue = asAddressValue(address); append(new AMD64Move.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue))); return result; } - public static class CompareMemoryCompressedOp extends AMD64LIRInstruction { - @Alive({COMPOSITE}) protected AMD64AddressValue x; - @Use({CONST, REG}) protected Value y; - @State protected LIRFrameState state; - - public CompareMemoryCompressedOp(AMD64AddressValue x, Value y, LIRFrameState state) { - assert HotSpotGraalRuntime.runtime().getConfig().useCompressedOops; - this.x = x; - this.y = y; - this.state = state; - } - - @Override - protected void verify() { - assert y instanceof Constant || y.getPlatformKind() == NarrowOopStamp.NarrowOop; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (state != null) { - crb.recordImplicitException(masm.position(), state); - } - if (y instanceof Constant) { - Constant constant = (Constant) y; - if (constant.isNull()) { - masm.cmpl(x.toAddress(), 0); - } else { - if (y.getKind() == Kind.Object) { - crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true)); - } else if (y.getKind() == Kind.Long) { - crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true)); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - masm.cmpl(x.toAddress(), 0xdeaddead); - } - } else { - masm.cmpl(asNarrowReg(y), x.toAddress()); - } - } - } - - protected void emitCompareBranchMemoryCompressed(Value left, Value right, Condition cond, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability, LIRFrameState state) { - boolean mirrored = false; - if (left instanceof AMD64AddressValue) { - append(new CompareMemoryCompressedOp((AMD64AddressValue) left, right, state)); - } else { - assert right instanceof AMD64AddressValue; - append(new CompareMemoryCompressedOp((AMD64AddressValue) right, left, state)); - mirrored = true; - } - - Condition finalCondition = mirrored ? cond.mirror() : cond; - append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); - } - public void emitNullCheck(Value address, LIRFrameState state) { assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!"; append(new AMD64Move.NullCheckOp(load(address), state)); @@ -645,8 +567,6 @@ protected void emitCompareOp(PlatformKind cmpKind, Variable left, Value right) { if (right instanceof HotSpotConstant) { append(new AMD64HotSpotCompare.HotSpotCompareConstantOp(left, (Constant) right)); - } else if (cmpKind == NarrowOopStamp.NarrowOop) { - append(new AMD64HotSpotCompare.HotSpotCompareNarrowOp(left, asAllocatable(right))); } else { super.emitCompareOp(cmpKind, left, right); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -30,9 +30,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.match.*; import com.oracle.graal.debug.*; @@ -63,49 +63,19 @@ result = ((PiNode) result).getOriginalNode(); } if (result instanceof CompressionNode) { - result = ((CompressionNode) result).getInput(); + result = ((CompressionNode) result).getValue(); } return result; } - private void emitCompareMemoryObject(IfNode ifNode, ValueNode valueNode, Access access, CompareNode compare) { - Value value; - // This works by embedding the compressed form for constants, so force a constant instead of - // respecting what operand() would return. - if (valueNode.isConstant()) { - value = valueNode.asConstant(); - } else { - value = gen.load(operand(valueNode)); - } - AMD64AddressValue address = makeAddress(access); - - Condition cond = compare.condition(); - Value left; - Value right; - if (access == filterCompression(compare.x())) { - left = value; - right = address; - } else { - assert access == filterCompression(compare.y()); - left = address; - right = value; - cond = cond.mirror(); - } - - LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor()); - LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor()); - double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); - getGen().emitCompareBranchMemoryCompressed(left, right, cond, trueLabel, falseLabel, trueLabelProbability, getState(access)); - } - private void emitCompareCompressedMemory(Kind kind, IfNode ifNode, ValueNode valueNode, CompressionNode compress, ConstantLocationNode location, Access access, CompareNode compare) { Value value = gen.load(operand(valueNode)); AMD64AddressValue address = makeCompressedAddress(compress, location); Condition cond = compare.condition(); - if (access == filterCompression(compare.x())) { + if (access == filterCompression(compare.getX())) { cond = cond.mirror(); } else { - assert access == filterCompression(compare.y()); + assert access == filterCompression(compare.getY()); } LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor()); @@ -135,7 +105,7 @@ @Override protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeMap nodeOperands) { - HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMap(), Kind.Long); + HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMap(), LIRKind.value(Kind.Long)); return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); } @@ -154,7 +124,7 @@ } } } - params[params.length - 1] = rbp.asValue(Kind.Long); + params[params.length - 1] = rbp.asValue(LIRKind.value(Kind.Long)); gen.emitIncomingValues(params); @@ -237,38 +207,28 @@ @Override public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Kind kind = x.newValue().getKind(); - assert kind == x.expectedValue().getKind(); - Value expected = gen.loadNonConst(operand(x.expectedValue())); Variable newVal = gen.load(operand(x.newValue())); + assert expected.getLIRKind().equals(newVal.getLIRKind()); - int disp = 0; - AMD64AddressValue address; - Value index = operand(x.offset()); - if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) { - assert !gen.getCodeCache().needsDataPatch(asConstant(index)); - disp += (int) ValueUtil.asConstant(index).asLong(); - address = new AMD64AddressValue(kind, gen.load(operand(x.object())), disp); - } else { - address = new AMD64AddressValue(kind, gen.load(operand(x.object())), gen.load(index), Scale.Times1, disp); - } + AMD64AddressValue address = getGen().emitAddress(operand(x.object()), 0, operand(x.offset()), 1); - RegisterValue raxLocal = AMD64.rax.asValue(kind); + RegisterValue raxLocal = AMD64.rax.asValue(expected.getLIRKind()); gen.emitMove(raxLocal, expected); - append(new CompareAndSwapOp(kind, raxLocal, address, raxLocal, newVal)); + append(new CompareAndSwapOp(expected.getKind(), raxLocal, address, raxLocal, newVal)); - Variable result = newVariable(x.getKind()); - gen.emitMove(result, raxLocal); - setResult(x, result); + setResult(x, gen.emitMove(raxLocal)); } boolean canFormCompressedMemory(CompressionNode compress, ConstantLocationNode location) { HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); if (config.useCompressedOops && compress.getEncoding().shift <= 3 && NumUtil.isInt(location.getDisplacement())) { - PlatformKind objectKind = compress.getInput().stamp().getPlatformKind(getGen()); - if (objectKind == NarrowOopStamp.NarrowOop || objectKind == Kind.Int && config.narrowKlassBase == config.narrowOopBase) { + Stamp compressedStamp = compress.getValue().stamp(); + if (compressedStamp instanceof NarrowOopStamp) { return true; + } else if (compressedStamp instanceof IntegerStamp) { + IntegerStamp is = (IntegerStamp) compressedStamp; + return is.getBits() == 32 && config.narrowKlassBase == config.narrowOopBase; } } return false; @@ -276,29 +236,11 @@ private AMD64AddressValue makeCompressedAddress(CompressionNode compress, ConstantLocationNode location) { assert canFormCompressedMemory(compress, location); - AMD64AddressValue address = getGen().emitAddress(getGen().getProviders().getRegisters().getHeapBaseRegister().asValue(), location.getDisplacement(), operand(compress.getInput()), + AMD64AddressValue address = getGen().emitAddress(getGen().getProviders().getRegisters().getHeapBaseRegister().asValue(), location.getDisplacement(), operand(compress.getValue()), 1 << compress.getEncoding().shift); return address; } - @MatchRule("(If (ObjectEquals=compare Constant=value (Pi (Compression Read=access))))") - @MatchRule("(If (ObjectEquals=compare Constant=value (Pi (Compression FloatingRead=access))))") - @MatchRule("(If (ObjectEquals=compare (Compression value) (Pi (Compression Read=access))))") - @MatchRule("(If (ObjectEquals=compare (Compression value) (Pi (Compression FloatingRead=access))))") - @MatchRule("(If (ObjectEquals=compare Constant=value (Compression Read=access)))") - @MatchRule("(If (ObjectEquals=compare Constant=value (Compression FloatingRead=access)))") - @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression Read=access)))") - @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression FloatingRead=access)))") - public ComplexMatchResult ifCompareMemoryObject(IfNode root, CompareNode compare, ValueNode value, Access access) { - if (HotSpotGraalRuntime.runtime().getConfig().useCompressedOops) { - return builder -> { - emitCompareMemoryObject(root, value, access, compare); - return null; - }; - } - return null; - } - @MatchRule("(If (IntegerEquals=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (IntegerLessThan=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (IntegerBelowThan=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") @@ -311,7 +253,7 @@ @MatchRule("(If (FloatLessThan=compare value (Read=access (Compression=compress object) ConstantLocation=location)))") public ComplexMatchResult ifCompareCompressedMemory(IfNode root, CompareNode compare, CompressionNode compress, ValueNode value, ConstantLocationNode location, Access access) { if (canFormCompressedMemory(compress, location)) { - PlatformKind cmpKind = gen.getPlatformKind(compare.x().stamp()); + PlatformKind cmpKind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind(); if (cmpKind instanceof Kind) { Kind kind = (Kind) cmpKind; return builder -> { @@ -358,7 +300,7 @@ @MatchRule("(FloatingRead (Pi (Compression=compress object)) ConstantLocation=location)") public ComplexMatchResult readCompressed(Access root, CompressionNode compress, ConstantLocationNode location) { if (canFormCompressedMemory(compress, location)) { - PlatformKind readKind = getGen().getPlatformKind(root.asNode().stamp()); + LIRKind readKind = getGen().getLIRKind(root.asNode().stamp()); return builder -> { return getGen().emitLoad(readKind, makeCompressedAddress(compress, location), getState(root)); }; @@ -370,7 +312,7 @@ @MatchRule("(Write (Pi (Compression=compress object)) ConstantLocation=location value)") public ComplexMatchResult writeCompressed(Access root, CompressionNode compress, ConstantLocationNode location, ValueNode value) { if (canFormCompressedMemory(compress, location)) { - PlatformKind readKind = getGen().getPlatformKind(value.asNode().stamp()); + LIRKind readKind = getGen().getLIRKind(value.asNode().stamp()); return builder -> { getGen().emitStore(readKind, makeCompressedAddress(compress, location), operand(value), getState(root)); return null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,7 +33,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.nodes.type.*; public class AMD64HotSpotRegisterConfig implements RegisterConfig { @@ -70,16 +69,9 @@ return categorized.get(kind); } - PlatformKind primitiveKind; - if (kind == NarrowOopStamp.NarrowOop) { - primitiveKind = Kind.Int; - } else { - primitiveKind = kind; - } - ArrayList list = new ArrayList<>(); for (Register reg : getAllocatableRegisters()) { - if (architecture.canStoreValue(reg.getRegisterCategory(), primitiveKind)) { + if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { list.add(reg); } } @@ -222,14 +214,14 @@ case Object: if (!stackOnly && currentGeneral < generalParameterRegisters.length) { Register register = generalParameterRegisters[currentGeneral++]; - locations[i] = register.asValue(kind); + locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Float: case Double: if (!stackOnly && currentXMM < xmmParameterRegisters.length) { Register register = xmmParameterRegisters[currentXMM++]; - locations[i] = register.asValue(kind); + locations[i] = register.asValue(target.getLIRKind(kind)); } break; default: @@ -237,13 +229,13 @@ } if (locations[i] == null) { - locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); + locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out); currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); - AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind.getStackKind()); + AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(target.getLIRKind(returnKind.getStackKind())); return new CallingConvention(currentStackOffset, returnLocation, locations); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -51,7 +51,7 @@ this.state = state; this.config = config; if (isPollingPageFar(config) || ImmutableCode.getValue()) { - temp = tool.getLIRGeneratorTool().newVariable(tool.getLIRGeneratorTool().target().wordKind); + temp = tool.getLIRGeneratorTool().newVariable(LIRKind.value(tool.getLIRGeneratorTool().target().wordKind)); } else { // Don't waste a register if it's unneeded temp = Value.ILLEGAL; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,15 +26,20 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.GraalInternalError; import com.oracle.graal.compiler.hsail.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.gpu.*; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hsail.*; import com.oracle.graal.java.*; @@ -55,11 +60,54 @@ return (HSAILHotSpotBackend) backend; } + ConcurrentHashMap, String> resolvedConsumerTargetMethods = new ConcurrentHashMap<>(); + /** - * Gets a compiled and installed kernel for the lambda called by the {@code accept(int value)} - * method in a class implementing {@code java.util.function.IntConsumer}. - * - * @param intConsumerClass a class implementing {@code java.util.function.IntConsumer} + * Returns the name of the reduction method given a class implementing {@link IntConsumer}. + * + * @param opClass a class implementing {@link IntConsumer}. + * @return the name of the reduction method + */ + public String getIntReduceTargetName(Class opClass) { + String cachedMethodName = resolvedConsumerTargetMethods.get(Objects.requireNonNull(opClass)); + if (cachedMethodName != null) { + return cachedMethodName; + } else { + Method acceptMethod = null; + for (Method m : opClass.getMethods()) { + if (m.getName().equals("applyAsInt")) { + assert acceptMethod == null : "found more than one implementation of applyAsInt in " + opClass; + acceptMethod = m; + } + } + // Ensure a debug configuration for this thread is initialized + if (DebugScope.getConfig() == null) { + DebugEnvironment.initialize(System.out); + } + + HSAILHotSpotBackend backend = getHSAILBackend(); + Providers providers = backend.getProviders(); + StructuredGraph graph = new StructuredGraph(((HotSpotMetaAccessProvider) providers.getMetaAccess()).lookupJavaMethod(acceptMethod)); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph); + NodeIterable calls = graph.getNodes(MethodCallTargetNode.class); + assert calls.count() == 1; + ResolvedJavaMethod lambdaMethod = calls.first().targetMethod(); + Debug.log("target ... %s", lambdaMethod); + + String className = lambdaMethod.getDeclaringClass().getName(); + if (!className.equals("Ljava/lang/Integer;")) { + return null; + } + resolvedConsumerTargetMethods.put(opClass, lambdaMethod.getName()); + return lambdaMethod.getName().intern(); + } + } + + /** + * Gets a compiled and installed kernel for the lambda called by the + * {@link IntConsumer#accept(int)} method in a class implementing {@link IntConsumer}. + * + * @param intConsumerClass a class implementing {@link IntConsumer} * @return a {@link HotSpotNmethod} handle to the compiled and installed kernel */ private static HotSpotNmethod getCompiledLambda(Class intConsumerClass) { @@ -108,6 +156,38 @@ } @Override + public Object createKernelFromHsailString(String code, String methodName) { + ExternalCompilationResult hsailCode = new ExternalCompilationResult(); + try (Debug.Scope ds = Debug.scope("GeneratingKernelBinary")) { + + HSAILHotSpotBackend backend = getHSAILBackend(); + Providers providers = backend.getProviders(); + Method integerOffloadMethod = null; + + for (Method m : Integer.class.getMethods()) { + if (m.getName().equals(methodName)) { + integerOffloadMethod = m; + break; + } + } + if (integerOffloadMethod != null) { + ResolvedJavaMethod rm = ((HotSpotMetaAccessProvider) providers.getMetaAccess()).lookupJavaMethod(integerOffloadMethod); + + long kernel = HSAILHotSpotBackend.generateKernel(code.getBytes(), "Integer::" + methodName); + if (kernel == 0) { + throw new GraalInternalError("Failed to compile HSAIL kernel from String"); + } + hsailCode.setEntryPoint(kernel); + return backend.installKernel(rm, hsailCode); // is a HotSpotNmethod + } else { + return null; + } + } catch (Throwable e) { + throw Debug.handle(e); + } + } + + @Override public boolean dispatchKernel(Object kernel, int jobSize, Object[] args) { HotSpotNmethod code = (HotSpotNmethod) kernel; if (code != null) { @@ -125,4 +205,258 @@ return false; } } + + /** + * Running with a larger global size seems to increase the performance for sum, but it might be + * different for other reductions so it is a knob. + */ + private static final int GlobalSize = 1024 * Integer.getInteger("com.amd.sumatra.reduce.globalsize.multiple", 1); + + @Override + public Integer offloadIntReduceImpl(Object okraKernel, int identity, int[] streamSource) { + // NOTE - this reduce requires local size of 64 which is the SumatraUtils default + + // Handmade reduce does not support +UseCompressedOops + HotSpotVMConfig config = runtime().getConfig(); + if (config.useCompressedOops == true || config.useHSAILDeoptimization == true) { + throw new GraalInternalError("Reduce offload not compatible with +UseCompressedOops or +UseHSAILDeoptimization"); + } + + try { + assert streamSource.length >= GlobalSize : "Input array length=" + streamSource.length + " smaller than requested global_size=" + GlobalSize; + + int result[] = {identity}; + Object args[] = {streamSource, result, streamSource.length}; + args[0] = streamSource; + + dispatchKernel(okraKernel, GlobalSize, args); + + // kernel result is result[0]. + return result[0]; + } catch (Exception e) { + System.err.println(e); + e.printStackTrace(); + } + return null; + } + + @Override + public String getIntegerReduceIntrinsic(String reducerName) { + + // Note all of these depend on group size of 256 + + String reduceOp = "/* Invalid */ "; + String atomicResultProduction = "/* Invalid */ "; + if (reducerName.equals("sum")) { + reduceOp = "add_u32 "; + atomicResultProduction = "atomicnoret_add_global_u32 "; + } else if (reducerName.equals("max")) { + reduceOp = "max_s32 "; + atomicResultProduction = "atomicnoret_max_global_s32 "; + } else if (reducerName.equals("min")) { + reduceOp = "min_s32 "; + atomicResultProduction = "atomicnoret_min_global_s32 "; + } else { + return "/* Invalid */ "; + } + + // @formatter:off + return new String( + "version 0:95:$full:$large; // BRIG Object Format Version 0:4" + "\n" + + "" + "\n" + + "kernel &run(" + "\n" + + " align 8 kernarg_u64 %arg_p3," + "\n" + + " align 8 kernarg_u64 %arg_p4," + "\n" + + " align 4 kernarg_u32 %arg_p5)" + "\n" + + "{" + "\n" + + "" + "\n" + + " align 4 group_u32 %reduce_cllocal_scratch[256];" + "\n" + + "" + "\n" + + " workitemabsid_u32 $s2, 0;" + "\n" + + "" + "\n" + + " ld_kernarg_u32 $s1, [%arg_p5];" + "\n" + + " ld_kernarg_u64 $d0, [%arg_p4];" + "\n" + + " ld_kernarg_u64 $d1, [%arg_p3];" + "\n" + + "" + "\n" + + " add_u64 $d0, $d0, 24; // adjust over obj array headers" + "\n" + + " add_u64 $d1, $d1, 24;" + "\n" + + " cmp_ge_b1_s32 $c0, $s2, $s1; // if(gloId < length){" + "\n" + + " cbr $c0, @BB0_1;" + "\n" + + " gridsize_u32 $s0, 0; // s0 is globalsize" + "\n" + + " add_u32 $s0, $s0, $s2; // gx += globalsize" + "\n" + + " cvt_s64_s32 $d2, $s2; // s2 is global id" + "\n" + + " shl_u64 $d2, $d2, 2;" + "\n" + + " add_u64 $d2, $d1, $d2;" + "\n" + + " ld_global_u32 $s3, [$d2]; // load this element from input" + "\n" + + " brn @BB0_3;" + "\n" + + "" + "\n" + + "@BB0_1:" + "\n" + + " mov_b32 $s0, $s2;" + "\n" + "" + "\n" + + "@BB0_3:" + "\n" + + " cmp_ge_b1_s32 $c1, $s0, $s1; // while (gx < length)" + "\n" + + " cbr $c1, @BB0_6;" + "\n" + + " gridsize_u32 $s2, 0;" + "\n" + + "" + "\n" + + "@BB0_5:" + "\n" + + " cvt_s64_s32 $d2, $s0;" + "\n" + + " shl_u64 $d2, $d2, 2;" + "\n" + + " add_u64 $d2, $d1, $d2;" + "\n" + + " ld_global_u32 $s4, [$d2];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " add_u32 $s0, $s0, $s2;" + "\n" + + " cmp_lt_b1_s32 $c1, $s0, $s1;" + "\n" + + " cbr $c1, @BB0_5;" + "\n" + + "" + "\n" + + "@BB0_6:" + "\n" + + " workgroupid_u32 $s0, 0;" + "\n" + + " workgroupsize_u32 $s2, 0;" + "\n" + + " mul_u32 $s2, $s2, $s0;" + "\n" + + " sub_u32 $s2, $s1, $s2;" + "\n" + + " workitemid_u32 $s1, 0;" + "\n" + + " add_u32 $s4, $s1, 128;" + + "\n" + + " cmp_lt_b1_u32 $c1, $s4, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 128;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " cvt_s64_s32 $d1, $s1;" + "\n" + + " shl_u64 $d1, $d1, 2;" + "\n" + + " lda_group_u64 $d2, [%reduce_cllocal_scratch];" + "\n" + + " add_u64 $d1, $d2, $d1;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_8;" + "\n" + + " ld_group_u32 $s3, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s4;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d3, $d2, $d3;" + "\n" + + " ld_group_u32 $s4, [$d3];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_8:" + "\n" + + " add_u32 $s3, $s1, 64;" + "\n" + + " cmp_lt_b1_u32 $c1, $s3, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 64;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_10;" + "\n" + + " ld_group_u32 $s4, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s3;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d3, $d2, $d3;" + "\n" + + " ld_group_u32 $s3, [$d3];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_10:" + "\n" + + " add_u32 $s3, $s1, 32;" + "\n" + + " cmp_lt_b1_u32 $c1, $s3, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 32;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_12;" + "\n" + + " ld_group_u32 $s4, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s3;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d3, $d2, $d3;" + "\n" + + " ld_group_u32 $s3, [$d3];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_12:" + "\n" + + " add_u32 $s3, $s1, 16;" + "\n" + + " cmp_lt_b1_u32 $c1, $s3, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 16;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_14;" + "\n" + + " ld_group_u32 $s4, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s3;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d3, $d2, $d3;" + "\n" + + " ld_group_u32 $s3, [$d3];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_14:" + "\n" + + " add_u32 $s3, $s1, 8;" + "\n" + + " cmp_lt_b1_u32 $c1, $s3, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 8;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_16;" + "\n" + + " ld_group_u32 $s4, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s3;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d3, $d2, $d3;" + "\n" + + " ld_group_u32 $s3, [$d3];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_16:" + "\n" + + " add_u32 $s3, $s1, 4;" + "\n" + + " cmp_lt_b1_u32 $c1, $s3, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 4;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_18;" + "\n" + + " ld_group_u32 $s4, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s3;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d3, $d2, $d3;" + "\n" + + " ld_group_u32 $s3, [$d3];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_18:" + "\n" + + " add_u32 $s3, $s1, 2;" + "\n" + + " cmp_lt_b1_u32 $c1, $s3, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 2;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_20;" + "\n" + + " ld_group_u32 $s4, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s3;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d3, $d2, $d3;" + "\n" + + " ld_group_u32 $s3, [$d3];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_20:" + "\n" + + " add_u32 $s3, $s1, 1;" + "\n" + + " cmp_lt_b1_u32 $c1, $s3, $s2;" + "\n" + + " cmp_lt_b1_s32 $c2, $s1, 1;" + "\n" + + " and_b1 $c1, $c2, $c1;" + "\n" + + " barrier_fgroup;" + "\n" + + " not_b1 $c1, $c1;" + "\n" + + " cbr $c1, @BB0_22;" + "\n" + + " ld_group_u32 $s4, [$d1];" + "\n" + + " cvt_s64_s32 $d3, $s3;" + "\n" + + " shl_u64 $d3, $d3, 2;" + "\n" + + " add_u64 $d2, $d2, $d3;" + "\n" + + " ld_group_u32 $s3, [$d2];" + "\n" + + reduceOp + " $s3, $s3, $s4;" + "\n" + + " st_group_u32 $s3, [$d1];" + "\n" + + "" + "\n" + + "@BB0_22:" + "\n" + + " cmp_gt_b1_u32 $c0, $s1, 0; // s1 is local id, done if > 0" + "\n" + + " cbr $c0, @BB0_24;" + "\n" + + "" + "\n" + + " ld_group_u32 $s2, [%reduce_cllocal_scratch]; // s2 is result[get_group_id(0)];" + "\n" + + atomicResultProduction + " [$d0], $s2; // build global result from local results" + "\n" + + "" + "\n" + + "@BB0_24:" + "\n" + + " ret;" + "\n" + + "};" + "\n"); + //@formatter:on + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -66,7 +66,6 @@ import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp; -import com.oracle.graal.lir.hsail.HSAILMove.AtomicReadAndAddOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.extended.*; @@ -103,8 +102,10 @@ paramTypeMap.put("HotSpotResolvedPrimitiveType", "f64"); paramTypeMap.put("HotSpotResolvedPrimitiveType", "s64"); - // The order of the conjunction below is important: the OkraUtil - // call may provision the native library required by the initialize() call + /* + * The order of the conjunction below is important: the OkraUtil call may provision the + * native library required by the initialize() call + */ deviceInitialized = OkraUtil.okraLibExists() && initialize(); } @@ -249,7 +250,7 @@ /** * Generates a GPU binary from HSAIL code. */ - private static native long generateKernel(byte[] hsailCode, String name); + static native long generateKernel(byte[] hsailCode, String name); /** * Installs the {@linkplain ExternalCompilationResult#getEntryPoint() GPU binary} associated @@ -261,8 +262,7 @@ */ public final HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult hsailCode) { assert hsailCode.getEntryPoint() != 0L; - // code below here lifted from HotSpotCodeCacheProviders.addExternalMethod - // used to be return getProviders().getCodeCache().addExternalMethod(method, hsailCode); + // Code here based on HotSpotCodeCacheProvider.addExternalMethod(). HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method; if (hsailCode.getId() == -1) { hsailCode.setId(javaMethod.allocateCompileId(hsailCode.getEntryBCI())); @@ -294,6 +294,7 @@ HSAILHotSpotNmethod code = new HSAILHotSpotNmethod(javaMethod, hsailCode.getName(), false, true); code.setOopMapArray(hsailCode.getOopMapArray()); + code.setUsesAllocationFlag(hsailCode.getUsesAllocationFlag()); HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(getTarget(), javaMethod, compilationResult); CodeInstallResult result = getRuntime().getCompilerToVM().installCode(compiled, code, null); if (result != CodeInstallResult.OK) { @@ -378,20 +379,13 @@ throw new GraalInternalError("Cannot execute GPU kernel if device is not initialized"); } int[] oopMapArray = ((HSAILHotSpotNmethod) kernel).getOopMapArray(); - Object[] oopsSaveArea; - if (getRuntime().getConfig().useHSAILDeoptimization) { - int saveAreaCounts = OopMapArrayBuilder.getSaveAreaCounts(oopMapArray); - int numDRegs = (saveAreaCounts >> 8) & 0xff; - int numStackSlots = (saveAreaCounts >> 16); - // pessimistically assume that any of the DRegs or stackslots could be oops - oopsSaveArea = new Object[maxDeoptIndex * (numDRegs + numStackSlots)]; - } else { - oopsSaveArea = null; - } - return executeKernel0(kernel, jobSize, args, oopsSaveArea, donorThreadPool.get().getThreads(), HsailAllocBytesPerWorkitem.getValue(), oopMapArray); + + // Pass donorThreadPoolArray if this kernel uses allocation, otherwise null + Thread[] donorThreadArray = ((HSAILHotSpotNmethod) kernel).getUsesAllocationFlag() ? donorThreadPool.get().getThreads() : null; + return executeKernel0(kernel, jobSize, args, donorThreadArray, HsailAllocBytesPerWorkitem.getValue(), oopMapArray); } - private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave, Thread[] donorThreads, int allocBytesPerWorkitem, int[] oopMapArray) + private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Thread[] donorThreads, int allocBytesPerWorkitem, int[] oopMapArray) throws InvalidInstalledCodeException; /** @@ -449,6 +443,7 @@ static class HSAILHotSpotNmethod extends HotSpotNmethod { private int[] oopMapArray; + private boolean usesAllocation; HSAILHotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) { super(method, name, isDefault, isExternal); @@ -461,6 +456,14 @@ int[] getOopMapArray() { return oopMapArray; } + + public void setUsesAllocationFlag(boolean val) { + usesAllocation = val; + } + + public boolean getUsesAllocationFlag() { + return usesAllocation; + } } @Override @@ -484,6 +487,7 @@ public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod method) { assert method != null : lir + " is not associated with a method"; Kind wordKind = getProviders().getCodeCache().getTarget().wordKind; + LIRKind wordLIRKind = LIRKind.value(wordKind); HotSpotVMConfig config = getRuntime().getConfig(); boolean useHSAILDeoptimization = config.useHSAILDeoptimization; @@ -493,19 +497,22 @@ Debug.log("+UseHSAILSafepoints requires +UseHSAILDeoptimization"); } - // see what graph nodes we have to see if we are using the thread register - // if not, we don't have to emit the code that sets that up - // maybe there is a better way to do this? - boolean usesThreadRegister = false; + /* + * See what graph nodes we have to see if we are using the thread register. If not, we don't + * have to emit the code that sets it up. Maybe there is a better way to do this? + */ + boolean usesAllocation = false; search: for (AbstractBlock b : lir.linearScanOrder()) { for (LIRInstruction op : lir.getLIRforBlock(b)) { - if (op instanceof AtomicReadAndAddOp) { - usesThreadRegister = true; + if ((op instanceof HSAILMove.LoadOp) && ((HSAILMove.LoadOp) op).usesThreadRegister()) { + usesAllocation = true; assert useHSAILDeoptimization : "cannot use thread register if HSAIL deopt support is disabled"; break search; } } } + // save usesAllocation flag in ExternalCompilationResult + ((ExternalCompilationResult) crb.compilationResult).setUsesAllocationFlag(usesAllocation); // Emit the prologue. HSAILAssembler asm = (HSAILAssembler) crb.asm; @@ -527,8 +534,7 @@ nonConstantParamCount++; } - // If this is an instance method, include mappings for the "this" parameter - // as the first parameter. + // If this is an instance method, include the "this" parameter if (!isStatic) { nonConstantParamCount++; } @@ -564,8 +570,10 @@ // Include the gid. System.arraycopy(paramtypes, 0, ccParamTypes, 0, nonConstantParamCount); - // Last entry is always int (its register gets used in the workitemabsid instruction) - // this is true even for object stream labmdas + /* + * Last entry is always int (its register gets used in the workitemabsid instruction). This + * is true even for object stream lambdas. + */ if (sigParamCount > 0) { ccParamTypes[ccParamTypes.length - 1] = metaAccess.lookupJavaType(int.class); } @@ -620,15 +628,14 @@ if (useHSAILDeoptimization) { // Aliases for d16 - RegisterValue d16_deoptInfo = HSAIL.d16.asValue(wordKind); - RegisterValue d16_donorThreads = d16_deoptInfo; + RegisterValue d16_deoptInfo = HSAIL.d16.asValue(wordLIRKind); // Aliases for d17 - RegisterValue d17_donorThreadIndex = HSAIL.d17.asValue(wordKind); + RegisterValue d17_donorThreadIndex = HSAIL.d17.asValue(wordLIRKind); RegisterValue d17_safepointFlagAddrIndex = d17_donorThreadIndex; // Aliases for s34 - RegisterValue s34_deoptOccurred = HSAIL.s34.asValue(Kind.Int); + RegisterValue s34_deoptOccurred = HSAIL.s34.asValue(LIRKind.value(Kind.Int)); RegisterValue s34_donorThreadIndex = s34_deoptOccurred; asm.emitLoadKernelArg(d16_deoptInfo, asm.getDeoptInfoName(), "u64"); @@ -636,30 +643,29 @@ if (useHSAILSafepoints) { // Load address of _notice_safepoints field - asm.emitLoad(wordKind, d17_safepointFlagAddrIndex, new HSAILAddressValue(wordKind, d16_deoptInfo, config.hsailNoticeSafepointsOffset).toAddress()); + asm.emitLoad(wordKind, d17_safepointFlagAddrIndex, new HSAILAddressValue(wordLIRKind, d16_deoptInfo, config.hsailNoticeSafepointsOffset).toAddress()); // Load int value from that field - asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d17_safepointFlagAddrIndex, 0).toAddress()); + asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(wordLIRKind, d17_safepointFlagAddrIndex, 0).toAddress()); asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false); asm.cbr(deoptInProgressLabel); } - asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d16_deoptInfo, config.hsailDeoptOccurredOffset).toAddress()); + asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(wordLIRKind, d16_deoptInfo, config.hsailDeoptOccurredOffset).toAddress()); asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false); asm.cbr(deoptInProgressLabel); - // load thread register if needed - if (usesThreadRegister) { + // load thread register if this kernel performs allocation + if (usesAllocation) { + RegisterValue threadReg = getProviders().getRegisters().getThreadRegister().asValue(wordLIRKind); assert HsailDonorThreads.getValue() > 0; - asm.emitLoad(wordKind, d16_donorThreads, new HSAILAddressValue(wordKind, d16_deoptInfo, config.hsailDonorThreadsOffset).toAddress()); + asm.emitLoad(wordKind, threadReg, new HSAILAddressValue(wordLIRKind, d16_deoptInfo, config.hsailCurTlabInfoOffset).toAddress()); if (HsailDonorThreads.getValue() != 1) { asm.emitComment("// map workitem to a donor thread"); asm.emitString(String.format("rem_u32 $%s, %s, %d;", s34_donorThreadIndex.getRegister(), workItemReg, HsailDonorThreads.getValue())); asm.emitConvert(d17_donorThreadIndex, s34_donorThreadIndex, wordKind, Kind.Int); - asm.emit("mad", d16_donorThreads, d17_donorThreadIndex, Constant.forInt(8), d16_donorThreads); + asm.emit("mad", threadReg, d17_donorThreadIndex, Constant.forInt(8), threadReg); } else { // workitem is already mapped to solitary donor thread } - AllocatableValue threadRegValue = getProviders().getRegisters().getThreadRegister().asValue(wordKind); - asm.emitComment("// $" + getProviders().getRegisters().getThreadRegister() + " will point to a donor thread for this workitem"); - asm.emitLoad(wordKind, threadRegValue, new HSAILAddressValue(wordKind, d16_donorThreads).toAddress()); + asm.emitComment("// $" + getProviders().getRegisters().getThreadRegister() + " will point to holder of tlab thread info for this workitem"); } } @@ -676,8 +682,10 @@ boolean useCompressedOops = config.useCompressedOops; final int arrayElementsOffset = HotSpotGraalRuntime.getArrayBaseOffset(wordKind); String iterationObjArgReg = HSAIL.mapRegister(cc.getArgument(nonConstantParamCount - 1)); - // iterationObjArgReg will be the highest $d register in use (it is the last parameter) - // so tempReg can be the next higher $d register + /* + * iterationObjArgReg will be the highest $d register in use (it is the last parameter) + * so tempReg can be the next higher $d register + */ String tmpReg = "$d" + (asRegister(cc.getArgument(nonConstantParamCount - 1)).encoding() + 1); // Convert gid to long. asm.emitString("cvt_u64_s32 " + tmpReg + ", " + workItemReg + "; // Convert gid to long"); @@ -740,8 +748,10 @@ int numDRegs = 0; int numStackSlotBytes = 0; if (useHSAILDeoptimization) { - // get the union of registers and stack slots needed to be saved at the infopoints - // while doing this compute the highest register in each category + /* + * Get the union of registers and stack slots needed to be saved at the infopoints. + * While doing this compute the highest register in each category. + */ HSAILHotSpotRegisterConfig hsailRegConfig = (HSAILHotSpotRegisterConfig) regConfig; Set infoUsedRegs = new TreeSet<>(); Set infoUsedStackSlots = new HashSet<>(); @@ -800,18 +810,18 @@ final int offsetToNumSaves = config.hsailFrameNumSRegOffset; final int offsetToSaveArea = config.hsailFrameHeaderSize; - AllocatableValue scratch64 = HSAIL.d16.asValue(wordKind); - AllocatableValue cuSaveAreaPtr = HSAIL.d17.asValue(wordKind); - AllocatableValue waveMathScratch1 = HSAIL.d18.asValue(wordKind); - AllocatableValue waveMathScratch2 = HSAIL.d19.asValue(wordKind); + AllocatableValue scratch64 = HSAIL.d16.asValue(wordLIRKind); + AllocatableValue cuSaveAreaPtr = HSAIL.d17.asValue(wordLIRKind); + AllocatableValue waveMathScratch1 = HSAIL.d18.asValue(wordLIRKind); + AllocatableValue waveMathScratch2 = HSAIL.d19.asValue(wordLIRKind); - AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); - AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); - AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); - AllocatableValue workidreg = HSAIL.s35.asValue(Kind.Int); + AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(LIRKind.value(Kind.Int)); + AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(LIRKind.value(Kind.Int)); + AllocatableValue scratch32 = HSAIL.s34.asValue(LIRKind.value(Kind.Int)); + AllocatableValue workidreg = HSAIL.s35.asValue(LIRKind.value(Kind.Int)); - HSAILAddress deoptNextIndexAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeoptNextIndex).toAddress(); - HSAILAddress neverRanArrayAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToNeverRanArray).toAddress(); + HSAILAddress deoptNextIndexAddr = new HSAILAddressValue(wordLIRKind, scratch64, offsetToDeoptNextIndex).toAddress(); + HSAILAddress neverRanArrayAddr = new HSAILAddressValue(wordLIRKind, scratch64, offsetToNeverRanArray).toAddress(); // The just-started lanes that see the deopt flag will jump here asm.emitString0(deoptInProgressLabel + ":\n"); @@ -819,7 +829,7 @@ asm.emitWorkItemAbsId(workidreg); asm.emitConvert(waveMathScratch2, workidreg, wordKind, Kind.Int); asm.emit("add", waveMathScratch1, waveMathScratch1, waveMathScratch2); - HSAILAddress neverRanStoreAddr = new HSAILAddressValue(Kind.Byte, waveMathScratch1, 0).toAddress(); + HSAILAddress neverRanStoreAddr = new HSAILAddressValue(wordLIRKind, waveMathScratch1, 0).toAddress(); asm.emitStore(Kind.Byte, Constant.forInt(1), neverRanStoreAddr); asm.emitString("ret;"); @@ -827,7 +837,7 @@ asm.emitString0(asm.getDeoptLabelName() + ":\n"); String labelExit = asm.getDeoptLabelName() + "_Exit"; - HSAILAddress deoptInfoAddr = new HSAILAddressValue(Kind.Int, scratch64, config.hsailDeoptOccurredOffset).toAddress(); + HSAILAddress deoptInfoAddr = new HSAILAddressValue(wordLIRKind, scratch64, config.hsailDeoptOccurredOffset).toAddress(); asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64"); // Set deopt occurred flag @@ -836,13 +846,16 @@ asm.emitComment("// Determine next deopt save slot"); asm.emitAtomicAdd(scratch32, deoptNextIndexAddr, Constant.forInt(1)); - // scratch32 now holds next index to use - // set error condition if no room in save area + /* + * scratch32 now holds next index to use set error condition if no room in save area + */ asm.emitComment("// assert room to save deopt"); asm.emitCompare(Kind.Int, scratch32, Constant.forInt(maxDeoptIndex), "lt", false, false); asm.cbr("@L_StoreDeopt"); - // if assert fails, store a guaranteed negative workitemid in top level deopt occurred - // flag + /* + * if assert fails, store a guaranteed negative workitemid in top level deopt occurred + * flag + */ asm.emitWorkItemAbsId(scratch32); asm.emit("mad", scratch32, scratch32, Constant.forInt(-1), Constant.forInt(-1)); asm.emitStore(scratch32, deoptInfoAddr); @@ -861,14 +874,14 @@ // Add offset to _deopt_save_states[0] asm.emit("add", scratch64, cuSaveAreaPtr, Constant.forInt(offsetToDeoptSaveStates)); - HSAILAddress workItemAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeoptimizationWorkItem).toAddress(); - HSAILAddress actionReasonStoreAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeoptimizationReason).toAddress(); + HSAILAddress workItemAddr = new HSAILAddressValue(wordLIRKind, scratch64, offsetToDeoptimizationWorkItem).toAddress(); + HSAILAddress actionReasonStoreAddr = new HSAILAddressValue(wordLIRKind, scratch64, offsetToDeoptimizationReason).toAddress(); asm.emitComment("// Get _deopt_info._first_frame"); asm.emit("add", waveMathScratch1, scratch64, Constant.forInt(offsetToDeoptimizationFrame)); // Now scratch64 is the _deopt_info._first_frame - HSAILAddress pcStoreAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToFramePc).toAddress(); - HSAILAddress regCountsAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToNumSaves).toAddress(); + HSAILAddress pcStoreAddr = new HSAILAddressValue(wordLIRKind, waveMathScratch1, offsetToFramePc).toAddress(); + HSAILAddress regCountsAddr = new HSAILAddressValue(wordLIRKind, waveMathScratch1, offsetToNumSaves).toAddress(); asm.emitComment("// store deopting workitem"); asm.emitWorkItemAbsId(scratch32); asm.emitStore(Kind.Int, scratch32, workItemAddr); @@ -880,24 +893,26 @@ asm.emitComment("// store regCounts (" + numSRegs + " $s registers, " + numDRegs + " $d registers, " + numStackSlots + " stack slots)"); asm.emitStore(Kind.Int, Constant.forInt(numSRegs + (numDRegs << 8) + (numStackSlots << 16)), regCountsAddr); - // loop thru the usedValues storing each of the registers that are used. - // we always store in a fixed location, even if some registers are skipped + /* + * Loop thru the usedValues storing each of the registers that are used. We always store + * in a fixed location, even if some registers are skipped. + */ asm.emitComment("// store used regs"); for (Register reg : infoUsedRegs) { if (hsailRegConfig.isAllocatableSReg(reg)) { // 32 bit registers Kind kind = Kind.Int; int ofst = offsetToSaveArea + reg.encoding * 4; - HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress(); - AllocatableValue regValue = reg.asValue(kind); + HSAILAddress addr = new HSAILAddressValue(wordLIRKind, waveMathScratch1, ofst).toAddress(); + AllocatableValue regValue = reg.asValue(LIRKind.value(kind)); asm.emitStore(kind, regValue, addr); } else if (hsailRegConfig.isAllocatableDReg(reg)) { // 64 bit registers Kind kind = Kind.Long; // d reg ofst starts past the 32 sregs int ofst = offsetToSaveArea + (numSRegs * 4) + reg.encoding * 8; - HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress(); - AllocatableValue regValue = reg.asValue(kind); + HSAILAddress addr = new HSAILAddressValue(wordLIRKind, waveMathScratch1, ofst).toAddress(); + AllocatableValue regValue = reg.asValue(LIRKind.value(kind)); asm.emitStore(kind, regValue, addr); } else { throw GraalInternalError.unimplemented(); @@ -912,7 +927,7 @@ Kind kind = slot.getKind(); int sizeInBits = (kind.isObject() || kind.getByteCount() == 8 ? 64 : 32); int ofst = offsetToSaveArea + (numSRegs * 4) + (numDRegs * 8) + HSAIL.getStackOffsetStart(slot, sizeInBits); - HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress(); + HSAILAddress addr = new HSAILAddressValue(wordLIRKind, waveMathScratch1, ofst).toAddress(); if (sizeInBits == 64) { asm.emitSpillLoad(kind, scratch64, slot); asm.emitStore(kind, scratch64, addr); @@ -961,11 +976,11 @@ private int intsPerInfopoint; int[] build(List infoList, int numSRegs, int numDRegs, int numStackSlots, HSAILHotSpotRegisterConfig hsailRegConfig) { - // we are told that infoList is always sorted - // each infoPoint can have a different oopMap - - // since numStackSlots is the number of 8-byte stack slots used, it is an upper limit on - // the number of oop stack slots + /* + * We are told that infoList is always sorted. Each infoPoint can have a different + * oopMap. Since numStackSlots is the number of 8-byte stack slots used, it is an upper + * limit on the number of oop stack slots + */ int bitsPerInfopoint = numDRegs + numStackSlots; int intsForBits = (bitsPerInfopoint + 31) / 32; int numInfopoints = infoList.size(); @@ -1045,10 +1060,6 @@ int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint + 1 + intIndex; return array[arrIndex]; } - - public static int getSaveAreaCounts(int[] array) { - return array[SAVEAREACOUNTS_OFST]; - } } private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List deopts, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs, int numDRegs) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -72,7 +72,7 @@ final int stackFrameAlignment = 8; final int implicitNullCheckLimit = 0; final boolean inlineObjects = true; - return new HotSpotTargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); + return new HotSpotTargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); } public String getArchitecture() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,7 +33,6 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.gen.*; @@ -44,11 +43,13 @@ import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp; import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp; import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp; +import com.oracle.graal.lir.hsail.HSAILMove.LoadAcquireOp; import com.oracle.graal.lir.hsail.HSAILMove.LoadOp; -import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp; import com.oracle.graal.lir.hsail.HSAILMove.StoreOp; +import com.oracle.graal.lir.hsail.HSAILMove.StoreReleaseOp; +import com.oracle.graal.lir.hsail.HSAILMove.WorkItemAbsIdOp; import com.oracle.graal.phases.util.*; /** @@ -106,28 +107,23 @@ } } - private static Kind getMemoryKind(PlatformKind kind) { - if (kind == NarrowOopStamp.NarrowOop) { - return Kind.Int; - } else { - return (Kind) kind; - } + @Override + public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) { + HSAILAddressValue loadAddress = asAddressValue(address); + Variable result = newVariable(kind); + append(new LoadOp((Kind) kind.getPlatformKind(), result, loadAddress, state)); + return result; } - @Override - public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { + public Variable emitLoadAcquire(LIRKind kind, Value address, LIRFrameState state) { HSAILAddressValue loadAddress = asAddressValue(address); Variable result = newVariable(kind); - if (kind == NarrowOopStamp.NarrowOop) { - append(new LoadOp(Kind.Int, result, loadAddress, state)); - } else { - append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); - } + append(new LoadAcquireOp((Kind) kind.getPlatformKind(), result, loadAddress, state)); return result; } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { + public void emitStore(LIRKind kind, Value address, Value inputVal, LIRFrameState state) { HSAILAddressValue storeAddress = asAddressValue(address); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); @@ -135,38 +131,41 @@ c = Constant.INT_0; } if (canStoreConstant(c)) { - append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); + append(new StoreConstantOp((Kind) kind.getPlatformKind(), storeAddress, c, state)); return; } } Variable input = load(inputVal); - if (kind == NarrowOopStamp.NarrowOop) { - append(new StoreOp(Kind.Int, storeAddress, input, state)); - } else { - append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); - } + append(new StoreOp((Kind) kind.getPlatformKind(), storeAddress, input, state)); + } + + public void emitStoreRelease(LIRKind kind, Value address, Value inputVal, LIRFrameState state) { + HSAILAddressValue storeAddress = asAddressValue(address); + // TODO: handle Constants here + Variable input = load(inputVal); + append(new StoreReleaseOp((Kind) kind.getPlatformKind(), storeAddress, input, state)); } public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { - PlatformKind kind = newValue.getPlatformKind(); - assert kind == expectedValue.getPlatformKind(); - Kind memKind = getMemoryKind(kind); + LIRKind kind = newValue.getLIRKind(); + assert kind.equals(expectedValue.getLIRKind()); + Kind memKind = (Kind) kind.getPlatformKind(); HSAILAddressValue addressValue = asAddressValue(address); Variable expected = emitMove(expectedValue); Variable casResult = newVariable(kind); append(new CompareAndSwapOp(memKind, casResult, addressValue, expected, asAllocatable(newValue))); - assert trueValue.getPlatformKind() == falseValue.getPlatformKind(); - Variable nodeResult = newVariable(trueValue.getPlatformKind()); + assert trueValue.getLIRKind().equals(falseValue.getLIRKind()); + Variable nodeResult = newVariable(trueValue.getLIRKind()); append(new CondMoveOp(HSAILLIRGenerator.mapKindToCompareOp(memKind), casResult, expected, nodeResult, Condition.EQ, trueValue, falseValue)); return nodeResult; } @Override public Value emitAtomicReadAndAdd(Value address, Value delta) { - PlatformKind kind = delta.getPlatformKind(); - Kind memKind = getMemoryKind(kind); + LIRKind kind = delta.getLIRKind(); + Kind memKind = (Kind) kind.getPlatformKind(); Variable result = newVariable(kind); HSAILAddressValue addressValue = asAddressValue(address); append(new HSAILMove.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta))); @@ -175,8 +174,8 @@ @Override public Value emitAtomicReadAndWrite(Value address, Value newValue) { - PlatformKind kind = newValue.getPlatformKind(); - Kind memKind = getMemoryKind(kind); + LIRKind kind = newValue.getLIRKind(); + Kind memKind = (Kind) kind.getPlatformKind(); Variable result = newVariable(kind); HSAILAddressValue addressValue = asAddressValue(address); append(new HSAILMove.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue))); @@ -204,13 +203,13 @@ */ @Override public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { - Variable result = newVariable(Kind.Object); // linkage.getDescriptor().getResultType()); + Variable result = newVariable(LIRKind.reference(Kind.Object)); // linkage.getDescriptor().getResultType()); // to make the LIRVerifier happy, we move any constants into registers Value[] argLocations = new Value[args.length]; for (int i = 0; i < args.length; i++) { Value arg = args[i]; - AllocatableValue loc = newVariable(arg.getKind()); + AllocatableValue loc = newVariable(arg.getLIRKind()); emitMove(loc, arg); argLocations[i] = loc; } @@ -235,23 +234,13 @@ @Override protected HSAILLIRInstruction createMove(AllocatableValue dst, Value src) { - if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) { - if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(src)) { - return new MoveToRegOp(Kind.Int, dst, Constant.INT_0); - } else if (src instanceof HotSpotObjectConstant) { - if (HotSpotObjectConstant.isCompressed((Constant) src)) { - Variable uncompressed = newVariable(Kind.Object); - append(new MoveToRegOp(Kind.Object, uncompressed, src)); - CompressEncoding oopEncoding = config.getOopEncoding(); - return new HSAILMove.CompressPointer(dst, newVariable(Kind.Object), uncompressed, oopEncoding.base, oopEncoding.shift, oopEncoding.alignment, true); - } else { - return new MoveToRegOp(Kind.Object, dst, src); - } - } else if (isRegister(src) || isStackSlot(dst)) { - return new MoveFromRegOp(Kind.Int, dst, src); - } else { - return new MoveToRegOp(Kind.Int, dst, src); - } + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(src)) { + return new MoveToRegOp(Kind.Int, dst, Constant.INT_0); + } else if (src instanceof HotSpotObjectConstant && HotSpotObjectConstant.isCompressed((Constant) src)) { + Variable uncompressed = newVariable(LIRKind.reference(Kind.Object)); + append(new MoveToRegOp(Kind.Object, uncompressed, src)); + CompressEncoding oopEncoding = config.getOopEncoding(); + return new HSAILMove.CompressPointer(dst, newVariable(LIRKind.reference(Kind.Object)), uncompressed, oopEncoding.base, oopEncoding.shift, oopEncoding.alignment, true); } else { return super.createMove(dst, src); } @@ -292,14 +281,14 @@ @Override public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { - Variable result = newVariable(NarrowOopStamp.NarrowOop); - append(new HSAILMove.CompressPointer(result, newVariable(pointer.getPlatformKind()), asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull)); + Variable result = newVariable(LIRKind.reference(Kind.Int)); + append(new HSAILMove.CompressPointer(result, newVariable(pointer.getLIRKind()), asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull)); return result; } @Override public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) { - Variable result = newVariable(Kind.Object); + Variable result = newVariable(LIRKind.reference(Kind.Object)); append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull)); return result; } @@ -310,8 +299,14 @@ public void emitNullCheck(Value address, LIRFrameState state) { assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!"; - Variable obj = newVariable(Kind.Object); + Variable obj = newVariable(LIRKind.reference(Kind.Object)); emitMove(obj, address); append(new HSAILMove.NullCheckOp(obj, state)); } + + public Variable emitWorkItemAbsId() { + Variable result = newVariable(LIRKind.value(Kind.Int)); + append(new WorkItemAbsIdOp(result)); + return result; + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Mon Jun 30 12:02:19 2014 +0200 @@ -78,12 +78,12 @@ } public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Kind kind = x.newValue().getKind(); - assert kind == x.expectedValue().getKind(); - Variable expected = getGen().load(operand(x.expectedValue())); Variable newVal = getGen().load(operand(x.newValue())); + LIRKind kind = newVal.getLIRKind(); + assert kind.equals(expected.getLIRKind()); + int disp = 0; HSAILAddressValue address; Value index = operand(x.offset()); @@ -95,8 +95,8 @@ throw GraalInternalError.shouldNotReachHere("NYI"); } - Variable casResult = newVariable(kind); - append(new CompareAndSwapOp(kind, casResult, address, expected, newVal)); + Variable casResult = gen.newVariable(kind); + append(new CompareAndSwapOp((Kind) kind.getPlatformKind(), casResult, address, expected, newVal)); setResult(x, casResult); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -29,7 +29,6 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hsail.*; /** @@ -107,7 +106,7 @@ if (!stackOnly && currentRegs32 < generalParameterRegisters.length) { Register register = generalParameterRegisters[currentRegs32++]; - locations[i] = register.asValue(kind); + locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Long: @@ -115,7 +114,7 @@ case Double: if (!stackOnly && currentRegs64 < longParameterRegisters.length) { Register register = longParameterRegisters[currentRegs64++]; - locations[i] = register.asValue(kind); + locations[i] = register.asValue(target.getLIRKind(kind)); } break; default: @@ -123,13 +122,13 @@ } if (locations[i] == null) { - locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); + locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out); currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); - AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind); + AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(target.getLIRKind(returnKind)); return new CallingConvention(currentStackOffset, returnLocation, locations); } @@ -145,14 +144,7 @@ @Override public Register[] getAllocatableRegisters(PlatformKind kind) { - Kind primitiveKind; - if (kind == NarrowOopStamp.NarrowOop) { - primitiveKind = Kind.Int; - } else { - primitiveKind = (Kind) kind; - } - - switch (primitiveKind) { + switch ((Kind) kind) { case Int: case Short: case Byte: diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; @@ -41,6 +42,7 @@ private final Replacements host; private HashSet ignoredResolvedMethods = new HashSet<>(); + private HashMap arrayCopyRedirectMethods = new HashMap<>(); public HSAILHotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, Assumptions assumptions, TargetDescription target, Replacements host) { super(providers, snippetReflection, assumptions, target); @@ -63,6 +65,28 @@ // Register the ignored substitutions addIgnoredResolvedMethod(String.class, "equals", Object.class); + + /* + * Register the special arraycopy snippet handling This basically ignores the sense of the + * CallArrayCopy flag and always directs to the snippets from UnsafeArrayCopyNode + */ + redirectArraycopySnippetMethod(Kind.Byte); + redirectArraycopySnippetMethod(Kind.Boolean); + redirectArraycopySnippetMethod(Kind.Char); + redirectArraycopySnippetMethod(Kind.Short); + redirectArraycopySnippetMethod(Kind.Int); + redirectArraycopySnippetMethod(Kind.Long); + redirectArraycopySnippetMethod(Kind.Float); + redirectArraycopySnippetMethod(Kind.Double); + redirectArraycopySnippetMethod(Kind.Object); + } + + private void redirectArraycopySnippetMethod(Kind kind) { + ResolvedJavaMethod foreignCallMethod = providers.getMetaAccess().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(kind, false, true)); + ResolvedJavaMethod nonForeignCallMethod = providers.getMetaAccess().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(kind, false, false)); + if (!foreignCallMethod.equals(nonForeignCallMethod)) { + arrayCopyRedirectMethods.put(foreignCallMethod, nonForeignCallMethod); + } } @Override @@ -75,25 +99,42 @@ public Class getMacroSubstitution(ResolvedJavaMethod method) { Class klass = super.getMacroSubstitution(method); if (klass == null) { - // eventually we want to only defer certain macro substitutions to the host, but for now - // we will do everything + /* + * Eventually we want to only defer certain macro substitutions to the host, but for now + * we will do everything. + */ return host.getMacroSubstitution(method); } return klass; } @Override - public StructuredGraph getSnippet(ResolvedJavaMethod method) { - // Must work in cooperation with HSAILHotSpotLoweringProvider - return host.getSnippet(method); + public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry) { + /* + * Must work in cooperation with HSAILHotSpotLoweringProvider. Before asking for the host + * snippet, see if it is one of the arraycopy methods which we want to redirect to the + * non-foreign-call version, regardless of the sense of CallArrayCopy option + */ + ResolvedJavaMethod snippetMethod = method; + ResolvedJavaMethod snippetRecursiveEntry = recursiveEntry; + ResolvedJavaMethod redirect = arrayCopyRedirectMethods.get(method); + if (redirect != null) { + snippetMethod = redirect; + if (recursiveEntry != null && recursiveEntry.equals(method)) { + snippetRecursiveEntry = redirect; + } + } + return host.getSnippet(snippetMethod, snippetRecursiveEntry); } @Override public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) { StructuredGraph m = super.getMethodSubstitution(original); if (m == null) { - // we check for a few special cases we do NOT want to defer here - // but basically we defer everything else to the host + /* + * We check for a few special cases we do NOT want to defer here but basically we defer + * everything else to the host. + */ if (ignoredResolvedMethods.contains(original)) { return null; } else { @@ -102,5 +143,4 @@ } return m; } - } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -61,23 +61,23 @@ masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */"); String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos; - AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object); - AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object); - AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); + AllocatableValue scratch64 = HSAIL.d16.asValue(LIRKind.reference(Kind.Object)); + AllocatableValue spAddrReg = HSAIL.d17.asValue(LIRKind.reference(Kind.Object)); + AllocatableValue scratch32 = HSAIL.s34.asValue(LIRKind.value(Kind.Int)); masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64"); // Build address of noticeSafepoints field - HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress(); + HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(LIRKind.value(Kind.Long), scratch64, offsetToNoticeSafepoints).toAddress(); masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr); // Load int value from that field - HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress(); + HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(LIRKind.value(Kind.Long), spAddrReg, 0).toAddress(); masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr); masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false); masm.cbr(afterSafepointLabel); - AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); - AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); + AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(LIRKind.value(Kind.Int)); + AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(LIRKind.value(Kind.Int)); masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); masm.emitJumpToLabelName(masm.getDeoptLabelName()); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectLoadAcquireNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectLoadAcquireNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, 2014, 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.hsail.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.hotspot.hsail.*; +import com.oracle.graal.word.*; + +public class HSAILDirectLoadAcquireNode extends DirectReadNode { + + public HSAILDirectLoadAcquireNode(ValueNode address, Kind readKind) { + super(address, readKind); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + HSAILHotSpotLIRGenerator hsailgen = (HSAILHotSpotLIRGenerator) (gen.getLIRGeneratorTool()); + LIRKind kind = hsailgen.getLIRKind(stamp()); + Value result = hsailgen.emitLoadAcquire(kind, gen.operand(getAddress()), null); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native long loadAcquire(long address, @ConstantNodeParameter Kind kind); + + public static long loadAcquireLong(Word address) { + return loadAcquire(address.rawValue(), Kind.Long); + } + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectStoreReleaseNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILDirectStoreReleaseNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, 2014, 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.hsail.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.hotspot.hsail.*; +import com.oracle.graal.word.*; + +public class HSAILDirectStoreReleaseNode extends DirectStoreNode { + + public HSAILDirectStoreReleaseNode(ValueNode address, ValueNode value, Kind kind) { + super(address, value, kind); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + HSAILHotSpotLIRGenerator hsailgen = (HSAILHotSpotLIRGenerator) (gen.getLIRGeneratorTool()); + Value v = gen.operand(getValue()); + LIRKind kind = hsailgen.getLIRKind(getValue().stamp()); + hsailgen.emitStoreRelease(kind, gen.operand(getAddress()), v, null); + } + + @NodeIntrinsic + public static native void storeRelease(long address, long value, @ConstantNodeParameter Kind kind); + + public static void storeReleaseLong(Word address, long value) { + storeRelease(address.rawValue(), value, Kind.Long); + } + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java Mon Jun 30 12:02:19 2014 +0200 @@ -43,11 +43,37 @@ hsailRegisters = registers; } + public static final LocationIdentity TLAB_INFO_LOCATION = new NamedLocationIdentity("TlabInfo"); + public static final LocationIdentity TLABINFO_LASTGOODTOP_LOCATION = new NamedLocationIdentity("TlabInfoLastGoodTop"); + public static final LocationIdentity TLABINFO_END_LOCATION = new NamedLocationIdentity("TlabInfoEnd"); + public static final LocationIdentity TLABINFO_TOP_LOCATION = new NamedLocationIdentity("TlabInfoTop"); + public static final LocationIdentity TLABINFO_START_LOCATION = new NamedLocationIdentity("TlabInfoStart"); + public static final LocationIdentity TLABINFO_ALLOCINFO_LOCATION = new NamedLocationIdentity("TlabInfoAllocInfo"); + public static final LocationIdentity TLABINFO_ORIGINALTOP_LOCATION = new NamedLocationIdentity("TlabInfoOriginalTop"); + public static final LocationIdentity TLABINFO_DONORTHREAD_LOCATION = new NamedLocationIdentity("TlabInfoDonorThread"); + + public static final LocationIdentity ALLOCINFO_TLABINFOSPOOLNEXT_LOCATION = new NamedLocationIdentity("AllocInfoTlabInfosPoolNext"); + public static final LocationIdentity ALLOCINFO_TLABINFOSPOOLEND_LOCATION = new NamedLocationIdentity("AllocInfoTlabInfosPoolEnd"); + public static final LocationIdentity ALLOCINFO_TLABALIGNRESERVEBYTES_LOCATION = new NamedLocationIdentity("AllocInfoTlabAlignreservebytes"); + /** - * Gets the value of the thread register as a Word. + * Gets the value of the thread register as a Word. There is a level of indirection here. Thread + * register actually points to a holder for tlab info. */ - public static Word thread() { - return registerAsWord(threadRegister(), true, false); + public static Word getTlabInfoPtr() { + Word threadRegAsWord = registerAsWord(threadRegister(), true, false); + return threadRegAsWord.readWord(0, TLAB_INFO_LOCATION); + } + + public static Word getTlabInfoPtrLoadAcquire() { + Word threadRegAsWord = registerAsWord(threadRegister(), true, false); + return Word.unsigned(HSAILDirectLoadAcquireNode.loadAcquireLong(threadRegAsWord)); + } + + public static void writeTlabInfoPtrStoreRelease(Word val) { + // this only gets done in the waiting loop so we will always use Store Release + Word threadRegAsWord = registerAsWord(threadRegister(), true, false); + HSAILDirectStoreReleaseNode.storeReleaseLong(threadRegAsWord, val.rawValue()); } @Fold @@ -55,19 +81,64 @@ return hsailRegisters.getThreadRegister(); } - public static Word atomicGetAndAddTlabTop(Word thread, int size) { - return Word.unsigned(AtomicReadAndAddNode.getAndAddLong(null, thread.rawValue() + threadTlabTopOffset(), size, TLAB_TOP_LOCATION)); + public static Word atomicGetAndAddTlabInfoTop(Word tlabInfo, int delta) { + return Word.unsigned(AtomicReadAndAddNode.getAndAddLong(null, tlabInfo.rawValue() + config().hsailTlabInfoTopOffset, delta, TLABINFO_TOP_LOCATION)); + } + + public static Word readTlabInfoEnd(Word tlabInfo) { + return tlabInfo.readWord(config().hsailTlabInfoEndOffset, TLABINFO_END_LOCATION); + } + + public static Word readTlabInfoStart(Word tlabInfo) { + return tlabInfo.readWord(config().hsailTlabInfoStartOffset, TLABINFO_START_LOCATION); + } + + public static void writeTlabInfoLastGoodTop(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoLastGoodTopOffset, val, TLABINFO_LASTGOODTOP_LOCATION); + } + + public static void writeTlabInfoStart(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoStartOffset, val, TLABINFO_START_LOCATION); + } + + public static void writeTlabInfoTop(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoTopOffset, val, TLABINFO_TOP_LOCATION); + } + + public static void writeTlabInfoEnd(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoEndOffset, val, TLABINFO_END_LOCATION); } - public static final LocationIdentity TLAB_PFTOP_LOCATION = new NamedLocationIdentity("TlabPfTop"); + public static Word readTlabInfoAllocInfo(Word tlabInfo) { + return tlabInfo.readWord(config().hsailTlabInfoAllocInfoOffset, TLABINFO_ALLOCINFO_LOCATION); + } - @Fold - public static int threadTlabPfTopOffset() { - return config().threadTlabPfTopOffset(); + public static void writeTlabInfoAllocInfo(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoAllocInfoOffset, val, TLABINFO_ALLOCINFO_LOCATION); + } + + public static void writeTlabInfoOriginalTop(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoOriginalTopOffset, val, TLABINFO_ORIGINALTOP_LOCATION); } - public static void writeTlabPfTop(Word thread, Word val) { - thread.writeWord(threadTlabPfTopOffset(), val, TLAB_PFTOP_LOCATION); + public static void writeTlabInfoDonorThread(Word tlabInfo, Word val) { + tlabInfo.writeWord(config().hsailTlabInfoDonorThreadOffset, val, TLABINFO_DONORTHREAD_LOCATION); + } + + public static Word readTlabInfoDonorThread(Word tlabInfo) { + return tlabInfo.readWord(config().hsailTlabInfoDonorThreadOffset, TLABINFO_DONORTHREAD_LOCATION); + } + + public static Word readAllocInfoTlabInfosPoolEnd(Word allocInfo) { + return allocInfo.readWord(config().hsailAllocInfoTlabInfosPoolEndOffset, ALLOCINFO_TLABINFOSPOOLEND_LOCATION); + } + + public static Word readAllocInfoTlabAlignReserveBytes(Word allocInfo) { + return allocInfo.readWord(config().hsailAllocInfoTlabAlignReserveBytesOffset, ALLOCINFO_TLABALIGNRESERVEBYTES_LOCATION); + } + + public static Word atomicGetAndAddAllocInfoTlabInfosPoolNext(Word allocInfo, int delta) { + return Word.unsigned(AtomicReadAndAddNode.getAndAddLong(null, allocInfo.rawValue() + config().hsailAllocInfoTlabInfosPoolNextOffset, delta, ALLOCINFO_TLABINFOSPOOLNEXT_LOCATION)); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Mon Jun 30 12:02:19 2014 +0200 @@ -60,6 +60,9 @@ @Option(help = "In HSAIL allocation, allow allocation from eden as fallback if TLAB is full") static final OptionValue HsailUseEdenAllocate = new OptionValue<>(false); + @Option(help = "In HSAIL allocation, allow GPU to allocate a new tlab if TLAB is full") + static final OptionValue HsailNewTlabAllocate = new OptionValue<>(true); + @Option(help = "Estimate of number of bytes allocated by each HSAIL workitem, used to size TLABs") static public final OptionValue HsailAllocBytesPerWorkitem = new OptionValue<>(64); @@ -67,44 +70,130 @@ } private static final boolean hsailUseEdenAllocate = HsailUseEdenAllocate.getValue(); + private static final boolean hsailNewTlabAllocate = HsailNewTlabAllocate.getValue(); + + protected static Word fillNewTlabInfoWithTlab(Word oldTlabInfo) { + Word allocInfo = readTlabInfoAllocInfo(oldTlabInfo); + Word newTlabInfo = atomicGetAndAddAllocInfoTlabInfosPoolNext(allocInfo, config().hsailTlabInfoSize); + Word tlabInfosPoolEnd = readAllocInfoTlabInfosPoolEnd(allocInfo); + if (newTlabInfo.aboveOrEqual(tlabInfosPoolEnd)) { + // could not get a new tlab info, mark zero and we will later deoptimize + return (Word.zero()); + } + + // make new size depend on old tlab size + Word newTlabSize = readTlabInfoEnd(oldTlabInfo).subtract(readTlabInfoStart(oldTlabInfo)); + // try to allocate a new tlab + Word tlabStart = NewInstanceStub.edenAllocate(newTlabSize, false); + writeTlabInfoStart(newTlabInfo, tlabStart); // write this field even if zero + if (tlabStart.equal(0)) { + // could not get a new tlab, mark zero and we will later deoptimize + return (Word.zero()); + } + // here we have a new tlab and a tlabInfo, we can fill it in + writeTlabInfoTop(newTlabInfo, tlabStart); + writeTlabInfoOriginalTop(newTlabInfo, tlabStart); + // set end so that we leave space for the tlab "alignment reserve" + Word alignReserveBytes = readAllocInfoTlabAlignReserveBytes(allocInfo); + writeTlabInfoEnd(newTlabInfo, tlabStart.add(newTlabSize.subtract(alignReserveBytes))); + writeTlabInfoAllocInfo(newTlabInfo, allocInfo); + writeTlabInfoDonorThread(newTlabInfo, readTlabInfoDonorThread(oldTlabInfo)); + return (newTlabInfo); + } + + protected static Word allocateFromTlabSlowPath(Word fastPathTlabInfo, int size, Word fastPathTop, Word fastPathEnd) { + // eventually this will be a separate call, not inlined + + // we come here from the fastpath allocation + // here we know that the tlab has overflowed (top + size > end) + // find out if we are the first overflower + Word tlabInfo = fastPathTlabInfo; + Word top = fastPathTop; + Word end = fastPathEnd; + + // start a loop where we try to get a new tlab and then try to allocate from it + // keep doing this until we run out of tlabs or tlabInfo structures + // initialize result with error return value + Word result = Word.zero(); + while (result.equal(Word.zero()) && tlabInfo.notEqual(Word.zero())) { + boolean firstOverflower = top.belowOrEqual(end); + if (firstOverflower) { + // store the last good top before overflow into last_good_top field + // we will move it back into top later when back in the VM + writeTlabInfoLastGoodTop(tlabInfo, top); + } + + // if all this allocate tlab from gpu logic is disabled, + // just immediately set tlabInfo to 0 here + if (!hsailNewTlabAllocate) { + tlabInfo = Word.zero(); + } else { + // loop here waiting for the first overflower to get a new tlab + // note that on an hsa device we must be careful how we loop in order to ensure + // "forward progress". For example we must not break out of the loop. + Word oldTlabInfo = tlabInfo; + do { + if (firstOverflower) { + // allocate new tlabInfo and new tlab to fill it, returning 0 if any + // problems + // this will get all spinners out of this loop. + tlabInfo = fillNewTlabInfoWithTlab(oldTlabInfo); + writeTlabInfoPtrStoreRelease(tlabInfo); + } else { + tlabInfo = getTlabInfoPtrLoadAcquire(); + } + } while (tlabInfo.equal(oldTlabInfo)); + // when we get out of the loop if tlabInfoPtr contains 0, it means we + // can't get any more tlabs and will have to deoptimize + // otherwise, we have a valid new tlabInfo/tlab and can try to allocate again. + if (tlabInfo.notEqual(0)) { + top = atomicGetAndAddTlabInfoTop(tlabInfo, size); + end = readTlabInfoEnd(tlabInfo); + Word newTop = top.add(size); + if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { + result = top; + } + } + } + } // while (result == 0) && (tlabInfo != 0)) + return result; + } + + protected static Object addressToFormattedObject(Word addr, @ConstantParameter int size, Word hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, + @ConstantParameter String typeContext) { + Object result = formatObject(hub, size, addr, prototypeMarkWord, fillContents, true, true); + profileAllocation("instance", size, typeContext); + return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + } @Snippet public static Object allocateInstanceAtomic(@ConstantParameter int size, Word hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, @ConstantParameter String typeContext) { - Word thread = thread(); boolean haveResult = false; if (useTLAB()) { - Word top = atomicGetAndAddTlabTop(thread, size); - Word end = readTlabEnd(thread); - Word newTop = top.add(size); - if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { - // writeTlabTop(thread, newTop) was done by the atomicGetAndAdd - Object result = formatObject(hub, size, top, prototypeMarkWord, fillContents, true, false, true); - profileAllocation("instance", size, typeContext); - return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); - } else { - // only one overflower will be the first overflower, detectable because - // oldtop was still below end - if (top.belowOrEqual(end)) { - // hack alert: store the last good top before overflow into pf_top - // we will move it back into top later when back in the VM - writeTlabPfTop(thread, top); + // inlining this manually here because it resulted in better fastpath codegen + Word tlabInfo = getTlabInfoPtr(); + if (probability(FAST_PATH_PROBABILITY, tlabInfo.notEqual(0))) { + Word top = atomicGetAndAddTlabInfoTop(tlabInfo, size); + Word end = readTlabInfoEnd(tlabInfo); + Word newTop = top.add(size); + if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { + return addressToFormattedObject(top, size, hub, prototypeMarkWord, fillContents, typeContext); + } else { + Word addr = allocateFromTlabSlowPath(tlabInfo, size, top, end); + if (addr.notEqual(0)) { + return addressToFormattedObject(addr, size, hub, prototypeMarkWord, fillContents, typeContext); + } } - // useless logic but see notes on deopt path below - haveResult = newTop.belowOrEqual(end); } } + + // we could not allocate from tlab, try allocating directly from eden if (hsailUseEdenAllocate) { - // originally: - // result = NewInstanceStubCall.call(hub); - - // we could not allocate from tlab, try allocating directly from eden // false for no logging - Word memory = NewInstanceStub.edenAllocate(Word.unsigned(size), false); - if (memory.notEqual(0)) { + Word addr = NewInstanceStub.edenAllocate(Word.unsigned(size), false); + if (addr.notEqual(0)) { new_eden.inc(); - Object result = formatObject(hub, size, memory, prototypeMarkWord, fillContents, true, false, true); - profileAllocation("instance", size, typeContext); - return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + return addressToFormattedObject(addr, size, hub, prototypeMarkWord, fillContents, typeContext); } } // haveResult test here helps avoid dropping earlier stores were seen to be dropped without @@ -126,44 +215,43 @@ return allocateArrayAtomicImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, maybeUnroll, typeContext); } + protected static Object addressToFormattedArray(Word addr, int allocationSize, int length, int headerSize, Word hub, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll, + @ConstantParameter String typeContext) { + // we are not in a stub so we can set useSnippetCounters to true + Object result = formatArray(hub, allocationSize, length, headerSize, addr, prototypeMarkWord, fillContents, maybeUnroll, true); + profileAllocation("array", allocationSize, typeContext); + return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + } + private static Object allocateArrayAtomicImpl(Word hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, boolean maybeUnroll, String typeContext) { int alignment = wordSize(); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); - Word thread = thread(); boolean haveResult = false; if (useTLAB()) { - Word top = atomicGetAndAddTlabTop(thread, allocationSize); - Word end = readTlabEnd(thread); - Word newTop = top.add(allocationSize); - if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { - // writeTlabTop(thread, newTop) was done by the atomicGetAndAdd - newarray_loopInit.inc(); - // we are not in a stub so we can set useSnippetCounters to true - Object result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, true); - profileAllocation("array", allocationSize, typeContext); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); - } else { - // only one overflower will be the first overflower, detectable because - // oldtop was still below end - if (top.belowOrEqual(end)) { - // hack alert: store the last good top before overflow into pf_top - // we will move it back into top later when back in the VM - writeTlabPfTop(thread, top); + // inlining this manually here because it resulted in better fastpath codegen + Word tlabInfo = getTlabInfoPtr(); + if (probability(FAST_PATH_PROBABILITY, tlabInfo.notEqual(0))) { + Word top = atomicGetAndAddTlabInfoTop(tlabInfo, allocationSize); + Word end = readTlabInfoEnd(tlabInfo); + Word newTop = top.add(allocationSize); + if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { + return addressToFormattedArray(top, allocationSize, length, headerSize, hub, prototypeMarkWord, fillContents, maybeUnroll, typeContext); + } else { + Word addr = allocateFromTlabSlowPath(tlabInfo, allocationSize, top, end); + if (addr.notEqual(0)) { + return addressToFormattedArray(addr, allocationSize, length, headerSize, hub, prototypeMarkWord, fillContents, maybeUnroll, typeContext); + } } - // useless logic but see notes on deopt path below - haveResult = newTop.belowOrEqual(end); } } + // we could not allocate from tlab, try allocating directly from eden if (hsailUseEdenAllocate) { // false for no logging - Word memory = NewInstanceStub.edenAllocate(Word.unsigned(allocationSize), false); - if (memory.notEqual(0)) { + Word addr = NewInstanceStub.edenAllocate(Word.unsigned(allocationSize), false); + if (addr.notEqual(0)) { newarray_eden.inc(); - // we are not in a stub so we can set useSnippetCounters to true - Object result = formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents, maybeUnroll, true); - profileAllocation("array", allocationSize, typeContext); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + return addressToFormattedArray(addr, allocationSize, length, headerSize, hub, prototypeMarkWord, fillContents, maybeUnroll, typeContext); } } if (!haveResult) { @@ -225,12 +313,13 @@ Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); - args.add("length", newArrayNode.length()); + ValueNode length = newArrayNode.length(); + args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length)); args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); args.addConst("headerSize", headerSize); args.addConst("log2ElementSize", log2ElementSize); args.addConst("fillContents", newArrayNode.fillContents()); - args.addConst("maybeUnroll", newArrayNode.length().isConstant()); + args.addConst("maybeUnroll", length.isConstant()); args.addConst("typeContext", MetaUtil.toJavaName(arrayType, false)); SnippetTemplate template = template(args); @@ -250,6 +339,7 @@ private static final SnippetCounter new_eden = new SnippetCounter(countersNew, "eden", "used edenAllocate"); private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null; - private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + // private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, + // "tlabLoopInit", "TLAB alloc with zeroing in a loop"); private static final SnippetCounter newarray_eden = new SnippetCounter(countersNewArray, "eden", "used edenAllocate"); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILWorkItemAbsIdNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILWorkItemAbsIdNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.hsail.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.hotspot.hsail.*; + +public class HSAILWorkItemAbsIdNode extends FixedWithNextNode implements LIRLowerable { + + public HSAILWorkItemAbsIdNode() { + super(StampFactory.forKind(Kind.Int)); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + HSAILHotSpotLIRGenerator hsailgen = (HSAILHotSpotLIRGenerator) (gen.getLIRGeneratorTool()); + Value result = hsailgen.emitWorkItemAbsId(); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native int getWorkItemAbsId(); + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -93,7 +93,7 @@ final int stackFrameAlignment = 1; final int implicitNullCheckLimit = 0; final boolean inlineObjects = true; - return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); + return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); } public String getArchitecture() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -110,7 +110,7 @@ if (returnKind == Kind.Void) { returnLocation = Value.ILLEGAL; } else { - returnLocation = new Variable(returnKind, currentGeneral++); + returnLocation = new Variable(target.getLIRKind(returnKind), currentGeneral++); } AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; @@ -129,7 +129,7 @@ case Double: case Object: if (!stackOnly) { - locations[i] = new Variable(kind, currentGeneral++); + locations[i] = new Variable(target.getLIRKind(kind), currentGeneral++); } break; default: @@ -137,7 +137,7 @@ } if (locations[i] == null) { - locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); + locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out); currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java --- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java Mon Jun 30 12:02:19 2014 +0200 @@ -37,6 +37,26 @@ */ public class GenGraalRuntimeInlineHpp { + private static final ZipFile graalJar; + + static { + String path = null; + String classPath = System.getProperty("java.class.path"); + for (String e : classPath.split(File.pathSeparator)) { + if (e.endsWith("graal.jar")) { + path = e; + break; + } + } + ZipFile zipFile = null; + try { + zipFile = new ZipFile(Objects.requireNonNull(path, "Could not find graal.jar on class path: " + classPath)); + } catch (IOException e) { + throw new InternalError(e); + } + graalJar = zipFile; + } + public static void main(String[] args) { PrintStream out = System.out; try { @@ -52,17 +72,8 @@ * Generates code for {@code GraalRuntime::get_service_impls()}. */ private static void genGetServiceImpls(PrintStream out) throws Exception { - String graalJar = null; - String classPath = System.getProperty("java.class.path"); - for (String e : classPath.split(File.pathSeparator)) { - if (e.endsWith("graal.jar")) { - graalJar = e; - break; - } - } final List> services = new ArrayList<>(); - final ZipFile zipFile = new ZipFile(new File(Objects.requireNonNull(graalJar, "Could not find graal.jar on class path: " + classPath))); - for (final Enumeration e = zipFile.entries(); e.hasMoreElements();) { + for (final Enumeration e = graalJar.entries(); e.hasMoreElements();) { final ZipEntry zipEntry = e.nextElement(); String name = zipEntry.getName(); if (name.startsWith("META-INF/services/")) { @@ -129,8 +140,9 @@ } lengths.add("PrintFlags".length()); - out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS) {"); - out.println(" if (value[0] == '+' || value[0] == '-') {"); + out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS) {"); + out.println(" bool check_only = hotSpotOptionsClass.is_null();"); + out.println(" if (value != NULL && (value[0] == '+' || value[0] == '-')) {"); out.println(" // boolean options"); genMatchers(out, lengths, options, true); out.println(" } else {"); @@ -153,7 +165,11 @@ out.println(" case " + len + ":"); out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len); out.println(" if (value[0] == '+') {"); - out.println(" set_option_helper(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);"); + out.println(" if (check_only) {"); + out.println(" TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", THREAD);"); + out.println(" hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));"); + out.println(" }"); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);"); out.println(" }"); out.println(" return true;"); out.println(" }"); @@ -167,17 +183,28 @@ } out.printf(" if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len); Class declaringClass = desc.getDeclaringClass(); - out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), - toInternalName(getFieldType(desc))); if (isBoolean) { - out.println(" set_option_helper(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);"); + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), + toInternalName(getFieldType(desc))); + out.println(" if (!check_only) {"); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, value[0], Handle(), 0L);"); + out.println(" }"); } else if (desc.getType() == String.class) { - out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); - out.println(" set_option_helper(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);"); + out.println(" check_required_value(name, name_len, value, CHECK_(true));"); + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), + toInternalName(getFieldType(desc))); + out.println(" if (!check_only) {"); + out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);"); + out.println(" }"); } else { char spec = getPrimitiveSpecChar(desc); - out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));"); - out.println(" set_option_helper(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);"); + out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));"); + out.println(" if (!check_only) {"); + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), + toInternalName(getFieldType(desc))); + out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);"); + out.println(" }"); } out.println(" return true;"); out.println(" }"); @@ -191,7 +218,14 @@ static SortedMap getOptions() throws Exception { Field field = Class.forName("com.oracle.graal.hotspot.HotSpotOptionsLoader").getDeclaredField("options"); field.setAccessible(true); - return (SortedMap) field.get(null); + SortedMap options = (SortedMap) field.get(null); + + Set> checked = new HashSet<>(); + for (final OptionDescriptor option : options.values()) { + Class cls = option.getDeclaringClass(); + OptionsVerifier.checkClass(cls, option, checked, graalJar); + } + return options; } private static Class getFieldType(OptionDescriptor desc) throws Exception { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2014, 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.sourcegen; + +import static java.lang.String.*; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.zip.*; + +import jdk.internal.org.objectweb.asm.*; +import jdk.internal.org.objectweb.asm.Type; + +import com.oracle.graal.options.*; + +/** + * A {@link ClassVisitor} that verifies a class declaring one or more {@linkplain OptionValue + * options} has a class initializer that only initializes the option(s). This sanity check mitigates + * the possibility of an option value being used before the code that sets the value (e.g., from the + * command line) has been executed. + */ +final class OptionsVerifier extends ClassVisitor { + + public static void checkClass(Class cls, OptionDescriptor option, Set> checked, ZipFile graalJar) throws IOException { + if (!checked.contains(cls)) { + checked.add(cls); + Class superclass = cls.getSuperclass(); + if (superclass != null && !superclass.equals(Object.class)) { + checkClass(superclass, option, checked, graalJar); + } + + String classFilePath = cls.getName().replace('.', '/') + ".class"; + ZipEntry entry = Objects.requireNonNull(graalJar.getEntry(classFilePath), "Could not find class file for " + cls.getName()); + ClassReader cr = new ClassReader(graalJar.getInputStream(entry)); + + ClassVisitor cv = new OptionsVerifier(cls, option); + cr.accept(cv, 0); + } + } + + /** + * The option field context of the verification. + */ + private final OptionDescriptor option; + + /** + * The class in which {@link #option} is declared or a super-class of that class. This is the + * class whose {@code } method is being verified. + */ + private final Class cls; + + /** + * Source file context for error reporting. + */ + String sourceFile = null; + + /** + * Line number for error reporting. + */ + int lineNo = -1; + + final Class[] boxingTypes = {Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}; + + private static Class resolve(String name) { + try { + return Class.forName(name.replace('/', '.')); + } catch (ClassNotFoundException e) { + throw new InternalError(e); + } + } + + OptionsVerifier(Class cls, OptionDescriptor desc) { + super(Opcodes.ASM5); + this.cls = cls; + this.option = desc; + } + + @Override + public void visitSource(String source, String debug) { + this.sourceFile = source; + } + + void verify(boolean condition, String message) { + if (!condition) { + error(message); + } + } + + void error(String message) { + String errorMessage = format("%s:%d: Illegal code in %s. which may be executed when %s.%s is initialized:%n%n %s%n%n" + "The recommended solution is to move " + option.getName() + + " into a separate class (e.g., %s.Options).%n", sourceFile, lineNo, cls.getSimpleName(), option.getDeclaringClass().getSimpleName(), option.getName(), message, + option.getDeclaringClass().getSimpleName()); + throw new InternalError(errorMessage); + + } + + @Override + public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) { + if (name.equals("")) { + return new MethodVisitor(Opcodes.ASM5) { + + @Override + public void visitLineNumber(int line, Label start) { + lineNo = line; + } + + @Override + public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) { + if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { + verify(resolve(owner).equals(option.getDeclaringClass()), format("store to field %s.%s", resolve(owner).getSimpleName(), fieldName)); + verify(opcode != Opcodes.PUTFIELD, format("store to non-static field %s.%s", resolve(owner).getSimpleName(), fieldName)); + } + } + + private Executable resolveMethod(String owner, String methodName, String methodDesc) { + Class declaringClass = resolve(owner); + if (methodName.equals("")) { + for (Constructor c : declaringClass.getDeclaredConstructors()) { + if (methodDesc.equals(Type.getConstructorDescriptor(c))) { + return c; + } + } + } else { + Type[] argumentTypes = Type.getArgumentTypes(methodDesc); + for (Method m : declaringClass.getDeclaredMethods()) { + if (m.getName().equals(methodName)) { + if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) { + if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) { + return m; + } + } + } + } + } + throw new NoSuchMethodError(declaringClass + "." + methodName + methodDesc); + } + + /** + * Checks whether a given method is allowed to be called. + */ + private boolean checkInvokeTarget(Executable method) { + Class holder = method.getDeclaringClass(); + if (method instanceof Constructor) { + if (OptionValue.class.isAssignableFrom(holder)) { + return true; + } + } else if (Arrays.asList(boxingTypes).contains(holder)) { + return method.getName().equals("valueOf"); + } else if (method.getDeclaringClass().equals(Class.class)) { + return method.getName().equals("desiredAssertionStatus"); + } + return false; + } + + @Override + public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) { + Executable callee = resolveMethod(owner, methodName, methodDesc); + verify(checkInvokeTarget(callee), "invocation of " + callee); + } + }; + } else { + return null; + } + } +} \ No newline at end of file diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -42,7 +42,7 @@ final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; final boolean inlineObjects = true; - return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); + return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); } public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -52,10 +52,10 @@ // The calling convention for the exception handler stub is (only?) defined in // TemplateInterpreterGenerator::generate_throw_exception() // in templateInterpreter_sparc.cpp around line 1925 - RegisterValue outgoingException = o0.asValue(Kind.Object); - RegisterValue outgoingExceptionPc = o1.asValue(word); - RegisterValue incomingException = i0.asValue(Kind.Object); - RegisterValue incomingExceptionPc = i1.asValue(word); + RegisterValue outgoingException = o0.asValue(target.getLIRKind(Kind.Object)); + RegisterValue outgoingExceptionPc = o1.asValue(target.getLIRKind(word)); + RegisterValue incomingException = i0.asValue(target.getLIRKind(Kind.Object)); + RegisterValue incomingExceptionPc = i1.asValue(LIRKind.value(word)); CallingConvention outgoingExceptionCc = new CallingConvention(0, ILLEGAL, outgoingException, outgoingExceptionPc); CallingConvention incomingExceptionCc = new CallingConvention(0, ILLEGAL, incomingException, incomingExceptionPc); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Jun 30 12:02:19 2014 +0200 @@ -120,7 +120,7 @@ public void emitReturn(Value input) { AllocatableValue operand = Value.ILLEGAL; if (input != null) { - operand = resultOperandFor(input.getKind()); + operand = resultOperandFor(input.getLIRKind()); emitMove(operand, input); } append(new SPARCHotSpotReturnOp(operand, getStub() != null)); @@ -148,9 +148,9 @@ } private void moveValueToThread(Value v, int offset) { - Kind wordKind = getProviders().getCodeCache().getTarget().wordKind; + LIRKind wordKind = LIRKind.value(getProviders().getCodeCache().getTarget().wordKind); RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind); - SPARCAddressValue pendingDeoptAddress = new SPARCAddressValue(v.getKind(), thread, offset); + SPARCAddressValue pendingDeoptAddress = new SPARCAddressValue(wordKind, thread, offset); append(new StoreOp(v.getKind(), pendingDeoptAddress, emitMove(v), null)); } @@ -167,25 +167,25 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { + public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) { SPARCAddressValue loadAddress = asAddressValue(address); Variable result = newVariable(kind); - append(new LoadOp((Kind) kind, result, loadAddress, state)); + append(new LoadOp((Kind) kind.getPlatformKind(), result, loadAddress, state)); return result; } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { + public void emitStore(LIRKind kind, Value address, Value inputVal, LIRFrameState state) { SPARCAddressValue storeAddress = asAddressValue(address); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); if (canStoreConstant(c)) { - append(new StoreConstantOp((Kind) kind, storeAddress, c, state)); + append(new StoreConstantOp((Kind) kind.getPlatformKind(), storeAddress, c, state)); return; } } Variable input = load(inputVal); - append(new StoreOp((Kind) kind, storeAddress, input, state)); + append(new StoreOp((Kind) kind.getPlatformKind(), storeAddress, input, state)); } public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { @@ -243,7 +243,7 @@ for (int i = 0; i < savedRegisters.length; i++) { PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); assert kind != Kind.Illegal; - StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); + StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(LIRKind.value(kind)); savedRegisterLocations[i] = spillSlot; } return emitSaveRegisters(savedRegisters, savedRegisterLocations, false); @@ -261,7 +261,7 @@ Register thread = getProviders().getRegisters().getThreadRegister(); Variable framePcVariable = load(framePc); Variable senderSpVariable = load(senderSp); - Variable scratchVariable = newVariable(getHostWordKind()); + Variable scratchVariable = newVariable(LIRKind.value(getHostWordKind())); append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable)); } @@ -284,7 +284,7 @@ Register threadRegister = getProviders().getRegisters().getThreadRegister(); Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(Kind.Long), trapRequest); + Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(Kind.Long)), trapRequest); append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister)); return result; @@ -297,7 +297,7 @@ Register threadRegister = getProviders().getRegisters().getThreadRegister(); Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(Kind.Long)); + Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(Kind.Long))); append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister)); return result; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -52,7 +52,7 @@ @Override protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeMap nodeOperands) { - HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMap(), Kind.Long); + HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMap(), LIRKind.value(Kind.Long)); return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); } @@ -68,17 +68,17 @@ @Override public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Kind kind = x.newValue().getKind(); - assert kind == x.expectedValue().getKind(); - Variable address = gen.load(operand(x.object())); Value offset = operand(x.offset()); Variable cmpValue = (Variable) gen.loadNonConst(operand(x.expectedValue())); Variable newValue = gen.load(operand(x.newValue())); + LIRKind kind = cmpValue.getLIRKind(); + assert kind.equals(newValue.getLIRKind()); + if (ValueUtil.isConstant(offset)) { assert !gen.getCodeCache().needsDataPatch(asConstant(offset)); - Variable longAddress = newVariable(Kind.Long); + Variable longAddress = gen.newVariable(LIRKind.value(Kind.Long)); gen.emitMove(longAddress, address); address = getGen().emitAdd(longAddress, asConstant(offset)); } else { @@ -88,10 +88,7 @@ } append(new CompareAndSwapOp(address, cmpValue, newValue)); - - Variable result = newVariable(x.getKind()); - gen.emitMove(result, newValue); - setResult(x, result); + setResult(x, gen.emitMove(newValue)); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -206,7 +206,7 @@ case Object: if (!stackOnly && currentGeneral < generalParameterRegisters.length) { Register register = generalParameterRegisters[currentGeneral++]; - locations[i] = register.asValue(kind); + locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Double: @@ -217,13 +217,13 @@ } Register register = fpuParameterRegisters[currentFloating]; currentFloating += 2; // Only every second is a double register - locations[i] = register.asValue(kind); + locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Float: if (!stackOnly && currentFloating < fpuParameterRegisters.length) { Register register = fpuParameterRegisters[currentFloating++]; - locations[i] = register.asValue(kind); + locations[i] = register.asValue(target.getLIRKind(kind)); } break; default: @@ -231,13 +231,13 @@ } if (locations[i] == null) { - locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); + locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out); currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); - AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(returnKind.getStackKind()); + AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind())); return new CallingConvention(currentStackOffset, returnLocation, locations); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -52,7 +52,7 @@ public SPARCHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { this.state = state; this.config = config; - temp = tool.newVariable(tool.target().wordKind); + temp = tool.newVariable(LIRKind.value(tool.target().wordKind)); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -692,7 +692,7 @@ }; DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig fixedConfig = Debug.fixedConfig(false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + DebugConfig fixedConfig = Debug.fixedConfig(false, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { ReentrantNodeIterator.apply(closure, graph.start(), false); new WriteBarrierVerificationPhase().apply(graph); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationQueue.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationQueue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationQueue.java Mon Jun 30 12:02:19 2014 +0200 @@ -40,6 +40,8 @@ import com.oracle.graal.options.*; import com.oracle.graal.printer.*; +//JaCoCo Exclude + /** * A queue for running {@link CompilationTask}s on background compilation thread(s). The singleton * {@linkplain #queue() instance} is created the first time this class is accessed. @@ -52,6 +54,10 @@ static { try (InitTimer t = timer("initialize CompilationQueue")) { + // The Graal runtime needs to be initialized here to avoid + // issues re-entering Java code during compilation scheduling. + HotSpotGraalRuntime.runtime(); + // Must be first to ensure any options accessed by the rest of the class // initializer are initialized from the command line. HotSpotOptions.initialize(); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Jun 30 12:02:19 2014 +0200 @@ -63,6 +63,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.printer.*; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -240,6 +241,11 @@ protected PhaseSuite getGraphBuilderSuite(HotSpotProviders providers) { PhaseSuite suite = providers.getSuites().getDefaultGraphBuilderSuite(); + if (HotSpotGraalRuntime.runtime().getCompilerToVM().shouldDebugNonSafepoints()) { + // need to tweak the graph builder config + suite.findPhase(GraphBuilderPhase.class).set(new GraphBuilderPhase(GraphBuilderConfiguration.getInfopointDefault())); + } + boolean osrCompilation = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; if (osrCompilation) { suite = suite.copy(); @@ -490,21 +496,31 @@ } /** - * Entry point for the VM to schedule a compilation for a metaspace Method. + * Schedules compilation of a metaspace Method. * * Called from the VM. */ @SuppressWarnings("unused") private static void compileMetaspaceMethod(long metaspaceMethod, final int entryBCI, long ctask, final boolean blocking) { - final HotSpotResolvedJavaMethod method = HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod); if (ctask != 0L) { + // Ensure a Graal runtime is initialized prior to Debug being initialized as the former + // may include processing command line options used by the latter. + Graal.getRuntime(); + + // Ensure a debug configuration for this thread is initialized + if (Debug.isEnabled() && DebugScope.getConfig() == null) { + DebugEnvironment.initialize(System.out); + } + // This is on a VM CompilerThread - no user frames exist + final HotSpotResolvedJavaMethod method = HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod); compileMethod(method, entryBCI, ctask, false); } else { // We have to use a privileged action here because compilations are // enqueued from user code which very likely contains unprivileged frames. AccessController.doPrivileged(new PrivilegedAction() { public Void run() { + final HotSpotResolvedJavaMethod method = HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod); compileMethod(method, entryBCI, 0L, blocking); return null; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Mon Jun 30 12:02:19 2014 +0200 @@ -269,4 +269,12 @@ public boolean needsJavaFrameAnchor() { return canDeoptimize() || transition == Transition.LEAF_SP; } + + public CompilationResult getStubCompilationResult(final Backend backend) { + return stub.getCompilationResult(backend); + } + + public Stub getStub() { + return stub; + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Jun 30 12:02:19 2014 +0200 @@ -52,7 +52,6 @@ import com.oracle.graal.hotspot.events.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.java.*; import com.oracle.graal.options.*; import com.oracle.graal.printer.*; import com.oracle.graal.replacements.*; @@ -124,9 +123,9 @@ TTY.initialize(Options.LogFile.getStream()); - if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null) { + if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null && Verify.getValue() == null) { if (MethodFilter.getValue() != null) { - TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time and Dump options are all null"); + TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, Dump and Verify options are all null"); } } @@ -147,9 +146,6 @@ } } - final HotSpotProviders hostProviders = hostBackend.getProviders(); - assert VerifyOptionsPhase.checkOptions(hostProviders.getMetaAccess()); - // Complete initialization of backends try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { hostBackend.completeInitialization(); @@ -173,7 +169,7 @@ @Option(help = "The runtime configuration to use") static final OptionValue GraalRuntime = new OptionValue<>(""); - @Option(help = "File to which logging is sent") + @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying the process, usually the process id.") public static final PrintStreamOption LogFile = new PrintStreamOption(); // @formatter:on } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,8 +26,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure; import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; /** * Extends {@link LIRFrameState} to handle {@link HotSpotMonitorValue}s correctly. @@ -39,15 +39,15 @@ } @Override - protected Value processValue(ValueProcedure proc, Value value) { + protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) { if (value instanceof HotSpotMonitorValue) { HotSpotMonitorValue monitor = (HotSpotMonitorValue) value; if (processed(monitor.getOwner())) { - monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS)); + monitor.setOwner(proc.doValue(inst, monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS)); } return value; } else { - return super.processValue(proc, value); + return super.processValue(inst, proc, value); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -36,9 +36,9 @@ private StackSlot[] locks; private final FrameMap frameMap; - private final Kind slotKind; + private final LIRKind slotKind; - public HotSpotLockStack(FrameMap frameMap, Kind slotKind) { + public HotSpotLockStack(FrameMap frameMap, LIRKind slotKind) { this.frameMap = frameMap; this.slotKind = slotKind; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition * to abstract methods from {@link LIRGenerator} and {@link NodeLIRBuilderTool}. */ -@MatchableNode(nodeClass = CompressionNode.class, inputs = {"input"}) +@MatchableNode(nodeClass = CompressionNode.class, inputs = {"value"}) public interface HotSpotNodeLIRBuilder { void emitPatchReturnAddress(ValueNode address); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,6 +36,8 @@ import com.oracle.graal.options.*; import com.oracle.graal.phases.common.inlining.*; +//JaCoCo Exclude + /** * Sets Graal options from the HotSpot command line. Such options are distinguished by a * {@code "-G:"} prefix. @@ -200,13 +202,22 @@ } protected static void printNoMatchMessage(String optionName) { - System.err.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)"); - List matches = fuzzyMatch(optionName); - if (!matches.isEmpty()) { - System.err.println("Did you mean one of the following?"); - for (OptionDescriptor match : matches) { - boolean isBoolean = match.getType() == boolean.class; - System.err.println(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); + OptionDescriptor desc = options.get(optionName); + if (desc != null) { + if (desc.getType() == Boolean.class) { + System.err.println("Boolean option " + optionName + " must be prefixed with '+' or '-'"); + } else { + System.err.println(desc.getType().getSimpleName() + " option " + optionName + " must not be prefixed with '+' or '-'"); + } + } else { + System.err.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)"); + List matches = fuzzyMatch(optionName); + if (!matches.isEmpty()) { + System.err.println("Did you mean one of the following?"); + for (OptionDescriptor match : matches) { + boolean isBoolean = match.getType() == Boolean.class; + System.err.println(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); + } } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,79 +28,129 @@ import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.compiler.common.*; public class HotSpotReferenceMap implements ReferenceMap, Serializable { private static final long serialVersionUID = -1052183095979496819L; + private static final int BITS_PER_WORD = 3; + /** - * Contains 2 bits per register. - *
    - *
  • bit0 = 0: contains no references
  • - *
  • bit0 = 1, bit1 = 0: contains a wide oop
  • - *
  • bit0 = 1, bit1 = 1: contains a narrow oop
  • - *
+ * Contains 3 bits per scalar register, and n*3 bits per n-word vector register (e.g., on a + * 64-bit system, a 256-bit vector register requires 12 reference map bits). + *

+ * These bits can have the following values (LSB first): + * + *

+     * 000 - contains no references
+     * 100 - contains a wide oop
+     * 110 - contains a narrow oop in the lower half
+     * 101 - contains a narrow oop in the upper half
+     * 111 - contains two narrow oops
+     * 
*/ private final BitSet registerRefMap; /** - * Contains 3 bits per stack slot. - *
    - *
  • bit0 = 0: contains no references
  • - *
  • bit0 = 1, bit1+2 = 0: contains a wide oop
  • - *
  • bit0 = 1, bit1 = 1: contains a narrow oop in the lower half
  • - *
  • bit0 = 1, bit2 = 1: contains a narrow oop in the upper half
  • - *
+ * Contains 3 bits per stack word. + *

+ * These bits can have the following values (LSB first): + * + *

+     * 000 - contains no references
+     * 100 - contains a wide oop
+     * 110 - contains a narrow oop in the lower half
+     * 101 - contains a narrow oop in the upper half
+     * 111 - contains two narrow oops
+     * 
*/ private final BitSet frameRefMap; - private final int frameSlotSize; + private final TargetDescription target; - public HotSpotReferenceMap(int registerCount, int frameSlotCount, int frameSlotSize) { + public HotSpotReferenceMap(int registerCount, int frameSlotCount, TargetDescription target) { if (registerCount > 0) { - this.registerRefMap = new BitSet(registerCount * 2); + this.registerRefMap = new BitSet(registerCount * BITS_PER_WORD); } else { this.registerRefMap = null; } - this.frameRefMap = new BitSet(frameSlotCount * 3); - this.frameSlotSize = frameSlotSize; + this.frameRefMap = new BitSet(frameSlotCount * BITS_PER_WORD); + this.target = target; + } + + private static void setOop(BitSet map, int startIdx, LIRKind kind) { + int length = kind.getPlatformKind().getVectorLength(); + map.clear(BITS_PER_WORD * startIdx, BITS_PER_WORD * (startIdx + length) - 1); + for (int i = 0, idx = BITS_PER_WORD * startIdx; i < length; i++, idx += BITS_PER_WORD) { + if (kind.isReference(i)) { + map.set(idx); + } + } } - public void setRegister(int idx, PlatformKind kind) { - if (kind == Kind.Object) { - registerRefMap.set(2 * idx); - } else if (kind == NarrowOopStamp.NarrowOop) { - registerRefMap.set(2 * idx); - registerRefMap.set(2 * idx + 1); + private static void setNarrowOop(BitSet map, int idx, LIRKind kind) { + int length = kind.getPlatformKind().getVectorLength(); + int nextIdx = idx + (length + 1) / 2; + map.clear(BITS_PER_WORD * idx, BITS_PER_WORD * nextIdx - 1); + for (int i = 0, regIdx = BITS_PER_WORD * idx; i < length; i += 2, regIdx += BITS_PER_WORD) { + if (kind.isReference(i)) { + map.set(regIdx); + map.set(regIdx + 1); + } + if ((i + 1) < length && kind.isReference(i + 1)) { + map.set(regIdx); + map.set(regIdx + 2); + } } } - public PlatformKind getRegister(int idx) { - int refMapIndex = idx * 2; - if (registerRefMap.get(refMapIndex)) { - if (registerRefMap.get(refMapIndex + 1)) { - return NarrowOopStamp.NarrowOop; - } else { - return Kind.Object; - } + public void setRegister(int idx, LIRKind kind) { + if (kind.isDerivedReference()) { + throw GraalInternalError.shouldNotReachHere("derived reference cannot be inserted in ReferenceMap"); } - return null; + + PlatformKind platformKind = kind.getPlatformKind(); + int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); + + if (bytesPerElement == target.wordSize) { + setOop(registerRefMap, idx, kind); + } else if (bytesPerElement == target.wordSize / 2) { + setNarrowOop(registerRefMap, idx, kind); + } else { + assert kind.isValue() : "unsupported reference kind " + kind; + } } - public void setStackSlot(int offset, PlatformKind kind) { - int idx = offset / frameSlotSize; - if (kind == Kind.Object) { - assert offset % frameSlotSize == 0; - frameRefMap.set(3 * idx); - } else if (kind == NarrowOopStamp.NarrowOop) { - frameRefMap.set(3 * idx); - if (offset % frameSlotSize == 0) { - frameRefMap.set(3 * idx + 1); + public void setStackSlot(int offset, LIRKind kind) { + if (kind.isDerivedReference()) { + throw GraalInternalError.shouldNotReachHere("derived reference cannot be inserted in ReferenceMap"); + } + + PlatformKind platformKind = kind.getPlatformKind(); + int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); + assert offset % bytesPerElement == 0 : "unaligned value in ReferenceMap"; + + if (bytesPerElement == target.wordSize) { + setOop(frameRefMap, offset / target.wordSize, kind); + } else if (bytesPerElement == target.wordSize / 2) { + if (platformKind.getVectorLength() > 1) { + setNarrowOop(frameRefMap, offset / target.wordSize, kind); } else { - assert offset % frameSlotSize == frameSlotSize / 2; - frameRefMap.set(3 * idx + 2); + // in this case, offset / target.wordSize may not divide evenly + // so setNarrowOop won't work correctly + int idx = offset / target.wordSize; + if (kind.isReference(0)) { + frameRefMap.set(BITS_PER_WORD * idx); + if (offset % target.wordSize == 0) { + frameRefMap.set(BITS_PER_WORD * idx + 1); + } else { + frameRefMap.set(BITS_PER_WORD * idx + 2); + } + } } + } else { + assert kind.isValue() : "unknown reference kind " + kind; } } @@ -113,14 +163,14 @@ } public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatter) { - for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 2)) { - sb.append(' ').append(formatter.formatRegister(reg / 2)); + for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + BITS_PER_WORD)) { + sb.append(' ').append(formatter.formatRegister(reg / BITS_PER_WORD)); } } public void appendFrameMap(StringBuilder sb, RefMapFormatter formatter) { - for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 3)) { - sb.append(' ').append(formatter.formatStackSlot(slot / 3)); + for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + BITS_PER_WORD)) { + sb.append(' ').append(formatter.formatStackSlot(slot / BITS_PER_WORD)); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,28 +24,20 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.nodes.type.*; public class HotSpotTargetDescription extends TargetDescription { - private final PlatformKind rawNarrowOopKind; - - public HotSpotTargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects, PlatformKind rawNarrowOopKind) { + public HotSpotTargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects) { super(arch, isMP, stackAlignment, implicitNullCheckLimit, inlineObjects); - this.rawNarrowOopKind = rawNarrowOopKind; } @Override public int getSizeInBytes(PlatformKind kind) { - if (kind == NarrowOopStamp.NarrowOop) { - return super.getSizeInBytes(rawNarrowOopKind); - } else { - return super.getSizeInBytes(kind); - } + return super.getSizeInBytes(kind); } @Override public ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount) { - return new HotSpotReferenceMap(hasRegisters ? arch.getRegisterReferenceMapBitCount() : 0, stackSlotCount, wordSize); + return new HotSpotReferenceMap(hasRegisters ? arch.getRegisterReferenceMapSize() : 0, stackSlotCount, this); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -1029,9 +1029,10 @@ */ @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_notice_safepoints", type = "jint*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNoticeSafepointsOffset; @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_occurred", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptOccurredOffset; - @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_never_ran_array", type = "jboolean *", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNeverRanArrayOffset; + @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_never_ran_array", type = "jboolean*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNeverRanArrayOffset; @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_next_index", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptNextIndexOffset; - @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_donor_threads", type = "JavaThread**", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDonorThreadsOffset; + @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_alloc_info", type = "HSAILAllocationInfo*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailAllocInfoOffset; + @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_cur_tlab_info", type = "HSAILTlabInfo**", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailCurTlabInfoOffset; @HotSpotVMField(name = "Hsail::HSAILKernelDeoptimization::_workitemid", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptimizationWorkItem; @HotSpotVMField(name = "Hsail::HSAILKernelDeoptimization::_actionAndReason", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptimizationReason; @@ -1043,6 +1044,20 @@ @HotSpotVMType(name = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMType.Type.SIZE) @Stable public int hsailKernelDeoptimizationHeaderSize; @HotSpotVMType(name = "Hsail::HSAILDeoptimizationInfo", get = HotSpotVMType.Type.SIZE) @Stable public int hsailDeoptimizationInfoHeaderSize; + @HotSpotVMField(name = "HSAILAllocationInfo::_tlab_infos_pool_start", type = "HSAILTlabInfo*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailAllocInfoTlabInfosPoolStartOffset; + @HotSpotVMField(name = "HSAILAllocationInfo::_tlab_infos_pool_next", type = "HSAILTlabInfo*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailAllocInfoTlabInfosPoolNextOffset; + @HotSpotVMField(name = "HSAILAllocationInfo::_tlab_infos_pool_end", type = "HSAILTlabInfo*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailAllocInfoTlabInfosPoolEndOffset; + @HotSpotVMField(name = "HSAILAllocationInfo::_tlab_align_reserve_bytes", type = "size_t", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailAllocInfoTlabAlignReserveBytesOffset; + + @HotSpotVMField(name = "HSAILTlabInfo::_start", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoStartOffset; + @HotSpotVMField(name = "HSAILTlabInfo::_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoTopOffset; + @HotSpotVMField(name = "HSAILTlabInfo::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoEndOffset; + @HotSpotVMField(name = "HSAILTlabInfo::_last_good_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoLastGoodTopOffset; + @HotSpotVMField(name = "HSAILTlabInfo::_original_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoOriginalTopOffset; + @HotSpotVMField(name = "HSAILTlabInfo::_donor_thread", type = "JavaThread*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoDonorThreadOffset; + @HotSpotVMField(name = "HSAILTlabInfo::_alloc_info", type = "HSAILAllocationInfo*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailTlabInfoAllocInfoOffset; + @HotSpotVMType(name = "HSAILTlabInfo", get = HotSpotVMType.Type.SIZE) @Stable public int hsailTlabInfoSize; + /** * Mark word right shift to get identity hash code. */ @@ -1390,14 +1405,14 @@ @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopAlignedArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopArraycopyUninit; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedArraycopy; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedArraycopyUninit; @HotSpotVMField(name = "StubRoutines::_arrayof_jbyte_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteAlignedDisjointArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jshort_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortAlignedDisjointArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jint_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintAlignedDisjointArraycopy; @HotSpotVMField(name = "StubRoutines::_arrayof_jlong_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jlongAlignedDisjointArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopDisjointArraycopy; - @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long alignedOopDisjointArraycopyUninit; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedDisjointArraycopy; + @HotSpotVMField(name = "StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long oopAlignedDisjointArraycopyUninit; @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopy; @HotSpotVMField(name = "StubRoutines::_checkcast_arraycopy_uninit", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long checkcastArraycopyUninit; @HotSpotVMField(name = "StubRoutines::_unsafe_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long unsafeArraycopy; @@ -1409,9 +1424,9 @@ @HotSpotVMValue(expression = "GraalRuntime::dynamic_new_array", get = HotSpotVMValue.Type.ADDRESS) @Stable public long dynamicNewArrayAddress; @HotSpotVMValue(expression = "GraalRuntime::dynamic_new_instance", get = HotSpotVMValue.Type.ADDRESS) @Stable public long dynamicNewInstanceAddress; @HotSpotVMValue(expression = "GraalRuntime::thread_is_interrupted", get = HotSpotVMValue.Type.ADDRESS) @Stable public long threadIsInterruptedAddress; - @HotSpotVMValue(expression = "GraalRuntime::vm_message", get = HotSpotVMValue.Type.ADDRESS) @Stable public long vmMessageAddress; + @HotSpotVMValue(expression = "GraalRuntime::vm_message", signature = "(unsigned char, long, long, long, long)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long vmMessageAddress; @HotSpotVMValue(expression = "GraalRuntime::identity_hash_code", get = HotSpotVMValue.Type.ADDRESS) @Stable public long identityHashCodeAddress; - @HotSpotVMValue(expression = "GraalRuntime::exception_handler_for_pc", get = HotSpotVMValue.Type.ADDRESS) @Stable public long exceptionHandlerForPcAddress; + @HotSpotVMValue(expression = "GraalRuntime::exception_handler_for_pc", signature = "(JavaThread*)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long exceptionHandlerForPcAddress; @HotSpotVMValue(expression = "GraalRuntime::monitorenter", get = HotSpotVMValue.Type.ADDRESS) @Stable public long monitorenterAddress; @HotSpotVMValue(expression = "GraalRuntime::monitorexit", get = HotSpotVMValue.Type.ADDRESS) @Stable public long monitorexitAddress; @HotSpotVMValue(expression = "GraalRuntime::create_null_exception", get = HotSpotVMValue.Type.ADDRESS) @Stable public long createNullPointerExceptionAddress; @@ -1437,9 +1452,9 @@ @HotSpotVMValue(expression = "(jint) GraalCounterSize") @Stable public int graalCountersSize; - @HotSpotVMValue(expression = "Deoptimization::fetch_unroll_info", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationFetchUnrollInfo; + @HotSpotVMValue(expression = "Deoptimization::fetch_unroll_info", signature = "(JavaThread*)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationFetchUnrollInfo; @HotSpotVMValue(expression = "Deoptimization::uncommon_trap", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationUncommonTrap; - @HotSpotVMValue(expression = "Deoptimization::unpack_frames", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationUnpackFrames; + @HotSpotVMValue(expression = "Deoptimization::unpack_frames", signature = "(JavaThread*, int)", get = HotSpotVMValue.Type.ADDRESS) @Stable public long deoptimizationUnpackFrames; @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone; @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck; @@ -1584,4 +1599,35 @@ } } } + + /** + * Returns the name of the C/C++ function that is associated (via HotSpotVMValue annotation) + * with the HotSpotVMConfig object's field containing {@code foreignCalltargetAddress}; returns + * null if no field holds the provided address. + * + * @param foreignCallTargetAddress address of foreign call target + * @return C/C++ symbol name or null + */ + public String getCSymbol(long foreignCallTargetAddress) { + for (Field f : HotSpotVMConfig.class.getDeclaredFields()) { + if (f.isAnnotationPresent(HotSpotVMValue.class)) { + HotSpotVMValue annotation = f.getAnnotation(HotSpotVMValue.class); + + if (annotation.get() == HotSpotVMValue.Type.ADDRESS) { + try { + if (foreignCallTargetAddress == f.getLong(this)) { + return (annotation.expression() + annotation.signature()); + } + } catch (IllegalArgumentException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IllegalAccessException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + } + } + return null; + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java Mon Jun 30 12:02:19 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot; import java.io.*; +import java.lang.management.*; import com.oracle.graal.options.*; @@ -44,6 +45,30 @@ private volatile PrintStream ps; /** + * Replace any instance of %p with a an identifying name. Try to get it from the RuntimeMXBean + * name. + * + * @return the name of the file to log to + */ + private String getFilename() { + String name = getValue(); + if (name.contains("%p")) { + String runtimeName = ManagementFactory.getRuntimeMXBean().getName(); + try { + int index = runtimeName.indexOf('@'); + if (index != -1) { + long pid = Long.parseLong(runtimeName.substring(0, index)); + runtimeName = Long.toString(pid); + } + name = name.replaceAll("%p", runtimeName); + } catch (NumberFormatException e) { + + } + } + return name; + } + + /** * Gets the print stream configured by this option. */ public PrintStream getStream() { @@ -53,7 +78,7 @@ if (ps == null) { try { final boolean enableAutoflush = true; - ps = new PrintStream(new FileOutputStream(getValue()), enableAutoflush); + ps = new PrintStream(new FileOutputStream(getFilename()), enableAutoflush); } catch (FileNotFoundException e) { throw new RuntimeException("couldn't open file: " + getValue(), e); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Mon Jun 30 12:02:19 2014 +0200 @@ -87,7 +87,7 @@ * @return the metaspace Method result or 0 is there is no unique concrete method for * {@code metaspaceMethod} */ - long findUniqueConcreteMethod(long metaspaceMethod); + long findUniqueConcreteMethod(long actualHolderMetaspaceKlass, long metaspaceMethod); /** * Returns the implementor for the given interface class. @@ -359,4 +359,6 @@ void resolveInvokeDynamic(long metaspaceConstantPool, int index); int getVtableIndexForInterface(long metaspaceKlass, long metaspaceMethod); + + boolean shouldDebugNonSafepoints(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jun 30 12:02:19 2014 +0200 @@ -68,7 +68,7 @@ public native boolean hasBalancedMonitors(long metaspaceMethod); @Override - public native long findUniqueConcreteMethod(long metaspaceMethod); + public native long findUniqueConcreteMethod(long actualHolderMetaspaceKlass, long metaspaceMethod); @Override public native long getKlassImplementor(long metaspaceKlass); @@ -197,4 +197,6 @@ public native void resolveInvokeDynamic(long metaspaceConstantPool, int index); public native int getVtableIndexForInterface(long metaspaceKlass, long metaspaceMethod); + + public native boolean shouldDebugNonSafepoints(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.nodes.type.*; /** * A data item that represents an oop value. @@ -48,7 +47,7 @@ @Override public int getSize(TargetDescription target) { if (compressed) { - return target.getSizeInBytes(NarrowOopStamp.NarrowOop); + return target.getSizeInBytes(Kind.Int); } else { return target.getSizeInBytes(Kind.Object); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Mon Jun 30 12:02:19 2014 +0200 @@ -386,7 +386,7 @@ ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE)); ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph); ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE)); - IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement())); + IntegerAddNode add = graph.unique(new IntegerAddNode(read, counter.getIncrement())); WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE)); graph.addBeforeFixed(counter, thread); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,6 +49,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.nodes.*; /** * HotSpot implementation of {@link LoweringProvider}. @@ -66,6 +67,7 @@ protected WriteBarrierSnippets.Templates writeBarrierSnippets; protected LoadExceptionObjectSnippets.Templates exceptionObjectSnippets; protected UnsafeLoadSnippets.Templates unsafeLoadSnippets; + protected AssertionSnippets.Templates assertionSnippets; public DefaultHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { super(metaAccess, target); @@ -85,6 +87,7 @@ writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); + assertionSnippets = new AssertionSnippets.Templates(providers, target); providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); } @@ -158,6 +161,8 @@ } } else if (n instanceof LoadExceptionObjectNode) { exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool); + } else if (n instanceof AssertionNode) { + assertionSnippets.lower((AssertionNode) n, tool); } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompressedNullConstant.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompressedNullConstant.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompressedNullConstant.java Mon Jun 30 12:02:19 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.nodes.type.*; /** * The compressed representation of the {@link Constant#NULL_OBJECT null constant}. @@ -35,7 +34,7 @@ public static final Constant COMPRESSED_NULL = new HotSpotCompressedNullConstant(); private HotSpotCompressedNullConstant() { - super(NarrowOopStamp.NarrowOop); + super(LIRKind.reference(Kind.Int)); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -229,6 +229,12 @@ return runtime.getHostProviders().getMetaAccess().lookupJavaType((Class) obj); } } + if (constant instanceof HotSpotMetaspaceConstant) { + Object obj = HotSpotMetaspaceConstant.getMetaspaceObject(constant); + if (obj instanceof HotSpotResolvedObjectType) { + return (ResolvedJavaType) obj; + } + } return null; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,6 +28,7 @@ import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; import static com.oracle.graal.hotspot.meta.DefaultHotSpotLoweringProvider.RuntimeCalls.*; +import static com.oracle.graal.hotspot.replacements.AssertionSnippets.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; @@ -64,12 +65,18 @@ stub.getLinkage().setCompiledStub(stub); } - public static ForeignCallDescriptor lookupArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint) { + public static ForeignCallDescriptor lookupArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint, boolean uninit) { + if (uninit) { + assert kind == Kind.Object; + return uninitObjectArraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0]; + } return arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind); } @SuppressWarnings("unchecked") private static final EnumMap[][] arraycopyDescriptors = new EnumMap[2][2]; + private static final ForeignCallDescriptor[][] uninitObjectArraycopyDescriptors = new ForeignCallDescriptor[2][2]; + static { // Populate the EnumMap instances for (int i = 0; i < arraycopyDescriptors.length; i++) { @@ -79,19 +86,28 @@ } } - private static ForeignCallDescriptor registerArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint) { - String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + "Arraycopy"; + private static ForeignCallDescriptor registerArraycopyDescriptor(Kind kind, boolean aligned, boolean disjoint, boolean uninit) { + String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + (uninit ? "Uninit" : "") + "Arraycopy"; ForeignCallDescriptor desc = new ForeignCallDescriptor(name, void.class, Word.class, Word.class, Word.class); - arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, desc); + if (uninit) { + assert kind == Kind.Object; + uninitObjectArraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0] = desc; + } else { + arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, desc); + } return desc; } private void registerArrayCopy(Kind kind, long routine, long alignedRoutine, long disjointRoutine, long alignedDisjointRoutine) { + registerArrayCopy(kind, routine, alignedRoutine, disjointRoutine, alignedDisjointRoutine, false); + } + + private void registerArrayCopy(Kind kind, long routine, long alignedRoutine, long disjointRoutine, long alignedDisjointRoutine, boolean uninit) { LocationIdentity killed = NamedLocationIdentity.getArrayLocation(kind); - registerForeignCall(registerArraycopyDescriptor(kind, false, false), routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); - registerForeignCall(registerArraycopyDescriptor(kind, true, false), alignedRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); - registerForeignCall(registerArraycopyDescriptor(kind, false, true), disjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); - registerForeignCall(registerArraycopyDescriptor(kind, true, true), alignedDisjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, false, false, uninit), routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, true, false, uninit), alignedRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, false, true, uninit), disjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); + registerForeignCall(registerArraycopyDescriptor(kind, true, true, uninit), alignedDisjointRoutine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed); } public void initialize(HotSpotProviders providers, HotSpotVMConfig c) { @@ -121,6 +137,7 @@ registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); link(new NewArrayStub(providers, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION))); @@ -155,6 +172,12 @@ registerArrayCopy(Kind.Float, c.jintArraycopy, c.jintAlignedArraycopy, c.jintDisjointArraycopy, c.jintAlignedDisjointArraycopy); registerArrayCopy(Kind.Long, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy); registerArrayCopy(Kind.Double, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy); - registerArrayCopy(Kind.Object, c.oopArraycopy, c.oopArraycopy, c.oopDisjointArraycopy, c.oopDisjointArraycopy); + registerArrayCopy(Kind.Object, c.oopArraycopy, c.oopAlignedArraycopy, c.oopDisjointArraycopy, c.oopAlignedDisjointArraycopy); + registerArrayCopy(Kind.Object, c.oopArraycopyUninit, c.oopAlignedArraycopyUninit, c.oopDisjointArraycopyUninit, c.oopAlignedDisjointArraycopyUninit, true); + } + + public HotSpotForeignCallLinkage getForeignCall(ForeignCallDescriptor descriptor) { + assert foreignCalls != null : descriptor; + return foreignCalls.get(descriptor); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; @@ -40,6 +41,8 @@ IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization); + Stamp loadStamp(Stamp stamp, Kind kind); + ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value); ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMonitorValue.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMonitorValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMonitorValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -37,7 +37,7 @@ private final boolean eliminated; public HotSpotMonitorValue(Value owner, StackSlot slot, boolean eliminated) { - super(Kind.Illegal); + super(LIRKind.Illegal); this.owner = owner; this.slot = slot; this.eliminated = eliminated; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.nodes.type.*; /** * Represents a constant non-{@code null} object reference, within the compiler and across the @@ -79,7 +78,7 @@ private final boolean compressed; private HotSpotObjectConstant(Object object, boolean compressed) { - super(compressed ? NarrowOopStamp.NarrowOop : Kind.Object); + super(LIRKind.reference(compressed ? Kind.Int : Kind.Object)); this.object = object; this.compressed = compressed; assert object != null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Jun 30 12:02:19 2014 +0200 @@ -350,8 +350,8 @@ return runtime().getCompilerToVM().getStackTraceElement(metaspaceMethod, bci); } - public ResolvedJavaMethod uniqueConcreteMethod() { - if (holder.isInterface()) { + public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) { + if (receiver.isInterface()) { // Cannot trust interfaces. Because of: // interface I { void foo(); } // class A { public void foo() {} } @@ -362,7 +362,7 @@ // seeing A.foo(). return null; } - final long uniqueConcreteMethod = runtime().getCompilerToVM().findUniqueConcreteMethod(metaspaceMethod); + final long uniqueConcreteMethod = runtime().getCompilerToVM().findUniqueConcreteMethod(receiver.getMetaspaceKlass(), metaspaceMethod); if (uniqueConcreteMethod == 0) { return null; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Jun 30 12:02:19 2014 +0200 @@ -459,7 +459,26 @@ @Override public ResolvedJavaMethod findUniqueConcreteMethod(ResolvedJavaMethod method) { - return ((HotSpotResolvedJavaMethod) method).uniqueConcreteMethod(); + HotSpotResolvedJavaMethod hmethod = (HotSpotResolvedJavaMethod) method; + HotSpotResolvedObjectType declaredHolder = hmethod.getDeclaringClass(); + /* + * Sometimes the receiver type in the graph hasn't stabilized to a subtype of declared + * holder, usually because of phis, so make sure that the type is related to the declared + * type before using it for lookup. + */ + if (!declaredHolder.isAssignableFrom(this) || this.isArray() || this.equals(declaredHolder)) { + return hmethod.uniqueConcreteMethod(declaredHolder); + } + /* + * The holder may be a subtype of the decaredHolder so make sure to resolve the method to + * the correct method for the subtype. + */ + HotSpotResolvedJavaMethod newMethod = (HotSpotResolvedJavaMethod) resolveMethod(hmethod, this); + if (newMethod != null && !hmethod.equals(newMethod)) { + hmethod = newMethod; + } + + return hmethod.uniqueConcreteMethod(this); } /** diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -44,7 +44,7 @@ } public static AllocatableValue emitCString(NodeLIRBuilderTool gen, String value) { - AllocatableValue dst = gen.getLIRGeneratorTool().newVariable(gen.getLIRGeneratorTool().target().wordKind); + AllocatableValue dst = gen.getLIRGeneratorTool().newVariable(LIRKind.value(gen.getLIRGeneratorTool().target().wordKind)); gen.getLIRGeneratorTool().emitData(dst, toCString(value)); return dst; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; @@ -32,10 +31,10 @@ /** * {@link MacroNode Macro node} for {@link Class#cast(Object)}. - * + * * @see ClassSubstitutions#cast(Class, Object) */ -public class ClassCastNode extends MacroNode implements Canonicalizable { +public class ClassCastNode extends MacroNode implements Canonicalizable.Binary { public ClassCastNode(Invoke invoke) { super(invoke); @@ -49,16 +48,21 @@ return arguments.get(1); } + public ValueNode getX() { + return getJavaClass(); + } + + public ValueNode getY() { + return getObject(); + } + @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ValueNode object = getObject(); - Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forJavaClass, ValueNode forObject) { + if (forJavaClass.isConstant()) { + Class c = (Class) HotSpotObjectConstant.asObject(forJavaClass.asConstant()); if (c != null && !c.isPrimitive()) { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c); - CheckCastNode checkcast = graph().add(new CheckCastNode(type, object, null, false)); - return checkcast; + return new CheckCastNode(type, forObject, null, false); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, 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.nodes; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * {@link MacroNode Macro node} for {@link Class#getClassLoader0()}. + * + * @see ClassSubstitutions#getClassLoader0(Class) + */ +@SuppressWarnings("javadoc") +public class ClassGetClassLoader0Node extends MacroNode implements Canonicalizable { + + public ClassGetClassLoader0Node(Invoke invoke) { + super(invoke); + } + + private ValueNode getJavaClass() { + return arguments.get(0); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + ValueNode javaClass = getJavaClass(); + if (javaClass.isConstant()) { + Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); + if (c != null) { + /* + * This is an intrinsic for getClassLoader0, which occurs after any security checks. + * We can't call that directly so just call getClassLoader. + */ + ClassLoader classLoader = c.getClassLoader(); + return ConstantNode.forConstant(HotSpotObjectConstant.forObject(classLoader), tool.getMetaAccess()); + } + } + return this; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -51,7 +51,7 @@ Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); if (c != null) { Class componentType = c.getComponentType(); - return ConstantNode.forConstant(HotSpotObjectConstant.forObject(componentType), tool.getMetaAccess(), graph()); + return ConstantNode.forConstant(HotSpotObjectConstant.forObject(componentType), tool.getMetaAccess()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -31,7 +31,7 @@ /** * {@link MacroNode Macro node} for {@link Class#getModifiers()}. - * + * * @see ClassSubstitutions#getModifiers(Class) */ public class ClassGetModifiersNode extends MacroNode implements Canonicalizable { @@ -50,7 +50,7 @@ if (javaClass.isConstant()) { Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); if (c != null) { - return ConstantNode.forInt(c.getModifiers(), graph()); + return ConstantNode.forInt(c.getModifiers()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -51,7 +51,7 @@ Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); if (c != null) { Class superclass = c.getSuperclass(); - return ConstantNode.forConstant(HotSpotObjectConstant.forObject(superclass), tool.getMetaAccess(), graph()); + return ConstantNode.forConstant(HotSpotObjectConstant.forObject(superclass), tool.getMetaAccess()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -31,7 +31,7 @@ /** * {@link MacroNode Macro node} for {@link Class#isArray()}. - * + * * @see ClassSubstitutions#isArray(Class) */ public class ClassIsArrayNode extends MacroNode implements Canonicalizable { @@ -50,7 +50,7 @@ if (javaClass.isConstant()) { Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); if (c != null) { - return ConstantNode.forBoolean(c.isArray(), graph()); + return ConstantNode.forBoolean(c.isArray()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -33,7 +33,7 @@ /** * {@link MacroNode Macro node} for {@link Class#isInstance(Object)}. - * + * * @see ClassSubstitutions#isInstance(Class, Object) */ public class ClassIsInstanceNode extends MacroNode implements Canonicalizable { @@ -58,15 +58,15 @@ Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); if (c != null) { if (c.isPrimitive()) { - return ConstantNode.forBoolean(false, graph()); + return ConstantNode.forBoolean(false); } if (object.isConstant()) { Object o = HotSpotObjectConstant.asObject(object.asConstant()); - return ConstantNode.forBoolean(o != null && c.isInstance(o), graph()); + return ConstantNode.forBoolean(o != null && c.isInstance(o)); } HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c); - InstanceOfNode instanceOf = graph().unique(new InstanceOfNode(type, object, null)); - return graph().unique(new ConditionalNode(instanceOf, ConstantNode.forBoolean(true, graph()), ConstantNode.forBoolean(false, graph()))); + InstanceOfNode instanceOf = new InstanceOfNode(type, object, null); + return new ConditionalNode(instanceOf, ConstantNode.forBoolean(true), ConstantNode.forBoolean(false)); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,7 +31,7 @@ /** * {@link MacroNode Macro node} for {@link Class#isInterface()}. - * + * * @see ClassSubstitutions#isInterface(Class) */ public class ClassIsInterfaceNode extends MacroNode implements Canonicalizable { @@ -50,7 +50,7 @@ if (javaClass.isConstant()) { Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); if (c != null) { - return ConstantNode.forBoolean(c.isInterface(), graph()); + return ConstantNode.forBoolean(c.isInterface()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -31,7 +31,7 @@ /** * {@link MacroNode Macro node} for {@link Class#isPrimitive()}. - * + * * @see ClassSubstitutions#isPrimitive(Class) */ public class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable { @@ -50,7 +50,7 @@ if (javaClass.isConstant()) { Class c = (Class) HotSpotObjectConstant.asObject(javaClass.asConstant()); if (c != null) { - return ConstantNode.forBoolean(c.isPrimitive(), graph()); + return ConstantNode.forBoolean(c.isPrimitive()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -40,7 +40,7 @@ * Compress or uncompress an oop or metaspace pointer. */ @NodeInfo(nameTemplate = "{p#op/s}") -public final class CompressionNode extends ConvertNode implements LIRLowerable, Canonicalizable { +public final class CompressionNode extends ConvertNode implements LIRLowerable { private enum CompressionOp { Compress, @@ -151,13 +151,13 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (getInput().isConstant()) { - return ConstantNode.forConstant(stamp(), evalConst(getInput().asConstant()), tool.getMetaAccess(), graph()); - } else if (getInput() instanceof CompressionNode) { - CompressionNode other = (CompressionNode) getInput(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forConstant(stamp(), evalConst(forValue.asConstant()), tool.getMetaAccess()); + } else if (forValue instanceof CompressionNode) { + CompressionNode other = (CompressionNode) forValue; if (op != other.op && encoding.equals(other.encoding)) { - return other.getInput(); + return other.getValue(); } } return this; @@ -167,8 +167,8 @@ public void generate(NodeLIRBuilderTool gen) { HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); boolean nonNull; - if (getInput().stamp() instanceof AbstractObjectStamp) { - nonNull = StampTool.isObjectNonNull(getInput().stamp()); + if (getValue().stamp() instanceof AbstractObjectStamp) { + nonNull = StampTool.isObjectNonNull(getValue().stamp()); } else { // metaspace pointers are never null nonNull = true; @@ -177,10 +177,10 @@ Value result; switch (op) { case Compress: - result = hsGen.emitCompress(gen.operand(getInput()), encoding, nonNull); + result = hsGen.emitCompress(gen.operand(getValue()), encoding, nonNull); break; case Uncompress: - result = hsGen.emitUncompress(gen.operand(getInput()), encoding, nonNull); + result = hsGen.emitUncompress(gen.operand(getValue()), encoding, nonNull); break; default: throw GraalInternalError.shouldNotReachHere(); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -38,14 +38,17 @@ */ public final class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable { + private LIRKind wordKind; + private CurrentJavaThreadNode(Kind kind) { super(StampFactory.forKind(kind)); + this.wordKind = LIRKind.value(kind); } @Override public void generate(NodeLIRBuilderTool gen) { Register rawThread = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).getProviders().getRegisters().getThreadRegister(); - gen.setResult(this, rawThread.asValue(this.getKind())); + gen.setResult(this, rawThread.asValue(wordKind)); } private static int eetopOffset() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -46,7 +46,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - AllocatableValue obj = gen.getLIRGeneratorTool().newVariable(gen.getLIRGeneratorTool().target().wordKind); + AllocatableValue obj = gen.getLIRGeneratorTool().newVariable(LIRKind.derivedReference(gen.getLIRGeneratorTool().target().wordKind)); gen.getLIRGeneratorTool().emitMove(obj, gen.operand(object)); gen.setResult(this, obj); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -71,7 +71,7 @@ } Value[] args = gen.visitInvokeArguments(cc, parameters); Value address = lirGen.emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0); - Value entry = lirGen.emitLoad(Kind.Long, address, null); + Value entry = lirGen.emitLoad(LIRKind.value(Kind.Long), address, null); HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen; hsgen.emitTailcall(args, entry); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,22 +30,6 @@ public class NarrowOopStamp extends AbstractObjectStamp { - public static final PlatformKind NarrowOop = new PlatformKind() { - - public String name() { - return "NarrowOop"; - } - - @Override - public String toString() { - return name(); - } - - public Constant getDefaultValue() { - return HotSpotCompressedNullConstant.COMPRESSED_NULL; - } - }; - private final CompressEncoding encoding; public NarrowOopStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull, CompressEncoding encoding) { @@ -71,8 +55,8 @@ } @Override - public PlatformKind getPlatformKind(PlatformKindTool tool) { - return NarrowOop; + public LIRKind getLIRKind(LIRKindTool tool) { + return LIRKind.reference(Kind.Int); } @Override @@ -117,4 +101,13 @@ } return super.equals(other); } + + @Override + public Constant asConstant() { + if (alwaysNull()) { + return HotSpotCompressedNullConstant.COMPRESSED_NULL; + } else { + return null; + } + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -45,7 +45,7 @@ @Override protected boolean verify(StructuredGraph graph, PhaseContext context) { for (ConstantNode node : getConstantNodes(graph)) { - if (node.recordsUsages() || !node.gatherUsages(graph).isEmpty()) { + if (node.recordsUsages()) { if (isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node) && !isBoundMethodHandle(node)) { throw new VerificationError("illegal object constant: " + node); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,6 +26,7 @@ import static com.oracle.graal.nodes.ConstantNode.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.HotSpotVMConfig.*; import com.oracle.graal.hotspot.meta.*; @@ -61,13 +62,35 @@ if (constant instanceof HotSpotObjectConstant && HotSpotObjectConstant.asObject(constant) instanceof Class) { MetaAccessProvider metaAccess = context.getMetaAccess(); ResolvedJavaType type = metaAccess.lookupJavaType((Class) HotSpotObjectConstant.asObject(constant)); - assert type instanceof HotSpotResolvedObjectType; - - Constant klass = ((HotSpotResolvedObjectType) type).klass(); + Constant klass; + LocationNode location; + if (type instanceof HotSpotResolvedObjectType) { + location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Object, classMirrorOffset, graph); + klass = ((HotSpotResolvedObjectType) type).klass(); + } else { + /* + * Primitive classes are more difficult since they don't have a corresponding Klass* + * so get them from Class.TYPE for the java box type. + */ + HotSpotResolvedPrimitiveType primitive = (HotSpotResolvedPrimitiveType) type; + ResolvedJavaType boxingClass = metaAccess.lookupJavaType(primitive.getKind().toBoxedJavaClass()); + klass = ((HotSpotResolvedObjectType) boxingClass).klass(); + HotSpotResolvedJavaField[] a = (HotSpotResolvedJavaField[]) boxingClass.getStaticFields(); + HotSpotResolvedJavaField typeField = null; + for (HotSpotResolvedJavaField f : a) { + if (f.getName().equals("TYPE")) { + typeField = f; + break; + } + } + if (typeField == null) { + throw new GraalInternalError("Can't find TYPE field in class"); + } + location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Object, typeField.offset(), graph); + } ConstantNode klassNode = ConstantNode.forConstant(klass, metaAccess, graph); Stamp stamp = StampFactory.exactNonNull(metaAccess.lookupJavaType(Class.class)); - LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Object, classMirrorOffset, graph); FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp)); if (HotSpotObjectConstant.isCompressed(constant)) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -20,6 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +//JaCoCo Exclude package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.api.meta.LocationIdentity.*; @@ -40,7 +41,7 @@ import com.oracle.graal.runtime.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class ArrayCopyCallNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single { +public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { @Input private ValueNode src; @Input private ValueNode srcPos; @@ -49,10 +50,15 @@ @Input private ValueNode length; private Kind elementKind; + + /** + * Aligned means that the offset of the copy is heap word aligned. + */ private boolean aligned; private boolean disjoint; + private boolean uninitialized; - private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint) { + private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, boolean uninitialized) { super(StampFactory.forVoid()); assert elementKind != null; this.src = src; @@ -63,10 +69,11 @@ this.elementKind = elementKind; this.aligned = aligned; this.disjoint = disjoint; + this.uninitialized = uninitialized; } - private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind) { - this(src, srcPos, dest, destPos, length, elementKind, false, false); + private ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean disjoint) { + this(src, srcPos, dest, destPos, length, elementKind, false, disjoint, false); } public ValueNode getSource() { @@ -85,31 +92,10 @@ return destPos; } - @Override - public ValueNode getArray() { - return dest; - } - - @Override - public ValueNode getIndex() { - return destPos; - } - - @Override public ValueNode getLength() { return length; } - @Override - public boolean isObjectArray() { - return elementKind == Kind.Object; - } - - @Override - public boolean isInitialization() { - return false; - } - public void addSnippetArguments(Arguments args) { args.add("src", src); args.add("srcPos", srcPos); @@ -137,13 +123,13 @@ public void lower(LoweringTool tool) { if (graph().getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { updateAlignedDisjoint(); - ForeignCallDescriptor desc = HotSpotHostForeignCallsProvider.lookupArraycopyDescriptor(elementKind, isAligned(), isDisjoint()); + ForeignCallDescriptor desc = HotSpotHostForeignCallsProvider.lookupArraycopyDescriptor(elementKind, isAligned(), isDisjoint(), isUninitialized()); StructuredGraph graph = graph(); ValueNode srcAddr = computeBase(getSource(), getSourcePosition()); ValueNode destAddr = computeBase(getDestination(), getDestinationPosition()); ValueNode len = getLength(); if (len.stamp().getStackKind() != Kind.Long) { - len = IntegerConvertNode.convert(len, StampFactory.forKind(Kind.Long)); + len = IntegerConvertNode.convert(len, StampFactory.forKind(Kind.Long), graph()); } ForeignCallNode call = graph.add(new ForeignCallNode(Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len)); call.setStateAfter(stateAfter()); @@ -161,11 +147,20 @@ } @NodeIntrinsic - public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind); + private static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind, @ConstantNodeParameter boolean aligned, + @ConstantNodeParameter boolean disjoint, @ConstantNodeParameter boolean uninitialized); + + public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind, boolean aligned, boolean disjoint) { + arraycopy(src, srcPos, dest, destPos, length, elementKind, aligned, disjoint, false); + } - @NodeIntrinsic - public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind, @ConstantNodeParameter boolean aligned, - @ConstantNodeParameter boolean disjoint); + public static void disjointArraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind) { + arraycopy(src, srcPos, dest, destPos, length, elementKind, false, true, false); + } + + public static void disjointUninitializedArraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter Kind elementKind) { + arraycopy(src, srcPos, dest, destPos, length, elementKind, false, true, true); + } public boolean isAligned() { return aligned; @@ -175,6 +170,10 @@ return disjoint; } + public boolean isUninitialized() { + return uninitialized; + } + public void updateAlignedDisjoint() { Kind componentKind = elementKind; if (srcPos == destPos) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AssertionSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AssertionSnippets.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, 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.replacements; + +import static com.oracle.graal.hotspot.nodes.CStringNode.*; +import static com.oracle.graal.replacements.SnippetTemplate.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +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.spi.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.word.*; + +public class AssertionSnippets implements Snippets { + + /** + * This call can only be used with true for the "vmError" parameter, so that it can be + * configured to be a leaf method. + */ + public static final ForeignCallDescriptor ASSERTION_VM_MESSAGE_C = new ForeignCallDescriptor("assertionVmMessageC", void.class, boolean.class, Word.class, long.class, long.class, long.class); + + @Snippet + public static void assertion(boolean value, @ConstantParameter String message) { + if (!value) { + vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); + } + } + + @Snippet + public static void stubAssertion(boolean value, @ConstantParameter String message) { + if (!value) { + vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); + } + } + + @NodeIntrinsic(ForeignCallNode.class) + private static native void vmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3); + + @NodeIntrinsic(StubForeignCallNode.class) + private static native void stubVmMessageC(@ConstantNodeParameter ForeignCallDescriptor stubPrintfC, boolean vmError, Word format, long v1, long v2, long v3); + + public static class Templates extends AbstractTemplates { + + private final SnippetInfo assertion = snippet(AssertionSnippets.class, "assertion"); + private final SnippetInfo stubAssertion = snippet(AssertionSnippets.class, "stubAssertion"); + + public Templates(HotSpotProviders providers, TargetDescription target) { + super(providers, providers.getSnippetReflection(), target); + } + + public void lower(AssertionNode assertionNode, LoweringTool tool) { + StructuredGraph graph = assertionNode.graph(); + Arguments args = new Arguments(graph.start() instanceof StubStartNode ? stubAssertion : assertion, graph.getGuardsStage(), tool.getLoweringStage()); + args.add("value", assertionNode.value()); + args.addConst("message", "failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")"); + + template(args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args); + } + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Mon Jun 30 12:02:19 2014 +0200 @@ -82,6 +82,9 @@ return klass.equal(0); } + @MacroSubstitution(macro = ClassGetClassLoader0Node.class, isStatic = false) + public static native ClassLoader getClassLoader0(Class thisObj); + @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getSuperclass(final Class thisObj) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Jun 30 12:02:19 2014 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -539,7 +540,7 @@ private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object); public static Word loadWordFromObject(Object object, int offset) { - assert offset != hubOffset() : "Use loadHubIntrinsic instead"; + ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject"); return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.ANY_LOCATION); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Jun 30 12:02:19 2014 +0200 @@ -223,7 +223,7 @@ protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { if (replacer.instanceOf instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf; - ValueNode object = instanceOf.object(); + ValueNode object = instanceOf.getValue(); TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue()); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), providers.getMetaAccess(), instanceOf.graph()); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -38,12 +38,13 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; /** * Node for invocation methods defined on the class {@link MethodHandle}. */ -public class MethodHandleNode extends MacroNode implements Canonicalizable { +public class MethodHandleNode extends MacroNode implements Simplifiable { /** The method that this node is representing. */ private final IntrinsicMethod intrinsicMethod; @@ -81,7 +82,7 @@ } @Override - public Node canonical(CanonicalizerTool tool) { + public void simplify(SimplifierTool tool) { InvokeNode invoke; switch (intrinsicMethod) { case INVOKE_BASIC: @@ -97,9 +98,11 @@ throw GraalInternalError.shouldNotReachHere(); } if (invoke != null) { - return invoke; + FixedNode next = next(); + replaceAtUsages(invoke); + GraphUtil.removeFixedWithUnusedInputs(this); + graph().addBeforeFixed(next, invoke); } - return this; } /** diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Jun 30 12:02:19 2014 +0200 @@ -501,7 +501,7 @@ graph.addAfterFixed(graph.start(), invoke); StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod()); - InliningUtil.inline(invoke, inlineeGraph, false); + InliningUtil.inline(invoke, inlineeGraph, false, null); List rets = graph.getNodes(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { @@ -520,7 +520,7 @@ inlineeGraph = template(args).copySpecializedGraph(); // inlineeGraph = replacements.getSnippet(checkCounter.getMethod()); - InliningUtil.inline(invoke, inlineeGraph, false); + InliningUtil.inline(invoke, inlineeGraph, false, null); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Jun 30 12:02:19 2014 +0200 @@ -141,7 +141,7 @@ if (useTLAB() && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, false); - result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, false, true); + result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, true); } else { new_stub.inc(); result = NewInstanceStubCall.call(hub); @@ -290,16 +290,16 @@ * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ - private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean noAsserts, boolean useSnippetCounters) { - assert noAsserts || size % 8 == 0 : "unaligned object size"; + private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { + ReplacementsUtil.runtimeAssert((size & 0x7) == 0, "unaligned object size"); int offset = startOffset; - if (offset % 8 != 0) { + if ((offset & 0x7) != 0) { memory.writeInt(offset, 0, INIT_LOCATION); offset += 4; } - assert noAsserts || offset % 8 == 0 : "unaligned"; + ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset"); if (manualUnroll && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { - assert noAsserts || !constantSize : "size shouldn't be constant at instantiation time"; + ReplacementsUtil.staticAssert(!constantSize, "size shouldn't be constant at instantiation time"); // This case handles arrays of constant length. Instead of having a snippet variant for // each length, generate a chain of stores of maximum length. Once it's inlined the // break statement will trim excess stores. @@ -337,17 +337,17 @@ * since they can't be compiled in stubs. */ public static Object formatObjectForStub(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord) { - return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, true, false); + return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, false); } /** * Formats some allocated memory with an object header and zeroes out the rest. */ - protected static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean noAsserts, boolean useSnippetCounters) { + protected static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean useSnippetCounters) { Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(size, memory, constantSize, instanceHeaderSize(), false, noAsserts, useSnippetCounters); + zeroMemory(size, memory, constantSize, instanceHeaderSize(), false, useSnippetCounters); } return memory.toObject(); } @@ -364,7 +364,7 @@ */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, true, useSnippetCounters); + zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, useSnippetCounters); } return memory.toObject(); } @@ -420,13 +420,14 @@ Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); - args.add("length", newArrayNode.length()); + ValueNode length = newArrayNode.length(); + args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length)); args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); args.addConst("headerSize", headerSize); args.addConst("log2ElementSize", log2ElementSize); args.addConst("fillContents", newArrayNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("maybeUnroll", newArrayNode.length().isConstant()); + args.addConst("maybeUnroll", length.isConstant()); args.addConst("typeContext", ProfileAllocations.getValue() ? toJavaName(arrayType, false) : ""); SnippetTemplate template = template(args); @@ -445,9 +446,11 @@ } public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { + StructuredGraph graph = newArrayNode.graph(); Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage()); args.add("elementType", newArrayNode.getElementType()); - args.add("length", newArrayNode.length()); + ValueNode length = newArrayNode.length(); + args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length)); args.addConst("fillContents", newArrayNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -77,6 +77,7 @@ assert snippetGraph != null : "ObjectCloneSnippets should be installed"; return lowerReplacement(snippetGraph.copy(), tool); } + assert false : "unhandled array type " + type.getComponentType().getKind(); } else { type = getConcreteType(getObject().stamp(), tool.assumptions(), tool.getMetaAccess()); if (type != null) { @@ -106,7 +107,7 @@ /* * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an * exact type) and if it is a cloneable type. - * + * * If yes, then the exact type is returned, otherwise it returns null. */ private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,10 +36,14 @@ public static final EnumMap arrayCloneMethods = new EnumMap<>(Kind.class); static { + arrayCloneMethods.put(Kind.Boolean, getCloneMethod("booleanArrayClone", boolean[].class)); arrayCloneMethods.put(Kind.Byte, getCloneMethod("byteArrayClone", byte[].class)); arrayCloneMethods.put(Kind.Char, getCloneMethod("charArrayClone", char[].class)); + arrayCloneMethods.put(Kind.Short, getCloneMethod("shortArrayClone", short[].class)); arrayCloneMethods.put(Kind.Int, getCloneMethod("intArrayClone", int[].class)); + arrayCloneMethods.put(Kind.Float, getCloneMethod("floatArrayClone", float[].class)); arrayCloneMethods.put(Kind.Long, getCloneMethod("longArrayClone", long[].class)); + arrayCloneMethods.put(Kind.Double, getCloneMethod("doubleArrayClone", double[].class)); arrayCloneMethods.put(Kind.Object, getCloneMethod("objectArrayClone", Object[].class)); } @@ -52,47 +56,65 @@ } @Snippet(removeAllFrameStates = true) + public static boolean[] booleanArrayClone(boolean[] src) { + boolean[] result = (boolean[]) NewArrayNode.newUninitializedArray(Boolean.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Boolean); + return result; + } + + @Snippet(removeAllFrameStates = true) public static byte[] byteArrayClone(byte[] src) { - byte[] result = new byte[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + byte[] result = (byte[]) NewArrayNode.newUninitializedArray(Byte.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Byte); + return result; + } + + @Snippet(removeAllFrameStates = true) + public static short[] shortArrayClone(short[] src) { + short[] result = (short[]) NewArrayNode.newUninitializedArray(Short.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Short); return result; } @Snippet(removeAllFrameStates = true) public static char[] charArrayClone(char[] src) { - char[] result = new char[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + char[] result = (char[]) NewArrayNode.newUninitializedArray(Character.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Char); return result; } @Snippet(removeAllFrameStates = true) public static int[] intArrayClone(int[] src) { - int[] result = new int[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + int[] result = (int[]) NewArrayNode.newUninitializedArray(Integer.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Int); + return result; + } + + @Snippet(removeAllFrameStates = true) + public static float[] floatArrayClone(float[] src) { + float[] result = (float[]) NewArrayNode.newUninitializedArray(Float.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Float); return result; } @Snippet(removeAllFrameStates = true) public static long[] longArrayClone(long[] src) { - long[] result = new long[src.length]; - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + long[] result = (long[]) NewArrayNode.newUninitializedArray(Long.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Long); + return result; + } + + @Snippet(removeAllFrameStates = true) + public static double[] doubleArrayClone(double[] src) { + double[] result = (double[]) NewArrayNode.newUninitializedArray(Double.TYPE, src.length); + ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Double); return result; } @Snippet(removeAllFrameStates = true) public static Object[] objectArrayClone(Object[] src) { - Object[] result = (Object[]) DynamicNewArrayNode.newArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length); - for (int i = 0; i < result.length; i++) { - result[i] = src[i]; - } + Object[] result = (Object[]) DynamicNewArrayNode.newUninitializedArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length); + ArrayCopyCallNode.disjointUninitializedArraycopy(src, 0, result, 0, src.length, Kind.Object); return result; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -67,10 +67,18 @@ if (usages().isEmpty()) { return null; } else { + ResolvedJavaType type = StampTool.typeOrNull(getObject()); if (StampTool.isExactType(getObject())) { - ResolvedJavaType type = StampTool.typeOrNull(getObject()); Constant clazz = type.getEncoding(Representation.JavaClass); - return ConstantNode.forConstant(clazz, tool.getMetaAccess(), graph()); + return ConstantNode.forConstant(clazz, tool.getMetaAccess()); + } + if (type != null && tool.assumptions().useOptimisticAssumptions()) { + ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); + if (exactType != null) { + tool.assumptions().recordConcreteSubtype(type, exactType); + Constant clazz = exactType.getEncoding(Representation.JavaClass); + return ConstantNode.forConstant(clazz, tool.getMetaAccess()); + } } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -53,7 +53,7 @@ ConstantNode callerClassNode = getCallerClassNode(tool.getMetaAccess()); if (callerClassNode != null) { - graph().replaceFixedWithFloating(this, callerClassNode); + graph().replaceFixedWithFloating(this, graph().addOrUniqueWithInputs(callerClassNode)); } else { InvokeNode invoke = createInvoke(); graph().replaceFixedWithFixed(this, invoke); @@ -64,7 +64,7 @@ /** * If inlining is deep enough this method returns a {@link ConstantNode} of the caller class by * walking the the stack. - * + * * @param metaAccess * @return ConstantNode of the caller class, or null */ @@ -94,7 +94,7 @@ if (!method.ignoredBySecurityStackWalk()) { // We have reached the desired frame; return the holder class. HotSpotResolvedObjectType callerClass = method.getDeclaringClass(); - return ConstantNode.forConstant(HotSpotObjectConstant.forObject(callerClass.mirror()), metaAccess, graph()); + return ConstantNode.forConstant(HotSpotObjectConstant.forObject(callerClass.mirror()), metaAccess); } break; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Jun 30 12:02:19 2014 +0200 @@ -64,6 +64,11 @@ protected InstalledCode code; /** + * Compilation result from which {@link #code} was created. + */ + protected CompilationResult compResult; + + /** * The registers destroyed by this stub. */ private Set destroyedRegisters; @@ -152,7 +157,7 @@ CallingConvention incomingCc = linkage.getIncomingCallingConvention(); TargetDescription target = codeCache.getTarget(); - final CompilationResult compResult = new CompilationResult(); + compResult = new CompilationResult(); try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) { Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); SchedulePhase schedule = emitFrontEnd(providers, target, graph, assumptions, null, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, @@ -182,6 +187,18 @@ } assert code != null : "error installing stub " + this; } + return code; } + + /** + * Gets the compilation result for this stub, compiling it first if necessary, and installing it + * in code. + */ + public synchronized CompilationResult getCompilationResult(final Backend backend) { + if (code == null) { + getCode(backend); + } + return compResult; + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java --- a/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java Mon Jun 30 12:02:19 2014 +0200 @@ -52,20 +52,22 @@ * channel for any debug messages and debugging annotation processors requires some special * setup. */ - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; - private static final String LOGFILE = new File(System.getProperty("java.io.tmpdir"), "hotspotvmconfigprocessor.log").getPath(); - - private static PrintWriter log; + private PrintWriter log; /** - * Logging facility for the debugging the annotation processor. + * Logging facility for debugging the annotation processor. */ - private static synchronized PrintWriter getLog() { + private PrintWriter getLog() { if (log == null) { try { - log = new PrintWriter(new FileWriter(LOGFILE, true)); + // Create the log file within the generated source directory so it's easy to find. + // /tmp isn't platform independent and java.io.tmpdir can map anywhere, particularly + // on the mac. + FileObject file = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", getClass().getSimpleName() + "log"); + log = new PrintWriter(new FileWriter(file.toUri().getPath(), true)); } catch (IOException e) { // Do nothing } @@ -73,7 +75,7 @@ return log; } - private static synchronized void logMessage(String format, Object... args) { + private void logMessage(String format, Object... args) { if (!DEBUG) { return; } @@ -84,7 +86,7 @@ } } - private static synchronized void logException(Throwable t) { + private void logException(Throwable t) { if (!DEBUG) { return; } @@ -104,7 +106,7 @@ logMessage("throw for %s:\n", element); } logException(t); - processingEnv.getMessager().printMessage(Kind.ERROR, "Exception throw during processing: " + t.toString() + " " + Arrays.toString(Arrays.copyOf(t.getStackTrace(), 8)), element); + errorMessage(element, "Exception throw during processing: %s %s", t, Arrays.toString(Arrays.copyOf(t.getStackTrace(), 4))); } //@formatter:off diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConstant.java diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMField.java diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMFlag.java diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMType.java diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMValue.java --- a/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -45,6 +45,13 @@ VALUE } + /** + * If {@link #expression} is a C++ function name, {@link #signature} represents the signature of + * the function. + * + */ + String signature() default ""; + Type get() default Type.VALUE; /** diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Jun 30 12:02:19 2014 +0200 @@ -907,20 +907,20 @@ switch (opcode) { case NOP : /* nothing to do */ break; case ACONST_NULL : frameState.apush(appendConstant(Constant.NULL_OBJECT)); break; - case ICONST_M1 : frameState.ipush(appendConstant(Constant.INT_MINUS_1)); break; - case ICONST_0 : frameState.ipush(appendConstant(Constant.INT_0)); break; - case ICONST_1 : frameState.ipush(appendConstant(Constant.INT_1)); break; - case ICONST_2 : frameState.ipush(appendConstant(Constant.INT_2)); break; - case ICONST_3 : frameState.ipush(appendConstant(Constant.INT_3)); break; - case ICONST_4 : frameState.ipush(appendConstant(Constant.INT_4)); break; - case ICONST_5 : frameState.ipush(appendConstant(Constant.INT_5)); break; - case LCONST_0 : frameState.lpush(appendConstant(Constant.LONG_0)); break; - case LCONST_1 : frameState.lpush(appendConstant(Constant.LONG_1)); break; - case FCONST_0 : frameState.fpush(appendConstant(Constant.FLOAT_0)); break; - case FCONST_1 : frameState.fpush(appendConstant(Constant.FLOAT_1)); break; - case FCONST_2 : frameState.fpush(appendConstant(Constant.FLOAT_2)); break; - case DCONST_0 : frameState.dpush(appendConstant(Constant.DOUBLE_0)); break; - case DCONST_1 : frameState.dpush(appendConstant(Constant.DOUBLE_1)); break; + case ICONST_M1 : // fall through + case ICONST_0 : // fall through + case ICONST_1 : // fall through + case ICONST_2 : // fall through + case ICONST_3 : // fall through + case ICONST_4 : // fall through + case ICONST_5 : frameState.ipush(appendConstant(Constant.forInt(opcode - ICONST_0))); break; + case LCONST_0 : // fall through + case LCONST_1 : frameState.lpush(appendConstant(Constant.forLong(opcode - LCONST_0))); break; + case FCONST_0 : // fall through + case FCONST_1 : // fall through + case FCONST_2 : frameState.fpush(appendConstant(Constant.forFloat(opcode - FCONST_0))); break; + case DCONST_0 : // fall through + case DCONST_1 : frameState.dpush(appendConstant(Constant.forDouble(opcode - DCONST_0))); break; case BIPUSH : frameState.ipush(appendConstant(Constant.forInt(stream.readByte()))); break; case SIPUSH : frameState.ipush(appendConstant(Constant.forInt(stream.readShort()))); break; case LDC : // fall through diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Jun 30 12:02:19 2014 +0200 @@ -72,6 +72,10 @@ return new GraphBuilderConfiguration(false, false, false); } + public static GraphBuilderConfiguration getInfopointDefault() { + return new GraphBuilderConfiguration(false, false, true); + } + public static GraphBuilderConfiguration getEagerDefault() { return new GraphBuilderConfiguration(true, false, false); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -461,52 +461,52 @@ @Override protected ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y) { - return new IntegerAddNode(StampFactory.forKind(kind), x, y); + return new IntegerAddNode(x, y); } @Override protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) { - return new IntegerSubNode(StampFactory.forKind(kind), x, y); + return new IntegerSubNode(x, y); } @Override protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) { - return new IntegerMulNode(StampFactory.forKind(kind), x, y); + return new IntegerMulNode(x, y); } @Override protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatAddNode(StampFactory.forKind(kind), x, y, isStrictFP); + return new FloatAddNode(x, y, isStrictFP); } @Override protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatSubNode(StampFactory.forKind(kind), x, y, isStrictFP); + return new FloatSubNode(x, y, isStrictFP); } @Override protected ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatMulNode(StampFactory.forKind(kind), x, y, isStrictFP); + return new FloatMulNode(x, y, isStrictFP); } @Override protected ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatDivNode(StampFactory.forKind(kind), x, y, isStrictFP); + return new FloatDivNode(x, y, isStrictFP); } @Override protected ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new FloatRemNode(StampFactory.forKind(kind), x, y, isStrictFP); + return new FloatRemNode(x, y, isStrictFP); } @Override protected ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y) { - return new IntegerDivNode(StampFactory.forKind(kind), x, y); + return new IntegerDivNode(x, y); } @Override protected ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y) { - return new IntegerRemNode(StampFactory.forKind(kind), x, y); + return new IntegerRemNode(x, y); } @Override @@ -516,32 +516,32 @@ @Override protected ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y) { - return new LeftShiftNode(StampFactory.forKind(kind), x, y); + return new LeftShiftNode(x, y); } @Override protected ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y) { - return new RightShiftNode(StampFactory.forKind(kind), x, y); + return new RightShiftNode(x, y); } @Override protected ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y) { - return new UnsignedRightShiftNode(StampFactory.forKind(kind), x, y); + return new UnsignedRightShiftNode(x, y); } @Override protected ValueNode genAnd(Kind kind, ValueNode x, ValueNode y) { - return new AndNode(StampFactory.forKind(kind), x, y); + return new AndNode(x, y); } @Override protected ValueNode genOr(Kind kind, ValueNode x, ValueNode y) { - return new OrNode(StampFactory.forKind(kind), x, y); + return new OrNode(x, y); } @Override protected ValueNode genXor(Kind kind, ValueNode x, ValueNode y) { - return new XorNode(StampFactory.forKind(kind), x, y); + return new XorNode(x, y); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * 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.java; - -import static com.oracle.graal.api.meta.MetaUtil.*; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.options.*; -import com.oracle.graal.phases.*; - -/** - * Verifies that a class declaring one or more {@linkplain OptionValue options} has a class - * initializer that only initializes the option(s). This sanity check mitigates the possibility of - * an option value being used before the code that sets the value (e.g., from the command line) has - * been executed. - */ -public class VerifyOptionsPhase extends Phase { - - public static boolean checkOptions(MetaAccessProvider metaAccess) { - ServiceLoader sl = ServiceLoader.loadInstalled(Options.class); - Set checked = new HashSet<>(); - for (Options opts : sl) { - for (OptionDescriptor desc : opts) { - ResolvedJavaType holder = metaAccess.lookupJavaType(desc.getDeclaringClass()); - checkType(holder, desc, metaAccess, checked); - } - } - return true; - } - - private static void checkType(ResolvedJavaType type, OptionDescriptor option, MetaAccessProvider metaAccess, Set checked) { - if (!checked.contains(type)) { - checked.add(type); - ResolvedJavaType superType = type.getSuperclass(); - if (superType != null && !MetaUtil.isJavaLangObject(superType)) { - checkType(superType, option, metaAccess, checked); - } - ResolvedJavaMethod clinit = type.getClassInitializer(); - if (clinit != null) { - StructuredGraph graph = new StructuredGraph(clinit); - new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - new VerifyOptionsPhase(type, metaAccess, option).apply(graph); - } - } - } - - private final MetaAccessProvider metaAccess; - private final ResolvedJavaType declaringClass; - private final ResolvedJavaType optionValueType; - private final Set boxingTypes; - private final OptionDescriptor option; - - public VerifyOptionsPhase(ResolvedJavaType declaringClass, MetaAccessProvider metaAccess, OptionDescriptor option) { - this.metaAccess = metaAccess; - this.declaringClass = declaringClass; - this.optionValueType = metaAccess.lookupJavaType(OptionValue.class); - this.option = option; - this.boxingTypes = new HashSet<>(); - for (Class c : new Class[]{Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}) { - this.boxingTypes.add(metaAccess.lookupJavaType(c)); - } - } - - /** - * Checks whether a given method is allowed to be called. - */ - private boolean checkInvokeTarget(ResolvedJavaMethod method) { - ResolvedJavaType holder = method.getDeclaringClass(); - if (method.isConstructor()) { - if (optionValueType.isAssignableFrom(holder)) { - return true; - } - } else if (boxingTypes.contains(holder)) { - return method.getName().equals("valueOf"); - } else if (method.getDeclaringClass().equals(metaAccess.lookupJavaType(Class.class))) { - return method.getName().equals("desiredAssertionStatus"); - } else if (method.getDeclaringClass().equals(declaringClass)) { - return (method.getName().equals("$jacocoInit")); - } - return false; - } - - @Override - protected void run(StructuredGraph graph) { - for (ValueNode node : graph.getNodes().filter(ValueNode.class)) { - if (node instanceof StoreFieldNode) { - ResolvedJavaField field = ((StoreFieldNode) node).field(); - verify(field.getDeclaringClass().equals(declaringClass), node, "store to field " + format("%H.%n", field)); - verify(field.isStatic(), node, "store to field " + format("%H.%n", field)); - if (optionValueType.isAssignableFrom((ResolvedJavaType) field.getType())) { - verify(field.isFinal(), node, "option field " + format("%H.%n", field) + " not final"); - } else { - verify((field.isSynthetic()), node, "store to non-synthetic field " + format("%H.%n", field)); - } - } else if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); - ResolvedJavaMethod targetMethod = callTarget.targetMethod(); - verify(checkInvokeTarget(targetMethod), node, "invocation of " + format("%H.%n(%p)", targetMethod)); - } - } - } - - private void verify(boolean condition, Node node, String message) { - if (!condition) { - error(node, message); - } - } - - private void error(Node node, String message) { - String loc = GraphUtil.approxSourceLocation(node); - throw new GraalInternalError(String.format("The " + option.getName() + " option is declared in " + option.getDeclaringClass() + - " whose class hierarchy contains a class initializer (in %s) with a code pattern at or near %s implying an action other than initialization of an option:%n%n %s%n%n" + - "The recommended solution is to move " + option.getName() + " into a separate class (e.g., " + option.getDeclaringClass().getName() + ".Options).%n", - toJavaName(declaringClass), loc, message)); - } -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -44,6 +44,9 @@ */ public class JTTTest extends GraalCompilerTest { + public static final class DummyTestClass { + } + protected static final Set EMPTY = Collections. emptySet(); /** * The arguments which, if non-null, will replace the Locals in the test method's graph. @@ -64,9 +67,13 @@ assert parameterTypes.length == args.length; for (int i = 0; i < args.length; i++) { ParameterNode param = graph.getParameter(i); - Constant c = getSnippetReflection().forBoxed(parameterTypes[i].getKind(), args[i]); - ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph); - param.replaceAtUsages(replacement); + if (param != null) { + Constant c = getSnippetReflection().forBoxed(parameterTypes[i].getKind(), args[i]); + ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph); + param.replaceAtUsages(replacement); + } else { + // Parameter is not used and has been dead-code eliminated + } } } return graph; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_checkcast01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_checkcast01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_checkcast01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,12 @@ */ public class BC_checkcast01 extends JTTTest { + private static class TestClass { + } + static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new BC_checkcast01(); + static Object object4 = new TestClass(); public static int test(int arg) { Object obj; @@ -45,7 +48,7 @@ } else { obj = null; } - final BC_checkcast01 bc = (BC_checkcast01) obj; + final TestClass bc = (TestClass) obj; if (bc != null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_checkcast02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_checkcast02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_checkcast02.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,12 @@ */ public class BC_checkcast02 extends JTTTest { + private static class TestClass { + } + static Object[] o1 = {new Object()}; static String[] o2 = {""}; - static BC_checkcast02[] o3 = {new BC_checkcast02()}; + static TestClass[] o3 = {new TestClass()}; public static int test(int arg) { Object obj = null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_instanceof.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_instanceof.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_instanceof.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,12 @@ */ public class BC_instanceof extends JTTTest { + private static class TestClass { + } + static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new BC_instanceof(); + static Object object4 = new TestClass(); public static boolean test(int arg) { Object obj; @@ -45,7 +48,7 @@ } else { obj = null; } - return obj instanceof BC_instanceof; + return obj instanceof TestClass; } @Test diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokespecial.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokespecial.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokespecial.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,17 +30,19 @@ */ public class BC_invokespecial extends JTTTest { - static BC_invokespecial object = new BC_invokespecial(); + private static class TestClass { + @SuppressWarnings("static-method") + private int id(int i) { + return i; + } + } + + static TestClass object = new TestClass(); public static int test(int a) { return object.id(a); } - @SuppressWarnings("static-method") - private int id(int i) { - return i; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokespecial2.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokespecial2.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokespecial2.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,17 +33,19 @@ */ public class BC_invokespecial2 extends JTTTest { - static BC_invokespecial2 object = new BC_invokespecial2(); + private static class TestClass { + @SuppressWarnings("static-method") + private int id(int i) { + return 4 + i; + } + } + + static TestClass object = new TestClass(); public static int test(int a) { return 3 + object.id(a); } - @SuppressWarnings("static-method") - private int id(int i) { - return 4 + i; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokevirtual.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokevirtual.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_invokevirtual.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,16 +30,18 @@ */ public class BC_invokevirtual extends JTTTest { - static BC_invokevirtual object = new BC_invokevirtual(); + private static class TestClass { + public int id(int i) { + return i; + } + } + + static TestClass object = new TestClass(); public static int test(int a) { return object.id(a); } - public int id(int i) { - return i; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_monitorenter.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_monitorenter.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_monitorenter.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,7 @@ */ public class BC_monitorenter extends JTTTest { - static BC_monitorenter object = new BC_monitorenter(); + static DummyTestClass object = new DummyTestClass(); public static int test(int arg) { synchronized (object) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_monitorenter02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_monitorenter02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_monitorenter02.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,7 @@ */ public class BC_monitorenter02 extends JTTTest { - static BC_monitorenter02 object = new BC_monitorenter02(); + static DummyTestClass object = new DummyTestClass(); public static int test(int arg, int arg2) { int result = arg; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_multianewarray01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_multianewarray01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_multianewarray01.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,7 +31,7 @@ public class BC_multianewarray01 extends JTTTest { public static int test(int a) { - final BC_multianewarray01[][] v = new BC_multianewarray01[3][3]; + final DummyTestClass[][] v = new DummyTestClass[3][3]; return v != null ? a : -1; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_multianewarray02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_multianewarray02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_multianewarray02.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,7 +31,7 @@ public class BC_multianewarray02 extends JTTTest { public static int test(int a) { - final BC_multianewarray02[][][][] v = new BC_multianewarray02[3][3][3][3]; + final DummyTestClass[][][][] v = new DummyTestClass[3][3][3][3]; return v != null ? a : -1; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_new.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_new.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_new.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ @SuppressWarnings("unused") public static int test(int a) { - new BC_new(); + new DummyTestClass(); return a; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,11 @@ */ public class BC_putfield_01 extends JTTTest { - private static BC_putfield_01 object = new BC_putfield_01(); + private static class TestClass { + private int field; + } - private int field; + private static TestClass object = new TestClass(); public static int test(int arg) { object.field = arg; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_02.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,11 @@ */ public class BC_putfield_02 extends JTTTest { - private static BC_putfield_02 object = new BC_putfield_02(); + private static class TestClass { + private Object field; + } - private Object field; + private static TestClass object = new TestClass(); public static Object test(Object arg) { object.field = arg; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_03.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,11 @@ */ public class BC_putfield_03 extends JTTTest { - private static BC_putfield_03 object = new BC_putfield_03(); + private static class TestClass { + private volatile int field; + } - private volatile int field; + private static TestClass object = new TestClass(); public static int test(int arg) { object.field = arg; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_04.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_putfield_04.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,11 @@ */ public class BC_putfield_04 extends JTTTest { - private static BC_putfield_04 object = new BC_putfield_04(); + private static class TestClass { + private volatile Object field; + } - private volatile Object field; + private static TestClass object = new TestClass(); public static Object test(Object arg) { object.field = arg; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_anewarray.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_anewarray.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_anewarray.java Mon Jun 30 12:02:19 2014 +0200 @@ -35,7 +35,7 @@ @SuppressWarnings("unused") public static int test(int a) { - final BC_anewarray[] v = new BC_anewarray[a]; + final DummyTestClass[] v = new DummyTestClass[a]; if (v != null) { return a; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new BC_checkcast(); + static Object object4 = new DummyTestClass(); public static int test(int arg) { Object obj = null; @@ -45,7 +45,7 @@ if (arg == 4) { obj = object4; } - final BC_checkcast bc = (BC_checkcast) obj; + final DummyTestClass bc = (DummyTestClass) obj; if (bc == null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast1.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast1.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast1.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new BC_checkcast1(); + static Object object4 = new DummyTestClass(); public static int test(int arg) { Object obj = null; @@ -45,7 +45,7 @@ if (arg == 4) { obj = object4; } - final BC_checkcast1 bc = (BC_checkcast1) obj; + final DummyTestClass bc = (DummyTestClass) obj; if (bc == null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast2.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast2.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast2.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new com.oracle.graal.jtt.except.BC_checkcast2(); + static Object object4 = new DummyTestClass(); public static int test(int arg) { Object obj; @@ -45,7 +45,7 @@ } else { obj = null; } - final BC_checkcast2 bc = (BC_checkcast2) obj; + final DummyTestClass bc = (DummyTestClass) obj; if (bc != null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast3.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast3.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast3.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object[] o1 = {new Object()}; static String[] o2 = {""}; - static BC_checkcast3[] o3 = {new BC_checkcast3()}; + static DummyTestClass[] o3 = {new DummyTestClass()}; public static int test(int arg) { Object obj = null; @@ -45,7 +45,7 @@ if (arg == 2) { obj = o3; } - Object[] r = (BC_checkcast3[]) obj; + Object[] r = (DummyTestClass[]) obj; return r == null ? -1 : -1; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast4.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast4.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast4.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new BC_checkcast4(); + static Object object4 = new DummyTestClass(); public static int test(int arg) { Object obj; @@ -45,7 +45,7 @@ } else { obj = null; } - final BC_checkcast4 bc = (BC_checkcast4) obj; + final DummyTestClass bc = (DummyTestClass) obj; if (bc != null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast5.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast5.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast5.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new BC_checkcast5(); + static Object object4 = new DummyTestClass(); public static int test(int arg) { Object obj; @@ -46,7 +46,7 @@ obj = null; } try { - final BC_checkcast5 bc = (BC_checkcast5) obj; + final DummyTestClass bc = (DummyTestClass) obj; if (bc != null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast6.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast6.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_checkcast6.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new BC_checkcast6(); + static Object object4 = new DummyTestClass(); public static int test(int arg) { Object obj; @@ -46,7 +46,7 @@ obj = null; } try { - final BC_checkcast6 bc = (BC_checkcast6) obj; + final DummyTestClass bc = (DummyTestClass) obj; if (bc != null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_getfield.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_getfield.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_getfield.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,12 +30,14 @@ public class BC_getfield extends JTTTest { - private static BC_getfield object = new BC_getfield(); + private static class TestClass { + private int field = 13; + } - private int field = 13; + private static TestClass object = new TestClass(); public static int test(int arg) { - final BC_getfield obj = (arg == 3) ? null : object; + final TestClass obj = (arg == 3) ? null : object; return obj.field; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_getfield1.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_getfield1.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_getfield1.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,11 @@ public class BC_getfield1 extends JTTTest { - private int field = 13; + private static class TestClass { + private int field = 13; + } - public static void test(BC_getfield1 arg) { + public static void test(TestClass arg) { @SuppressWarnings("unused") int i = arg.field; } @@ -50,7 +52,7 @@ @Test public void run2() throws Throwable { - runTest("test", new BC_getfield1()); + runTest("test", new TestClass()); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokespecial01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokespecial01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokespecial01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,21 +30,23 @@ */ public class BC_invokespecial01 extends JTTTest { - private static final BC_invokespecial01 obj = new BC_invokespecial01(); + private static class TestClass { + @SuppressWarnings("static-method") + private boolean method() { + return true; + } + } + + private static final TestClass obj = new TestClass(); public static boolean test(int arg) { - BC_invokespecial01 object = null; + TestClass object = null; if (arg == 0) { object = obj; } return object.method(); } - @SuppressWarnings("static-method") - private boolean method() { - return true; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokevirtual01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokevirtual01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokevirtual01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,20 +30,22 @@ */ public class BC_invokevirtual01 extends JTTTest { - private static final BC_invokevirtual01 obj = new BC_invokevirtual01(); + private static class TestClass { + public boolean method() { + return true; + } + } + + private static final TestClass obj = new TestClass(); public static boolean test(int arg) { - BC_invokevirtual01 object = null; + TestClass object = null; if (arg == 0) { object = obj; } return object.method(); } - public boolean method() { - return true; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokevirtual02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokevirtual02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_invokevirtual02.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,21 +30,23 @@ */ public class BC_invokevirtual02 extends JTTTest { - private static final BC_invokevirtual02 obj = new BC_invokevirtual02(); + private static class TestClass { + @SuppressWarnings("static-method") + public final boolean method() { + return true; + } + } + + private static final TestClass obj = new TestClass(); public static boolean test(int arg) { - BC_invokevirtual02 object = null; + TestClass object = null; if (arg == 0) { object = obj; } return object.method(); } - @SuppressWarnings("static-method") - public final boolean method() { - return true; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_monitorenter.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_monitorenter.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_monitorenter.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,7 @@ */ public class BC_monitorenter extends JTTTest { - static com.oracle.graal.jtt.bytecode.BC_monitorenter object = new com.oracle.graal.jtt.bytecode.BC_monitorenter(); + static DummyTestClass object = new DummyTestClass(); public static boolean test(boolean arg) { final Object o = arg ? object : null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_multianewarray.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_multianewarray.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_multianewarray.java Mon Jun 30 12:02:19 2014 +0200 @@ -35,7 +35,7 @@ @SuppressWarnings("unused") public static int test(int a, int b) { - final BC_multianewarray[][] v = new BC_multianewarray[a][b]; + final DummyTestClass[][] v = new DummyTestClass[a][b]; if (v != null) { return a; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_putfield.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_putfield.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_putfield.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,12 +30,14 @@ public class BC_putfield extends JTTTest { - private static BC_putfield object = new BC_putfield(); + private static class TestClass { + private int field; + } - private int field; + private static TestClass object = new TestClass(); public static int test(int arg) { - final BC_putfield obj = arg == 3 ? null : object; + final TestClass obj = arg == 3 ? null : object; obj.field = arg; return obj.field; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NASE_2.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NASE_2.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NASE_2.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,7 +36,7 @@ @SuppressWarnings("unused") public static int test(int a) { try { - Catch_NASE_2[] v = new Catch_NASE_2[a]; + DummyTestClass[] v = new DummyTestClass[a]; if (v != null) { return v.length; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,21 @@ */ public class Except_Synchronized01 extends JTTTest { - static final Except_Synchronized01 object = new Except_Synchronized01(); + private static class TestClass { + final int x = 1; - final int x = 1; + @SuppressWarnings("all") + public synchronized int test2(int i) throws Exception { + try { + TestClass object = null; + return object.x; + } catch (NullPointerException e) { + return 2; + } + } + } + + static final TestClass object = new TestClass(); public static int test(int i) throws Exception { if (i == 0) { @@ -41,16 +53,6 @@ return object.test2(i); } - @SuppressWarnings("all") - public synchronized int test2(int i) throws Exception { - try { - Except_Synchronized01 object = null; - return object.x; - } catch (NullPointerException e) { - return 2; - } - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized02.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,24 @@ public class Except_Synchronized02 extends JTTTest { - static final Except_Synchronized02 object = new Except_Synchronized02(); + private static class TestClass { + + final int x = 1; - final int x = 1; + @SuppressWarnings("all") + public synchronized int test2(int i) throws Exception { + while (true) { + try { + TestClass object = null; + return object.x; + } catch (NullPointerException e) { + return 2; + } + } + } + } + + static final TestClass object = new TestClass(); public static int test(int i) throws Exception { if (i == 0) { @@ -41,18 +56,6 @@ return object.test2(i); } - @SuppressWarnings("all") - public synchronized int test2(int i) throws Exception { - while (true) { - try { - Except_Synchronized02 object = null; - return object.x; - } catch (NullPointerException e) { - return 2; - } - } - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized03.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,25 @@ */ public class Except_Synchronized03 extends JTTTest { - static final Except_Synchronized03 object = new Except_Synchronized03(); + private static class TestClass { + int x = 1; - int x = 1; + @SuppressWarnings("all") + public synchronized int test2(int i) throws Exception { + while (true) { + try { + synchronized (this) { + TestClass object = null; + return object.x; + } + } catch (NullPointerException e) { + return 2; + } + } + } + } + + static final TestClass object = new TestClass(); public static int test(int i) throws Exception { if (i == 0) { @@ -41,20 +57,6 @@ return object.test2(i); } - @SuppressWarnings("all") - public synchronized int test2(int i) throws Exception { - while (true) { - try { - synchronized (this) { - Except_Synchronized03 object = null; - return object.x; - } - } catch (NullPointerException e) { - return 2; - } - } - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized04.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized04.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,9 +30,24 @@ public class Except_Synchronized04 extends JTTTest { - static final Except_Synchronized04 object = new Except_Synchronized04(); + private static class TestClass { + + final int x = 1; - final int x = 1; + @SuppressWarnings("all") + public int test2(int i) throws Exception { + try { + synchronized (Except_Synchronized04.class) { + TestClass object = null; + return object.x; + } + } catch (NullPointerException e) { + return 2; + } + } + } + + static final TestClass object = new TestClass(); public static int test(int i) throws Exception { if (i == 0) { @@ -41,18 +56,6 @@ return object.test2(i); } - @SuppressWarnings("all") - public int test2(int i) throws Exception { - try { - synchronized (Except_Synchronized04.class) { - Except_Synchronized04 object = null; - return object.x; - } - } catch (NullPointerException e) { - return 2; - } - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/StackTrace_CCE_00.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/StackTrace_CCE_00.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/StackTrace_CCE_00.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static Object object2 = new Object(); static Object object3 = ""; - static Object object4 = new StackTrace_CCE_00(); + static Object object4 = new DummyTestClass(); public static int test(int arg) { Object obj = null; @@ -46,7 +46,7 @@ obj = object4; } try { - final StackTrace_CCE_00 bc = (StackTrace_CCE_00) obj; + final DummyTestClass bc = (DummyTestClass) obj; if (bc == null) { return arg; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized04.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized04.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,14 @@ public class Throw_Synchronized04 extends JTTTest { - static final Throw_Synchronized04 object = new Throw_Synchronized04(); + private static class TestClass { + @SuppressWarnings("unused") + public synchronized boolean test2(int i) throws Exception { + throw new Exception(); + } + } + + static final TestClass object = new TestClass(); public static boolean test(int i) throws Exception { if (i == 0) { @@ -39,11 +46,6 @@ return object.test2(i); } - @SuppressWarnings("unused") - public synchronized boolean test2(int i) throws Exception { - throw new Exception(); - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized05.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized05.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized05.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,19 @@ public class Throw_Synchronized05 extends JTTTest { - static final Throw_Synchronized05 object = new Throw_Synchronized05(); + private static class TestClass { + @SuppressWarnings("unused") + public synchronized boolean test2(int i) throws Exception { + try { + throw new Exception(); + } catch (Exception e) { + // do nothing and then rethrow + throw e; + } + } + } + + static final TestClass object = new TestClass(); public static boolean test(int i) throws Exception { if (i == 0) { @@ -39,16 +51,6 @@ return object.test2(i); } - @SuppressWarnings("unused") - public synchronized boolean test2(int i) throws Exception { - try { - throw new Exception(); - } catch (Exception e) { - // do nothing and then rethrow - throw e; - } - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field02.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,25 +32,27 @@ */ public class HP_field02 extends JTTTest { - public int a; - public int b; - public int c; + private static class TestClass { + public int a; + public int b; + public int c; - public static int test(int count) { - return new HP_field02().run(count); + public int run(int count) { + for (int i = 0; i <= count; i++) { + if (i > 5) { + a += i; + } else if (i > 7) { + b += i; + } else { + c += i; + } + } + return a + b + c; + } } - public int run(int count) { - for (int i = 0; i <= count; i++) { - if (i > 5) { - a += i; - } else if (i > 7) { - b += i; - } else { - c += i; - } - } - return a + b + c; + public static int test(int count) { + return new TestClass().run(count); } @Test diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,29 +31,31 @@ */ public class HP_field04 extends JTTTest { - public byte b; - public char c; - public short s; - public int i; - public long l; - public float f; - public double d; + private static class TestClass { + public byte b; + public char c; + public short s; + public int i; + public long l; + public float f; + public double d; - public static int test(int count) { - return new HP_field04().run(count); + public int run(int count) { + for (int x = 0; x <= count; x++) { + b += x; + c += x; + s += x; + i += x; + l += x; + f += x; + d += x; + } + return (int) (b + c + s + i + l + f + d); + } } - public int run(int count) { - for (int x = 0; x <= count; x++) { - b += x; - c += x; - s += x; - i += x; - l += x; - f += x; - d += x; - } - return (int) (b + c + s + i + l + f + d); + public static int test(int count) { + return new TestClass().run(count); } @Test diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java Mon Jun 30 12:02:19 2014 +0200 @@ -60,7 +60,7 @@ /* * buildTestData - * + * * Builds the data used for the test -- each time the test is run. */ @@ -115,7 +115,7 @@ /* * calcEncryptKey - * + * * Builds the 52 16-bit encryption subkeys Z[] from the user key and stores in 32-bit int array. * The routing corrects an error in the source code in the Schnier book. Basically, the sense of * the 7- and 9-bit shifts are reversed. It still works reversed, but would encrypted code would @@ -169,7 +169,7 @@ /* * calcDecryptKey - * + * * Builds the 52 16-bit encryption subkeys DK[] from the encryption- subkeys Z[]. DK[] is a * 32-bit int array holding 16-bit values as unsigned. */ @@ -216,7 +216,7 @@ /* * cipher_idea - * + * * IDEA encryption/decryption algorithm. It processes plaintext in 64-bit blocks, one at a time, * breaking the block into four 16-bit unsigned subblocks. It goes through eight rounds of * processing using 6 new subkeys each time, plus four for last step. The source text is in @@ -359,7 +359,7 @@ /* * mul - * + * * Performs multiplication, modulo (2**16)+1. This code is structured on the assumption that * untaken branches are cheaper than taken branches, and that the compiler doesn't schedule * branches. Java: Must work with 32-bit int and one 64-bit long to keep 16-bit values and their @@ -369,7 +369,7 @@ * zero whenever the result would zero, be 2**16. And if one of the multiplicands is 0, the * result is not zero, but (2**16) + 1 minus the other multiplicand (sort of an additive inverse * mod 0x10001). - * + * * NOTE: The java conversion of this routine works correctly, but is half the speed of using * Java's modulus division function (%) on the multiplication with a 16-bit masking of the * result--running in the Symantec Caje IDE. So it's not called for now; the test uses Java % @@ -380,7 +380,7 @@ * private int mul(int a, int b) throws ArithmeticException { long p; // Large enough to catch * 16-bit multiply // without hitting sign bit. if (a != 0) { if (b != 0) { p = (long) a * b; b * = (int) p & 0xFFFF; // Lower 16 bits. a = (int) p >>> 16; // Upper 16 bits. - * + * * return (b - a + (b < a ? 1 : 0) & 0xFFFF); } else return ((1 - a) & 0xFFFF); // If b = 0, * then same as // 0x10001 - a. } else // If a = 0, then return return((1 - b) & 0xFFFF); // * same as 0x10001 - b. } @@ -388,15 +388,14 @@ /* * inv - * + * * Compute multiplicative inverse of x, modulo (2**16)+1 using extended Euclid's GCD (greatest * common divisor) algorithm. It is unrolled twice to avoid swapping the meaning of the * registers. And some subtracts are changed to adds. Java: Though it uses signed 32-bit ints, * the interpretation of the bits within is strictly unsigned 16-bit. */ - @SuppressWarnings("static-method") - private int inv(int x) { + public int inv(int x) { int x2 = x; int t0, t1; int q, y; @@ -440,7 +439,7 @@ /* * freeTestData - * + * * Nulls arrays and forces garbage collection to free up memory. */ @@ -462,4 +461,8 @@ runTest("test"); } + @Test + public void runInv() { + runTest("inv", 724); + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java Mon Jun 30 12:02:19 2014 +0200 @@ -34,13 +34,15 @@ */ public class UnsafeAccess01 extends JTTTest { - @SuppressWarnings("unused") private int field = 42; + private static class TestClass { + @SuppressWarnings("unused") private int field = 42; + } public static int test() throws SecurityException, NoSuchFieldException { final Unsafe unsafe = getUnsafe(); - final UnsafeAccess01 object = new UnsafeAccess01(); - final Field field = UnsafeAccess01.class.getDeclaredField("field"); + final TestClass object = new TestClass(); + final Field field = TestClass.class.getDeclaredField("field"); final long offset = unsafe.objectFieldOffset(field); final int value = unsafe.getInt(object, offset); return value; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static final String string = ""; static final Object object = new Object(); - static final Class_cast01 thisObject = new Class_cast01(); + static final DummyTestClass thisObject = new DummyTestClass(); public static int test(int i) { if (i == 0) { @@ -51,7 +51,7 @@ } } if (i == 3) { - if (Class_cast01.class.cast(object) == null) { + if (DummyTestClass.class.cast(object) == null) { return -1; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast02.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static final String string = ""; static final Object object = new Object(); - static final Class_cast02 thisObject = new Class_cast02(); + static final DummyTestClass thisObject = new DummyTestClass(); public static int test(int i) { if (i == 0) { @@ -51,7 +51,7 @@ } } if (i == 3) { - if (Class_cast02.class.cast(null) == null) { + if (DummyTestClass.class.cast(null) == null) { return -1; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance01.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static final String string = ""; static final Object obj = new Object(); - static final Class_isInstance01 thisObject = new Class_isInstance01(); + static final DummyTestClass thisObject = new DummyTestClass(); public static boolean test(int i) { Object object = null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance02.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static final String string = ""; static final Object obj = new Object(); - static final Class_isInstance02 thisObject = new Class_isInstance02(); + static final DummyTestClass thisObject = new DummyTestClass(); public static boolean test(int i) { Object object = null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance03.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static final String string = ""; static final Object obj = new Object(); - static final Class_isInstance03 thisObject = new Class_isInstance03(); + static final DummyTestClass thisObject = new DummyTestClass(); public static boolean test(int i) { Object object = null; @@ -45,7 +45,7 @@ if (i == 2) { object = thisObject; } - return Class_isInstance03.class.isInstance(object); + return DummyTestClass.class.isInstance(object); } @Test diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance06.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance06.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance06.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,12 +28,15 @@ import com.oracle.graal.jtt.*; -public final class Class_isInstance06 extends JTTTest implements Cloneable { +public final class Class_isInstance06 extends JTTTest { + + private static class TestClass implements Cloneable { + } static final String string = ""; static final Object obj = new Object(); static final String[] sarray = {}; - static final Object thisObject = new Class_isInstance06(); + static final Object thisObject = new TestClass(); public static boolean test(int i) { Object object = null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance07.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance07.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_isInstance07.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,12 +28,12 @@ import com.oracle.graal.jtt.*; -public final class Class_isInstance07 extends JTTTest implements Cloneable { +public final class Class_isInstance07 extends JTTTest { static final String string = ""; static final Object obj = new Object(); static final String[] sarray = {}; - static final Object thisObject = new Class_isInstance07(); + static final Object thisObject = new DummyTestClass(); public static boolean test(int i, Class c) { Object object = null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_clone01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_clone01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_clone01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,17 +30,19 @@ public class Object_clone01 extends JTTTest { - static final Object_clone01 field = new Object_clone01(); + private static class TestClass { + @SuppressWarnings("unused") + private boolean tryClone(int i) throws CloneNotSupportedException { + return this == this.clone(); + } + } + + static final TestClass field = new TestClass(); public static boolean test(int i) throws CloneNotSupportedException { return field.tryClone(i); } - @SuppressWarnings("unused") - private boolean tryClone(int i) throws CloneNotSupportedException { - return this == this.clone(); - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_clone02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_clone02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_clone02.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,19 +28,21 @@ import com.oracle.graal.jtt.*; -public class Object_clone02 extends JTTTest implements Cloneable { +public class Object_clone02 extends JTTTest { - static final Object_clone02 field = new Object_clone02(); + private static class TestClass implements Cloneable { + @SuppressWarnings("unused") + private boolean tryClone(int i) throws CloneNotSupportedException { + return this == this.clone(); + } + } + + static final TestClass field = new TestClass(); public static boolean test(int i) throws CloneNotSupportedException { return field.tryClone(i); } - @SuppressWarnings("unused") - private boolean tryClone(int i) throws CloneNotSupportedException { - return this == this.clone(); - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_equals01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_equals01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_equals01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,7 @@ public final class Object_equals01 extends JTTTest { - public static Object_equals01 field = new Object_equals01(); + public static DummyTestClass field = new DummyTestClass(); public static boolean test(int i) { final Object obj1 = new Object(); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,7 +32,7 @@ static final Object object = new Object(); static final Object string = new String(); - static final Object_getClass01 thisObject = new Object_getClass01(); + static final DummyTestClass thisObject = new DummyTestClass(); public static String test(int i) { if (i == 0) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,6 +30,13 @@ public class Object_toString01 extends JTTTest { + private static class TestClass { + @Override + public String toString() { + return string; + } + } + static final String string = "Object_toString01"; static final Object object = new Object(); @@ -38,16 +45,11 @@ return object.toString() != null; } if (i == 1) { - return new Object_toString01().toString() == string; + return new TestClass().toString() == string; } return false; } - @Override - public String toString() { - return string; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString02.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,7 +33,14 @@ public class Object_toString02 extends JTTTest { - static final Object obj = new Object_toString02(); + private static class TestClass { + @Override + public String toString() { + return "XYZ"; + } + } + + static final Object obj = new TestClass(); public static String test(int i) { Object object = null; @@ -47,11 +54,6 @@ return object.toString(); } - @Override - public String toString() { - return "XYZ"; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop16.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop16.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop16.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,30 +32,32 @@ */ public class Loop16 extends JTTTest { - public int a; - public int b; - public int c; + private static class TestClass { + public int a; + public int b; + public int c; - public static int test(int count) { - return new Loop16().run(count); + public int run(int count) { + l1: for (int i = 0; i <= count; i++) { + if (i > 5) { + for (int j = 0; j < i; j++) { + a += i; + if (a > 500) { + break l1; + } + } + } else if (i > 7) { + b += i; + } else { + c += i; + } + } + return a + b + c; + } } - public int run(int count) { - l1: for (int i = 0; i <= count; i++) { - if (i > 5) { - for (int j = 0; j < i; j++) { - a += i; - if (a > 500) { - break l1; - } - } - } else if (i > 7) { - b += i; - } else { - c += i; - } - } - return a + b + c; + public static int test(int count) { + return new TestClass().run(count); } @Test diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java Mon Jun 30 12:02:19 2014 +0200 @@ -44,11 +44,11 @@ } static void oneOperandStackSlot() { - new StrangeFrames(); + new DummyTestClass(); } static void twoOperandStackSlots() { - two(new StrangeFrames(), new StrangeFrames()); + two(new DummyTestClass(), new DummyTestClass()); } static void oneLocalSlot() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,13 +33,62 @@ @SuppressWarnings("unused") public class Conditional01 extends JTTTest { + private static class TestClass { + private int nextPC; + private int pc; + private boolean aC; + private boolean aH; + private boolean aN; + private boolean aZ; + private boolean aV; + private boolean aS; + private int cyclesConsumed; + private int[] sram = new int[RAM_SIZE]; + + public void visit(CPC i) { + nextPC = pc + 2; + int tmp0 = getRegisterByte(i.r1); + int tmp1 = getRegisterByte(i.r2); + int tmp2 = bit(aC); + int tmp3 = tmp0 - tmp1 - tmp2; + boolean tmp4 = ((tmp0 & 128) != 0); + boolean tmp5 = ((tmp1 & 128) != 0); + boolean tmp6 = ((tmp3 & 128) != 0); + boolean tmp7 = ((tmp0 & 8) != 0); + boolean tmp8 = ((tmp1 & 8) != 0); + boolean tmp9 = ((tmp3 & 8) != 0); + aH = !tmp7 && tmp8 || tmp8 && tmp9 || tmp9 && !tmp7; + aC = !tmp4 && tmp5 || tmp5 && tmp6 || tmp6 && !tmp4; + aN = tmp6; + aZ = low(tmp3) == 0 && aZ; + aV = tmp4 && !tmp5 && !tmp6 || !tmp4 && tmp5 && tmp6; + aS = (aN != aV); + cyclesConsumed++; + } + + public int getRegisterByte(Register r1) { + if ((r1.val % 10) == 0) { + return sram[r1.num]; + } + return r1.val; + } + + public int low(int tmp3) { + return tmp3 & 0x01; + } + + public int bit(boolean c2) { + return c2 ? 1 : 0; + } + } + private static final int RAM_SIZE = 0x100; private static final int init = new Random().nextInt(); private static final int init1 = new Register().val; private static final Register init2 = new CPC().r1; public static int test(int arg) { - Conditional01 c = new Conditional01(); + TestClass c = new TestClass(); Random rnd = new Random(); for (int i = 0; i < arg; i++) { CPC i2 = new CPC(); @@ -71,53 +120,6 @@ } - private int nextPC; - private int pc; - private boolean aC; - private boolean aH; - private boolean aN; - private boolean aZ; - private boolean aV; - private boolean aS; - private int cyclesConsumed; - private int[] sram = new int[RAM_SIZE]; - - public void visit(CPC i) { - nextPC = pc + 2; - int tmp0 = getRegisterByte(i.r1); - int tmp1 = getRegisterByte(i.r2); - int tmp2 = bit(aC); - int tmp3 = tmp0 - tmp1 - tmp2; - boolean tmp4 = ((tmp0 & 128) != 0); - boolean tmp5 = ((tmp1 & 128) != 0); - boolean tmp6 = ((tmp3 & 128) != 0); - boolean tmp7 = ((tmp0 & 8) != 0); - boolean tmp8 = ((tmp1 & 8) != 0); - boolean tmp9 = ((tmp3 & 8) != 0); - aH = !tmp7 && tmp8 || tmp8 && tmp9 || tmp9 && !tmp7; - aC = !tmp4 && tmp5 || tmp5 && tmp6 || tmp6 && !tmp4; - aN = tmp6; - aZ = low(tmp3) == 0 && aZ; - aV = tmp4 && !tmp5 && !tmp6 || !tmp4 && tmp5 && tmp6; - aS = (aN != aV); - cyclesConsumed++; - } - - public int getRegisterByte(Register r1) { - if ((r1.val % 10) == 0) { - return sram[r1.num]; - } - return r1.val; - } - - public int low(int tmp3) { - return tmp3 & 0x01; - } - - public int bit(boolean c2) { - return c2 ? 1 : 0; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Fold_Cast01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Fold_Cast01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Fold_Cast01.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,20 +31,22 @@ */ public class Fold_Cast01 extends JTTTest { - static final Object object = new Fold_Cast01(); + private static class TestClass { + int field = 9; + } - int field = 9; + static final Object object = new TestClass(); public static int test(int arg) { if (arg == 0) { - return ((Fold_Cast01) object).field; + return ((TestClass) object).field; } if (arg == 1) { - Object obj = new Fold_Cast01(); - return ((Fold_Cast01) obj).field; + Object obj = new TestClass(); + return ((TestClass) obj).field; } if (arg == 2) { - return ((Fold_Cast01) null).field; + return ((TestClass) null).field; } return 0; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Fold_InstanceOf01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Fold_InstanceOf01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Fold_InstanceOf01.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,18 +31,18 @@ */ public class Fold_InstanceOf01 extends JTTTest { - static final Object object = new Fold_InstanceOf01(); + static final Object object = new DummyTestClass(); public static boolean test(int arg) { if (arg == 0) { - return object instanceof Fold_InstanceOf01; + return object instanceof DummyTestClass; } if (arg == 1) { - Object obj = new Fold_InstanceOf01(); - return obj instanceof Fold_InstanceOf01; + Object obj = new DummyTestClass(); + return obj instanceof DummyTestClass; } if (arg == 2) { - return null instanceof Fold_InstanceOf01; + return null instanceof DummyTestClass; } return false; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/LLE_01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/LLE_01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/LLE_01.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,10 +33,12 @@ */ public class LLE_01 extends JTTTest { - int field1; + private static class TestClass { + int field1; + } public static int test() { - LLE_01 o = new LLE_01(); + TestClass o = new TestClass(); o.field1 = 1; o.field1 = 0; return o.field1; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/List_reorder_bug.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/List_reorder_bug.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/List_reorder_bug.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,6 +31,38 @@ @SuppressWarnings("unused") public class List_reorder_bug extends JTTTest { + private static class TestClass { + String s; + + private void print(String s2) { + this.s = s2; + } + + private void match(Object a, int src, int id, int seq) { + print("match: " + src + ", " + id); + List item = list; + List itemPrev = null; + while (item != null) { + if (item.id == id) { + if (item.bool) { + outcall(item.id); + } + if (itemPrev != null) { + itemPrev.next = item.next; + } else { + list = item.next; + } + + item.next = null; + return; + } + + itemPrev = item; + item = item.next; + } + } + } + static class List { List(int id) { @@ -47,46 +79,16 @@ public static boolean test(int i) { list = new List(5); list.next = new List(6); - new List_reorder_bug().match(new Object(), 27, 6, 0); + new TestClass().match(new Object(), 27, 6, 0); return list.next == null; } - private void match(Object a, int src, int id, int seq) { - print("match: " + src + ", " + id); - List item = list; - List itemPrev = null; - while (item != null) { - if (item.id == id) { - if (item.bool) { - outcall(item.id); - } - if (itemPrev != null) { - itemPrev.next = item.next; - } else { - list = item.next; - } - - item.next = null; - return; - } - - itemPrev = item; - item = item.next; - } - } - static int globalId; private static void outcall(int id) { globalId = id; } - String s; - - private void print(String s2) { - this.s = s2; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_01.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,13 +31,15 @@ */ public class NCE_01 extends JTTTest { - public static NCE_01 object = new NCE_01(); + private static class TestClass { + int field1 = 22; + int field2 = 23; + } - int field1 = 22; - int field2 = 23; + public static TestClass object = new TestClass(); public static int test() { - NCE_01 o = object; + TestClass o = object; int i = o.field1; // expected null check elimination here return o.field2 + i; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_02.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,13 +31,15 @@ */ public class NCE_02 extends JTTTest { - public static NCE_02 object = new NCE_02(); + public static class TestClass { + int field1; + int field2 = 23; + } - int field1; - int field2 = 23; + public static TestClass object = new TestClass(); public static int test() { - NCE_02 o = object; + TestClass o = object; o.field1 = 11; // expect non-null o.field1 = 22; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_03.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,14 +31,16 @@ */ public class NCE_03 extends JTTTest { - private static boolean cond = true; - public static NCE_03 object = new NCE_03(); + public static class TestClass { + int field1; + int field2 = 23; + } - int field1; - int field2 = 23; + private static boolean cond = true; + public static TestClass object = new TestClass(); public static int test() { - NCE_03 o = object; + TestClass o = object; o.field1 = 11; if (cond) { // expect non-null diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_04.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_04.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,14 +31,16 @@ */ public class NCE_04 extends JTTTest { - private static boolean cond = true; - public static NCE_04 object = new NCE_04(); + public static class TestClass { + int field1; + int field2 = 23; + } - int field1; - int field2 = 23; + private static boolean cond = true; + public static TestClass object = new TestClass(); public static int test() { - NCE_04 o = object; + TestClass o = object; if (cond) { o.field1 = 22; } else { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NestedLoop_EA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NestedLoop_EA.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, 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.graal.jtt.optimize; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.jtt.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.virtual.phases.ea.*; + +public class NestedLoop_EA extends JTTTest { + + @Override + protected Suites createSuites() { + Suites suites = super.createSuites(); + ListIterator> position = suites.getHighTier().findPhase(PartialEscapePhase.class); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!GraalOptions.ImmutableCode.getValue()); + // incremental canonicalizer of PEA is missing some important canonicalization (TODO?) + position.add(canonicalizer); + position.add(new PartialEscapePhase(true, canonicalizer)); + return suites; + } + + static class Frame { + Object objects[] = new Object[10]; + } + + final static int RESULT_SLOT = 0; + final static int K_SLOT = 1; + final static int I_SLOT = 2; + final static int ARG_SLOT = 3; + final static int STACK_BASE = 4; + + static class Pointer { + public int sp = STACK_BASE; + } + + public static int simpleLoop(int arg) { + Frame f = new Frame(); + Pointer p = new Pointer(); + f.objects[ARG_SLOT] = arg; + f.objects[RESULT_SLOT] = 0; + f.objects[K_SLOT] = 0; + for (; (int) f.objects[K_SLOT] < (int) f.objects[ARG_SLOT];) { + + f.objects[RESULT_SLOT] = (int) f.objects[RESULT_SLOT] + 5; + + f.objects[++p.sp] = f.objects[K_SLOT]; + f.objects[++p.sp] = 1; + int result = (int) f.objects[p.sp] + (int) f.objects[p.sp - 1]; + p.sp--; + f.objects[p.sp] = result; + f.objects[K_SLOT] = (int) f.objects[p.sp]; + p.sp--; + } + return (int) f.objects[RESULT_SLOT]; + } + + @Test + public void run0() throws Throwable { + runTest("simpleLoop", 5); + } + + public static int nestedLoop(int arg) { + Frame f = new Frame(); + Pointer p = new Pointer(); + f.objects[ARG_SLOT] = arg; + f.objects[RESULT_SLOT] = 0; + f.objects[K_SLOT] = 0; + for (; (int) f.objects[K_SLOT] < (int) f.objects[ARG_SLOT];) { + + f.objects[I_SLOT] = 0; + for (; (int) f.objects[I_SLOT] < (int) f.objects[ARG_SLOT];) { + f.objects[RESULT_SLOT] = (int) f.objects[RESULT_SLOT] + 5; + + f.objects[++p.sp] = f.objects[I_SLOT]; + f.objects[++p.sp] = 1; + int result = (int) f.objects[p.sp] + (int) f.objects[p.sp - 1]; + p.sp--; + f.objects[p.sp] = result; + f.objects[I_SLOT] = (int) f.objects[p.sp]; + p.sp--; + } + + f.objects[++p.sp] = f.objects[K_SLOT]; + f.objects[++p.sp] = 1; + int result = (int) f.objects[p.sp] + (int) f.objects[p.sp - 1]; + p.sp--; + f.objects[p.sp] = result; + f.objects[K_SLOT] = (int) f.objects[p.sp]; + p.sp--; + } + return (int) f.objects[RESULT_SLOT]; + } + + @Test + public void run1() throws Throwable { + runTest("nestedLoop", 5); + } + + @Override + protected boolean checkHighTierGraph(StructuredGraph graph) { + assert graph.getNodes().filter(CommitAllocationNode.class).count() == 0 : "all allocations should be virtualized"; + return true; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Cast01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Cast01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Cast01.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,9 +31,11 @@ */ public class VN_Cast01 extends JTTTest { - static final Object object = new VN_Cast01(); + private static class TestClass { + int field = 9; + } - int field = 9; + static final Object object = new TestClass(); public static int test(int arg) { if (arg == 0) { @@ -50,23 +52,23 @@ private static int test1() { Object o = object; - VN_Cast01 a = (VN_Cast01) o; - VN_Cast01 b = (VN_Cast01) o; + TestClass a = (TestClass) o; + TestClass b = (TestClass) o; return a.field + b.field; } private static int test2() { - Object obj = new VN_Cast01(); - VN_Cast01 a = (VN_Cast01) obj; - VN_Cast01 b = (VN_Cast01) obj; + Object obj = new TestClass(); + TestClass a = (TestClass) obj; + TestClass b = (TestClass) obj; return a.field + b.field; } @SuppressWarnings("all") private static int test3() { Object o = null; - VN_Cast01 a = (VN_Cast01) o; - VN_Cast01 b = (VN_Cast01) o; + TestClass a = (TestClass) o; + TestClass b = (TestClass) o; return a.field + b.field; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Cast02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Cast02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Cast02.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,10 +31,12 @@ */ public class VN_Cast02 extends JTTTest { + private static class TestClass { + int field = 9; + } + private static boolean cond = true; - static final Object object = new VN_Cast02(); - - int field = 9; + static final Object object = new TestClass(); public static int test(int arg) { if (arg == 0) { @@ -51,19 +53,19 @@ private static int test1() { Object o = object; - VN_Cast02 a = (VN_Cast02) o; + TestClass a = (TestClass) o; if (cond) { - VN_Cast02 b = (VN_Cast02) o; + TestClass b = (TestClass) o; return a.field + b.field; } return 0; } private static int test2() { - Object obj = new VN_Cast02(); - VN_Cast02 a = (VN_Cast02) obj; + Object obj = new TestClass(); + TestClass a = (TestClass) obj; if (cond) { - VN_Cast02 b = (VN_Cast02) obj; + TestClass b = (TestClass) obj; return a.field + b.field; } return 0; @@ -72,9 +74,9 @@ @SuppressWarnings("all") private static int test3() { Object o = null; - VN_Cast02 a = (VN_Cast02) o; + TestClass a = (TestClass) o; if (cond) { - VN_Cast02 b = (VN_Cast02) o; + TestClass b = (TestClass) o; return a.field + b.field; } return 0; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Field01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Field01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Field01.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,9 +31,11 @@ */ public class VN_Field01 extends JTTTest { - static final VN_Field01 object = new VN_Field01(); + private static class TestClass { + int field = 9; + } - int field = 9; + static final TestClass object = new TestClass(); public static int test(int arg) { if (arg == 0) { @@ -49,20 +51,20 @@ } private static int test1() { - VN_Field01 a = object; + TestClass a = object; return a.field + a.field; } private static int test2() { - VN_Field01 a = object; - VN_Field01 b = object; + TestClass a = object; + TestClass b = object; return a.field + b.field; } @SuppressWarnings("all") private static int test3() { - VN_Field01 a = null; - VN_Field01 b = null; + TestClass a = null; + TestClass b = null; return a.field + b.field; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Field02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Field02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_Field02.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,10 +31,12 @@ */ public class VN_Field02 extends JTTTest { + private static class TestClass { + int field = 9; + } + private static boolean cond = true; - static final VN_Field02 object = new VN_Field02(); - - int field = 9; + static final TestClass object = new TestClass(); public static int test(int arg) { if (arg == 0) { @@ -50,7 +52,7 @@ } private static int test1() { - VN_Field02 a = object; + TestClass a = object; int c = a.field; if (cond) { return c + a.field; @@ -59,9 +61,9 @@ } private static int test2() { - VN_Field02 a = object; + TestClass a = object; if (cond) { - VN_Field02 b = object; + TestClass b = object; return a.field + b.field; } return 0; @@ -69,9 +71,9 @@ @SuppressWarnings("all") private static int test3() { - VN_Field02 a = null; + TestClass a = null; if (cond) { - VN_Field02 b = null; + TestClass b = null; return a.field + b.field; } return 0; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf01.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,7 +31,7 @@ */ public class VN_InstanceOf01 extends JTTTest { - static final Object object = new VN_InstanceOf01(); + static final Object object = new DummyTestClass(); public static boolean test(int arg) { if (arg == 0) { @@ -48,21 +48,21 @@ } private static boolean foo1() { - boolean a = object instanceof VN_InstanceOf01; - boolean b = object instanceof VN_InstanceOf01; + boolean a = object instanceof DummyTestClass; + boolean b = object instanceof DummyTestClass; return a | b; } private static boolean foo2() { - Object obj = new VN_InstanceOf01(); - boolean a = obj instanceof VN_InstanceOf01; - boolean b = obj instanceof VN_InstanceOf01; + Object obj = new DummyTestClass(); + boolean a = obj instanceof DummyTestClass; + boolean b = obj instanceof DummyTestClass; return a | b; } private static boolean foo3() { - boolean a = null instanceof VN_InstanceOf01; - boolean b = null instanceof VN_InstanceOf01; + boolean a = null instanceof DummyTestClass; + boolean b = null instanceof DummyTestClass; return a | b; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,7 +33,7 @@ private static boolean cond = true; - static final Object object = new VN_InstanceOf02(); + static final Object object = new DummyTestClass(); public static boolean test(int arg) { if (arg == 0) { @@ -50,28 +50,28 @@ } private static boolean foo1() { - boolean a = object instanceof VN_InstanceOf02; + boolean a = object instanceof DummyTestClass; if (cond) { - boolean b = object instanceof VN_InstanceOf02; + boolean b = object instanceof DummyTestClass; return a | b; } return false; } private static boolean foo2() { - Object obj = new VN_InstanceOf02(); - boolean a = obj instanceof VN_InstanceOf02; + Object obj = new DummyTestClass(); + boolean a = obj instanceof DummyTestClass; if (cond) { - boolean b = obj instanceof VN_InstanceOf02; + boolean b = obj instanceof DummyTestClass; return a | b; } return false; } private static boolean foo3() { - boolean a = null instanceof VN_InstanceOf02; + boolean a = null instanceof DummyTestClass; if (cond) { - boolean b = null instanceof VN_InstanceOf02; + boolean b = null instanceof DummyTestClass; return a | b; } return false; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf03.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,17 +33,17 @@ private static boolean cond = true; - static final Object object = new VN_InstanceOf03(); + static final Object object = new DummyTestClass(); public static boolean test() { return foo(); } private static boolean foo() { - Object obj = new VN_InstanceOf03(); - boolean a = obj instanceof VN_InstanceOf03; + Object obj = new DummyTestClass(); + boolean a = obj instanceof DummyTestClass; if (cond) { - boolean b = obj instanceof VN_InstanceOf03; + boolean b = obj instanceof DummyTestClass; return a | b; } return false; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,34 +30,36 @@ */ public class Field_get02 extends JTTTest { - private static final Field_get02 object = new Field_get02(); + public static class TestClass { + public final byte byteField = 11; + public final short shortField = 12; + public final char charField = 13; + public final int intField = 14; + public final long longField = 15; + public final float floatField = 16; + public final double doubleField = 17; + public final boolean booleanField = true; + } - public final byte byteField = 11; - public final short shortField = 12; - public final char charField = 13; - public final int intField = 14; - public final long longField = 15; - public final float floatField = 16; - public final double doubleField = 17; - public final boolean booleanField = true; + private static final TestClass object = new TestClass(); public static boolean test(int arg) throws NoSuchFieldException, IllegalAccessException { if (arg == 0) { - return Field_get02.class.getField("byteField").get(object).equals(object.byteField); + return TestClass.class.getField("byteField").get(object).equals(object.byteField); } else if (arg == 1) { - return Field_get02.class.getField("shortField").get(object).equals(object.shortField); + return TestClass.class.getField("shortField").get(object).equals(object.shortField); } else if (arg == 2) { - return Field_get02.class.getField("charField").get(object).equals(object.charField); + return TestClass.class.getField("charField").get(object).equals(object.charField); } else if (arg == 3) { - return Field_get02.class.getField("intField").get(object).equals(object.intField); + return TestClass.class.getField("intField").get(object).equals(object.intField); } else if (arg == 4) { - return Field_get02.class.getField("longField").get(object).equals(object.longField); + return TestClass.class.getField("longField").get(object).equals(object.longField); } else if (arg == 5) { - return Field_get02.class.getField("floatField").get(object).equals(object.floatField); + return TestClass.class.getField("floatField").get(object).equals(object.floatField); } else if (arg == 6) { - return Field_get02.class.getField("doubleField").get(object).equals(object.doubleField); + return TestClass.class.getField("doubleField").get(object).equals(object.doubleField); } else if (arg == 7) { - return Field_get02.class.getField("booleanField").get(object).equals(object.booleanField); + return TestClass.class.getField("booleanField").get(object).equals(object.booleanField); } return false; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java Mon Jun 30 12:02:19 2014 +0200 @@ -43,29 +43,31 @@ static { try { - ByteField = Field_get03.class.getField("byteField"); - ShortField = Field_get03.class.getField("shortField"); - CharField = Field_get03.class.getField("charField"); - IntField = Field_get03.class.getField("intField"); - LongField = Field_get03.class.getField("longField"); - FloatField = Field_get03.class.getField("floatField"); - DoubleField = Field_get03.class.getField("doubleField"); - BooleanField = Field_get03.class.getField("booleanField"); + ByteField = TestClass.class.getField("byteField"); + ShortField = TestClass.class.getField("shortField"); + CharField = TestClass.class.getField("charField"); + IntField = TestClass.class.getField("intField"); + LongField = TestClass.class.getField("longField"); + FloatField = TestClass.class.getField("floatField"); + DoubleField = TestClass.class.getField("doubleField"); + BooleanField = TestClass.class.getField("booleanField"); } catch (SecurityException | NoSuchFieldException e) { throw new RuntimeException(e); } } - private static final Field_get03 object = new Field_get03(); + private static class TestClass { + public final byte byteField = 11; + public final short shortField = 12; + public final char charField = 13; + public final int intField = 14; + public final long longField = 15; + public final float floatField = 16; + public final double doubleField = 17; + public final boolean booleanField = true; + } - public final byte byteField = 11; - public final short shortField = 12; - public final char charField = 13; - public final int intField = 14; - public final long longField = 15; - public final float floatField = 16; - public final double doubleField = 17; - public final boolean booleanField = true; + private static final TestClass object = new TestClass(); public static boolean test(int arg) throws IllegalAccessException { if (arg == 0) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,34 +30,36 @@ */ public class Field_get04 extends JTTTest { - private static final Field_get04 object = new Field_get04(); + private static class TestClass { + public final byte byteField = 11; + public final short shortField = 12; + public final char charField = 13; + public final int intField = 14; + public final long longField = 15; + public final float floatField = 16; + public final double doubleField = 17; + public final boolean booleanField = true; + } - public final byte byteField = 11; - public final short shortField = 12; - public final char charField = 13; - public final int intField = 14; - public final long longField = 15; - public final float floatField = 16; - public final double doubleField = 17; - public final boolean booleanField = true; + private static final TestClass object = new TestClass(); public static boolean test(int arg) throws NoSuchFieldException, IllegalAccessException { if (arg == 0) { - return Field_get04.class.getField("byteField").getByte(object) == object.byteField; + return TestClass.class.getField("byteField").getByte(object) == object.byteField; } else if (arg == 1) { - return Field_get04.class.getField("shortField").getShort(object) == object.shortField; + return TestClass.class.getField("shortField").getShort(object) == object.shortField; } else if (arg == 2) { - return Field_get04.class.getField("charField").getChar(object) == object.charField; + return TestClass.class.getField("charField").getChar(object) == object.charField; } else if (arg == 3) { - return Field_get04.class.getField("intField").getInt(object) == object.intField; + return TestClass.class.getField("intField").getInt(object) == object.intField; } else if (arg == 4) { - return Field_get04.class.getField("longField").getLong(object) == object.longField; + return TestClass.class.getField("longField").getLong(object) == object.longField; } else if (arg == 5) { - return Field_get04.class.getField("floatField").getFloat(object) == object.floatField; + return TestClass.class.getField("floatField").getFloat(object) == object.floatField; } else if (arg == 6) { - return Field_get04.class.getField("doubleField").getDouble(object) == object.doubleField; + return TestClass.class.getField("doubleField").getDouble(object) == object.doubleField; } else if (arg == 7) { - return Field_get04.class.getField("booleanField").getBoolean(object) == object.booleanField; + return TestClass.class.getField("booleanField").getBoolean(object) == object.booleanField; } return false; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,41 +30,43 @@ */ public class Field_set02 extends JTTTest { - private static final Field_set02 object = new Field_set02(); + private static class TestClass { + public byte byteField; + public short shortField; + public char charField; + public int intField; + public long longField; + public float floatField; + public double doubleField; + public boolean booleanField; + } - public byte byteField; - public short shortField; - public char charField; - public int intField; - public long longField; - public float floatField; - public double doubleField; - public boolean booleanField; + private static final TestClass object = new TestClass(); public static boolean test(int arg) throws NoSuchFieldException, IllegalAccessException { if (arg == 0) { - Field_set02.class.getField("byteField").set(object, Byte.valueOf((byte) 11)); + TestClass.class.getField("byteField").set(object, Byte.valueOf((byte) 11)); return object.byteField == 11; } else if (arg == 1) { - Field_set02.class.getField("shortField").set(object, Short.valueOf((short) 12)); + TestClass.class.getField("shortField").set(object, Short.valueOf((short) 12)); return object.shortField == 12; } else if (arg == 2) { - Field_set02.class.getField("charField").set(object, Character.valueOf((char) 13)); + TestClass.class.getField("charField").set(object, Character.valueOf((char) 13)); return object.charField == 13; } else if (arg == 3) { - Field_set02.class.getField("intField").set(object, Integer.valueOf(14)); + TestClass.class.getField("intField").set(object, Integer.valueOf(14)); return object.intField == 14; } else if (arg == 4) { - Field_set02.class.getField("longField").set(object, Long.valueOf(15L)); + TestClass.class.getField("longField").set(object, Long.valueOf(15L)); return object.longField == 15; } else if (arg == 5) { - Field_set02.class.getField("floatField").set(object, Float.valueOf(16)); + TestClass.class.getField("floatField").set(object, Float.valueOf(16)); return object.floatField == 16; } else if (arg == 6) { - Field_set02.class.getField("doubleField").set(object, Double.valueOf(17)); + TestClass.class.getField("doubleField").set(object, Double.valueOf(17)); return object.doubleField == 17; } else if (arg == 7) { - Field_set02.class.getField("booleanField").set(object, true); + TestClass.class.getField("booleanField").set(object, true); return object.booleanField == true; } return false; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,41 +30,43 @@ */ public class Field_set03 extends JTTTest { - private static final Field_set03 object = new Field_set03(); + private static class TestClass { + public byte byteField; + public short shortField; + public char charField; + public int intField; + public long longField; + public float floatField; + public double doubleField; + public boolean booleanField; + } - public byte byteField; - public short shortField; - public char charField; - public int intField; - public long longField; - public float floatField; - public double doubleField; - public boolean booleanField; + private static final TestClass object = new TestClass(); public static boolean test(int arg) throws NoSuchFieldException, IllegalAccessException { if (arg == 0) { - Field_set03.class.getField("byteField").setByte(object, (byte) 11); + TestClass.class.getField("byteField").setByte(object, (byte) 11); return object.byteField == 11; } else if (arg == 1) { - Field_set03.class.getField("shortField").setShort(object, (short) 12); + TestClass.class.getField("shortField").setShort(object, (short) 12); return object.shortField == 12; } else if (arg == 2) { - Field_set03.class.getField("charField").setChar(object, (char) 13); + TestClass.class.getField("charField").setChar(object, (char) 13); return object.charField == 13; } else if (arg == 3) { - Field_set03.class.getField("intField").setInt(object, 14); + TestClass.class.getField("intField").setInt(object, 14); return object.intField == 14; } else if (arg == 4) { - Field_set03.class.getField("longField").setLong(object, 15L); + TestClass.class.getField("longField").setLong(object, 15L); return object.longField == 15; } else if (arg == 5) { - Field_set03.class.getField("floatField").setFloat(object, 16); + TestClass.class.getField("floatField").setFloat(object, 16); return object.floatField == 16; } else if (arg == 6) { - Field_set03.class.getField("doubleField").setDouble(object, 17); + TestClass.class.getField("doubleField").setDouble(object, 17); return object.doubleField == 17; } else if (arg == 7) { - Field_set03.class.getField("booleanField").setBoolean(object, true); + TestClass.class.getField("booleanField").setBoolean(object, true); return object.booleanField == true; } return false; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,6 +32,12 @@ */ public class Invoke_except01 extends JTTTest { + public static class TestClass { + public static int method(int[] arg) { + return arg.length; + } + } + public static int test(int arg) throws IllegalAccessException, InvocationTargetException { Object[] args; if (arg == 0) { @@ -45,7 +51,7 @@ } else { args = null; } - for (Method m : Invoke_except01.class.getDeclaredMethods()) { + for (Method m : TestClass.class.getDeclaredMethods()) { if ("method".equals(m.getName())) { return (Integer) m.invoke(null, args); } @@ -53,10 +59,6 @@ return 42; } - public static int method(int[] arg) { - return arg.length; - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,19 +32,21 @@ */ public class Invoke_main01 extends JTTTest { + public static class TestClass { + public static void main(String[] args) { + field = args[0]; + } + } + static String field; public static String test(String input) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { field = null; final String[] args = {input}; - Invoke_main01.class.getMethod("main", String[].class).invoke(null, new Object[]{args}); + TestClass.class.getMethod("main", String[].class).invoke(null, new Object[]{args}); return field; } - public static void main(String[] args) { - field = args[0]; - } - @Test public void run0() throws Throwable { runTest("test", "test1"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main02.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,19 +32,21 @@ */ public class Invoke_main02 extends JTTTest { + public static class TestClass { + public static void main(String[] args) { + field = args[0]; + } + } + static String field; public static String test(String input) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { field = null; final String[] args = {input}; - Invoke_main02.class.getDeclaredMethod("main", String[].class).invoke(null, new Object[]{args}); + TestClass.class.getDeclaredMethod("main", String[].class).invoke(null, new Object[]{args}); return field; } - public static void main(String[] args) { - field = args[0]; - } - @Test public void run0() throws Throwable { runTest("test", "test1"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,12 +32,18 @@ */ public class Invoke_main03 extends JTTTest { + public static class TestClass { + public static void main(String[] args) { + field = args[0]; + } + } + static String field; public static String test(String input) throws IllegalAccessException, InvocationTargetException { field = null; final String[] args = {input}; - for (Method m : Invoke_main03.class.getDeclaredMethods()) { + for (Method m : TestClass.class.getDeclaredMethods()) { if ("main".equals(m.getName())) { m.invoke(null, new Object[]{args}); } @@ -45,10 +51,6 @@ return field; } - public static void main(String[] args) { - field = args[0]; - } - @Test public void run0() throws Throwable { runTest("test", "test1"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,17 +28,35 @@ import com.oracle.graal.jtt.*; -public final class Monitor_contended01 extends JTTTest implements Runnable { +public final class Monitor_contended01 extends JTTTest { + + private static class TestClass implements Runnable { + boolean started = false; + boolean acquired = false; + + public void run() { + // signal that we have started up so first thread will release lock + synchronized (cond) { + started = true; + cond.notifyAll(); + } + synchronized (obj) { + + } + // signal that we have successfully acquired and released the monitor + synchronized (cond) { + acquired = true; + cond.notifyAll(); + } + } + } static final Object cond = new Object(); static final Object obj = new Object(); - boolean started = false; - boolean acquired = false; - public static boolean test() throws InterruptedException { // test contention for monitor - final Monitor_contended01 object = new Monitor_contended01(); + final TestClass object = new TestClass(); synchronized (obj) { new Thread(object).start(); // wait for other thread to startup and contend @@ -56,22 +74,6 @@ return object.acquired; } - public void run() { - // signal that we have started up so first thread will release lock - synchronized (cond) { - started = true; - cond.notifyAll(); - } - synchronized (obj) { - - } - // signal that we have successfully acquired and released the monitor - synchronized (cond) { - acquired = true; - cond.notifyAll(); - } - } - @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,7 +28,19 @@ import com.oracle.graal.jtt.*; -public class Object_wait01 extends JTTTest implements Runnable { +public class Object_wait01 extends JTTTest { + + private static class TestClass implements Runnable { + public void run() { + int i = 0; + while (i++ < 1000000 && !done) { + synchronized (object) { + count++; + object.notifyAll(); + } + } + } + } static volatile int count = 0; static volatile boolean done; @@ -37,7 +49,7 @@ public static boolean test(int i) throws InterruptedException { count = 0; done = false; - new Thread(new Object_wait01()).start(); + new Thread(new TestClass()).start(); synchronized (object) { while (count < i) { object.wait(); @@ -45,17 +57,6 @@ done = true; return count >= i; } - - } - - public void run() { - int i = 0; - while (i++ < 1000000 && !done) { - synchronized (object) { - count++; - object.notifyAll(); - } - } } @Test(timeout = 20000) diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,7 +28,21 @@ import com.oracle.graal.jtt.*; -public class Object_wait02 extends JTTTest implements Runnable { +public class Object_wait02 extends JTTTest { + + private static class TestClass implements Runnable { + public void run() { + try { + Thread.sleep(sleep); + } catch (InterruptedException ex) { + + } + synchronized (object) { + done = true; + object.notifyAll(); + } + } + } static volatile boolean done; static final Object object = new Object(); @@ -37,7 +51,7 @@ public static boolean test(int i) throws InterruptedException { done = false; sleep = i * 200; - new Thread(new Object_wait02()).start(); + new Thread(new TestClass()).start(); synchronized (object) { while (!done) { object.wait(200); @@ -46,18 +60,6 @@ return done; } - public void run() { - try { - Thread.sleep(sleep); - } catch (InterruptedException ex) { - - } - synchronized (object) { - done = true; - object.notifyAll(); - } - } - @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,7 +28,21 @@ import com.oracle.graal.jtt.*; -public class Object_wait03 extends JTTTest implements Runnable { +public class Object_wait03 extends JTTTest { + + private static class TestClass implements Runnable { + public void run() { + try { + Thread.sleep(sleep); + } catch (InterruptedException ex) { + + } + synchronized (object) { + done = true; + object.notifyAll(); + } + } + } static volatile boolean done; static final Object object = new Object(); @@ -38,7 +52,7 @@ done = false; sleep = i * 200; synchronized (object) { - new Thread(new Object_wait03()).start(); + new Thread(new TestClass()).start(); dowait(); } return done; @@ -52,18 +66,6 @@ } } - public void run() { - try { - Thread.sleep(sleep); - } catch (InterruptedException ex) { - - } - synchronized (object) { - done = true; - object.notifyAll(); - } - } - @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,7 +28,21 @@ import com.oracle.graal.jtt.*; -public class Object_wait04 extends JTTTest implements Runnable { +public class Object_wait04 extends JTTTest { + + private static class TestClass implements Runnable { + public void run() { + try { + Thread.sleep(sleep); + } catch (InterruptedException ex) { + + } + synchronized (object) { + done = true; + object.notifyAll(); + } + } + } static volatile boolean done; static final Object object = new Object(); @@ -38,7 +52,7 @@ done = false; sleep = i * 50; synchronized (object) { - new Thread(new Object_wait04()).start(); + new Thread(new TestClass()).start(); dowait(i); } return done; @@ -56,18 +70,6 @@ } } - public void run() { - try { - Thread.sleep(sleep); - } catch (InterruptedException ex) { - - } - synchronized (object) { - done = true; - object.notifyAll(); - } - } - @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,22 +28,24 @@ import com.oracle.graal.jtt.*; -public class Thread_join01 extends JTTTest implements Runnable { +public class Thread_join01 extends JTTTest { + + private static class TestClass implements Runnable { + public void run() { + cont = false; + } + } static volatile boolean cont; public static boolean test() throws InterruptedException { cont = true; - final Thread thread = new Thread(new Thread_join01()); + final Thread thread = new Thread(new TestClass()); thread.start(); thread.join(); return cont; } - public void run() { - cont = false; - } - @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,26 +31,28 @@ import com.oracle.graal.jtt.*; -public class Thread_join02 extends JTTTest implements Runnable { +public class Thread_join02 extends JTTTest { + + private static class TestClass implements Runnable { + public void run() { + try { + Thread.sleep(200); + } catch (InterruptedException ex) { + } + cont = false; + } + } static volatile boolean cont; public static boolean test() throws InterruptedException { cont = true; - final Thread thread = new Thread(new Thread_join02()); + final Thread thread = new Thread(new TestClass()); thread.start(); thread.join(); return cont; } - public void run() { - try { - Thread.sleep(200); - } catch (InterruptedException ex) { - } - cont = false; - } - @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,23 +31,25 @@ import com.oracle.graal.jtt.*; -public class Thread_join03 extends JTTTest implements Runnable { +public class Thread_join03 extends JTTTest { + + private static class TestClass implements Runnable { + public void run() { + cont = false; + } + } static volatile boolean cont; public static boolean test() throws InterruptedException { cont = true; - final Thread thread = new Thread(new Thread_join03()); + final Thread thread = new Thread(new TestClass()); thread.start(); Thread.sleep(200); thread.join(); return cont; } - public void run() { - cont = false; - } - @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,9 +28,15 @@ import com.oracle.graal.jtt.*; -public class Thread_new02 extends JTTTest implements Runnable { +public class Thread_new02 extends JTTTest { - static final Thread_new02 thisObject = new Thread_new02(); + private static class TestClass implements Runnable { + public void run() { + // do nothing. + } + } + + static final TestClass thisObject = new TestClass(); public static boolean test(int i) { if (i == 0) { @@ -48,10 +54,6 @@ return false; } - public void run() { - // do nothing. - } - @Test public void run0() throws Throwable { runTest("test", 0); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -41,11 +41,11 @@ protected final Scale scale; protected final int displacement; - public AMD64AddressValue(PlatformKind kind, AllocatableValue base, int displacement) { + public AMD64AddressValue(LIRKind kind, AllocatableValue base, int displacement) { this(kind, base, Value.ILLEGAL, Scale.Times1, displacement); } - public AMD64AddressValue(PlatformKind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { + public AMD64AddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { super(kind); this.base = base; this.index = index; @@ -93,13 +93,13 @@ public boolean equals(Object obj) { if (obj instanceof AMD64AddressValue) { AMD64AddressValue addr = (AMD64AddressValue) obj; - return getPlatformKind() == addr.getPlatformKind() && displacement == addr.displacement && base.equals(addr.base) && scale == addr.scale && index.equals(addr.index); + return getLIRKind().equals(addr.getLIRKind()) && displacement == addr.displacement && base.equals(addr.base) && scale == addr.scale && index.equals(addr.index); } return false; } @Override public int hashCode() { - return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ (scale.value << 8) ^ getPlatformKind().hashCode(); + return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ (scale.value << 8) ^ getLIRKind().hashCode(); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -351,7 +351,7 @@ @Use({REG, STACK}) public AllocatableValue y; public MulHighOp(AMD64Arithmetic opcode, AllocatableValue y) { - PlatformKind kind = y.getPlatformKind(); + LIRKind kind = y.getLIRKind(); this.opcode = opcode; this.x = AMD64.rax.asValue(kind); @@ -411,8 +411,8 @@ public DivRemOp(AMD64Arithmetic opcode, AllocatableValue x, AllocatableValue y, LIRFrameState state) { this.opcode = opcode; - this.divResult = AMD64.rax.asValue(x.getPlatformKind()); - this.remResult = AMD64.rdx.asValue(x.getPlatformKind()); + this.divResult = AMD64.rax.asValue(x.getLIRKind()); + this.remResult = AMD64.rdx.asValue(x.getLIRKind()); this.x = x; this.y = y; this.state = state; @@ -446,7 +446,7 @@ public FPDivRemOp(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { this.opcode = opcode; this.result = result; - this.raxTemp = AMD64.rax.asValue(Kind.Int); + this.raxTemp = AMD64.rax.asValue(LIRKind.value(Kind.Int)); this.x = x; this.y = y; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -75,15 +75,15 @@ this.lengthValue = length; // Allocate some temporaries. - this.temp1 = tool.newVariable(tool.target().wordKind); - this.temp2 = tool.newVariable(tool.target().wordKind); - this.temp3 = tool.newVariable(tool.target().wordKind); - this.temp4 = tool.newVariable(tool.target().wordKind); + this.temp1 = tool.newVariable(LIRKind.derivedReference(tool.target().wordKind)); + this.temp2 = tool.newVariable(LIRKind.derivedReference(tool.target().wordKind)); + this.temp3 = tool.newVariable(LIRKind.value(tool.target().wordKind)); + this.temp4 = tool.newVariable(LIRKind.value(tool.target().wordKind)); // We only need the vector temporaries if we generate SSE code. if (supportsSSE41(tool.target())) { - this.vectorTemp1 = tool.newVariable(Kind.Double); - this.vectorTemp2 = tool.newVariable(Kind.Double); + this.vectorTemp1 = tool.newVariable(LIRKind.value(Kind.Double)); + this.vectorTemp2 = tool.newVariable(LIRKind.value(Kind.Double)); } else { this.vectorTemp1 = Value.ILLEGAL; this.vectorTemp2 = Value.ILLEGAL; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -141,7 +141,7 @@ * The register allocator does not support virtual registers that are used at the call * site, so use a fixed register. */ - callTemp = AMD64.rax.asValue(Kind.Long); + callTemp = AMD64.rax.asValue(LIRKind.value(Kind.Long)); assert ValueUtil.differentRegisters(parameters, callTemp); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -157,9 +157,8 @@ break; case Object: assert condition == Condition.EQ || condition == Condition.NE; - Register temp = asObjectReg(scratch); - AMD64Move.move(crb, masm, temp.asValue(Kind.Object), keyConstants[index]); - masm.cmpptr(keyRegister, temp); + AMD64Move.move(crb, masm, scratch, keyConstants[index]); + masm.cmpptr(keyRegister, asObjectReg(scratch)); break; default: throw new GraalInternalError("switch only supported for int, long and object"); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Mon Jun 30 12:02:19 2014 +0200 @@ -98,7 +98,7 @@ } @Override - protected StackSlot allocateNewSpillSlot(PlatformKind kind, int additionalOffset) { + protected StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset) { return StackSlot.get(kind, -spillSize + additionalOffset, true); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -55,7 +55,7 @@ } protected void restoreRegister(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, StackSlot input) { - RegisterValue result = register.asValue(input.getKind()); + RegisterValue result = register.asValue(input.getLIRKind()); AMD64Move.move(crb, masm, result, input); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -54,7 +54,7 @@ protected final boolean supportsRemove; /** - * + * * @param savedRegisters the registers saved by this operation which may be subject to * {@linkplain #remove(Set) pruning} * @param slots the slots to which the registers are saved @@ -67,7 +67,7 @@ } protected void saveRegister(CompilationResultBuilder crb, AMD64MacroAssembler masm, StackSlot result, Register register) { - RegisterValue input = register.asValue(result.getKind()); + RegisterValue input = register.asValue(result.getLIRKind()); AMD64Move.move(crb, masm, result, input); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -59,7 +59,7 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { for (int i = 0; i < zappedRegisters.length; i++) { if (zappedRegisters[i] != null) { - RegisterValue registerValue = zappedRegisters[i].asValue(zapValues[i].getPlatformKind()); + RegisterValue registerValue = zappedRegisters[i].asValue(zapValues[i].getLIRKind()); AMD64Move.move(crb, masm, registerValue, zapValues[i]); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILAddressValue.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILAddressValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILAddressValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -42,23 +42,23 @@ /** * Creates an {@link HSAILAddressValue} with given base register and no displacement. - * + * * @param kind the kind of the value being addressed * @param base the base register */ - public HSAILAddressValue(Kind kind, AllocatableValue base) { + public HSAILAddressValue(LIRKind kind, AllocatableValue base) { this(kind, base, 0); } /** * Creates an {@link HSAILAddressValue} with given base register and a displacement. This is the * most general constructor. - * + * * @param kind the kind of the value being addressed * @param base the base register * @param displacement the displacement */ - public HSAILAddressValue(Kind kind, AllocatableValue base, long displacement) { + public HSAILAddressValue(LIRKind kind, AllocatableValue base, long displacement) { super(kind); this.base = base; this.displacement = displacement; @@ -92,7 +92,7 @@ public boolean equals(Object obj) { if (obj instanceof HSAILAddressValue) { HSAILAddressValue addr = (HSAILAddressValue) obj; - return getKind() == addr.getKind() && displacement == addr.displacement && base.equals(addr.base); + return getLIRKind().equals(addr.getLIRKind()) && displacement == addr.displacement && base.equals(addr.base); } return false; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -177,8 +177,8 @@ masm.emitComment("/* HSAIL Deoptimization pos=" + codeBufferPos + ", bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */"); - AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); - AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); + AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(LIRKind.value(Kind.Int)); + AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(LIRKind.value(Kind.Int)); masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); masm.emitJumpToLabelName(masm.getDeoptLabelName()); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILFrameMap.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILFrameMap.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILFrameMap.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -28,9 +28,9 @@ /** * HSAIL specific frame map. - * + * * This is the format of a HSAIL stack frame: - * + * *
  * TODO stack frame layout
  * 
@@ -66,7 +66,7 @@ } @Override - protected StackSlot allocateNewSpillSlot(PlatformKind kind, int additionalOffset) { + protected StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset) { return StackSlot.get(kind, -spillSize + additionalOffset, true); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.hsail.*; /** * Implementation of move instructions. @@ -167,6 +168,25 @@ HSAILAddress addr = address.toAddress(); masm.emitLoad(kind, result, addr); } + + public boolean usesThreadRegister() { + return (address.toAddress().getBase().equals(HSAIL.threadRegister)); + } + } + + /** + * A LoadOp that uses the HSAIL ld_acq instruction + */ + public static class LoadAcquireOp extends LoadOp { + public LoadAcquireOp(Kind kind, AllocatableValue result, HSAILAddressValue address, LIRFrameState state) { + super(kind, result, address, state); + } + + @Override + public void emitMemAccess(HSAILAssembler masm) { + HSAILAddress addr = address.toAddress(); + masm.emitLoadAcquire(result, addr); + } } public static class StoreOp extends MemOp { @@ -186,6 +206,22 @@ } } + /** + * A StoreOp that uses the HSAIL st_rel instruction + */ + public static class StoreReleaseOp extends StoreOp { + public StoreReleaseOp(Kind kind, HSAILAddressValue address, AllocatableValue input, LIRFrameState state) { + super(kind, address, input, state); + } + + @Override + public void emitMemAccess(HSAILAssembler masm) { + assert isRegister(input); + HSAILAddress addr = address.toAddress(); + masm.emitStoreRelease(input, addr); + } + } + public static class StoreConstantOp extends MemOp { protected final Constant input; @@ -465,4 +501,18 @@ } } + public static class WorkItemAbsIdOp extends HSAILLIRInstruction { + + @Def({REG}) protected AllocatableValue result; + + public WorkItemAbsIdOp(AllocatableValue result) { + this.result = result; + } + + @Override + public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + masm.emitWorkItemAbsId(result); + } + } + } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -43,23 +43,23 @@ /** * Creates an {@link PTXAddressValue} with given base register and no displacement. - * + * * @param kind the kind of the value being addressed * @param base the base register */ - public PTXAddressValue(PlatformKind kind, AllocatableValue base) { + public PTXAddressValue(LIRKind kind, AllocatableValue base) { this(kind, base, 0); } /** * Creates an {@link PTXAddressValue} with given base register and a displacement. This is the * most general constructor. - * + * * @param kind the kind of the value being addressed * @param base the base register * @param displacement the displacement */ - public PTXAddressValue(PlatformKind kind, AllocatableValue base, long displacement) { + public PTXAddressValue(LIRKind kind, AllocatableValue base, long displacement) { super(kind); this.base = base; this.displacement = displacement; @@ -94,13 +94,13 @@ public boolean equals(Object obj) { if (obj instanceof PTXAddressValue) { PTXAddressValue addr = (PTXAddressValue) obj; - return getPlatformKind() == addr.getPlatformKind() && displacement == addr.displacement && base.equals(addr.base); + return getLIRKind().equals(addr.getLIRKind()) && displacement == addr.displacement && base.equals(addr.base); } return false; } @Override public int hashCode() { - return base.hashCode() ^ ((int) displacement << 4) ^ getPlatformKind().hashCode(); + return base.hashCode() ^ ((int) displacement << 4) ^ getLIRKind().hashCode(); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXFrameMap.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXFrameMap.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXFrameMap.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -28,9 +28,9 @@ /** * PTX specific frame map. - * + * * This is the format of a PTX stack frame: - * + * *
  * TODO stack frame layout
  * 
@@ -66,7 +66,7 @@ } @Override - protected StackSlot allocateNewSpillSlot(PlatformKind kind, int additionalOffset) { + protected StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset) { return StackSlot.get(kind, -spillSize + additionalOffset, true); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -39,11 +39,11 @@ @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue index; protected final int displacement; - public SPARCAddressValue(PlatformKind kind, AllocatableValue base, int displacement) { + public SPARCAddressValue(LIRKind kind, AllocatableValue base, int displacement) { this(kind, base, Value.ILLEGAL, displacement); } - public SPARCAddressValue(PlatformKind kind, AllocatableValue base, AllocatableValue index, int displacement) { + public SPARCAddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index, int displacement) { super(kind); assert isIllegal(index) || displacement == 0; this.base = base; @@ -94,13 +94,13 @@ public boolean equals(Object obj) { if (obj instanceof SPARCAddressValue) { SPARCAddressValue addr = (SPARCAddressValue) obj; - return getPlatformKind() == addr.getPlatformKind() && displacement == addr.displacement && base.equals(addr.base) && index.equals(addr.index); + return getLIRKind().equals(addr.getLIRKind()) && displacement == addr.displacement && base.equals(addr.base) && index.equals(addr.index); } return false; } @Override public int hashCode() { - return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ getPlatformKind().hashCode(); + return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ getLIRKind().hashCode(); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -251,8 +251,8 @@ this.result = result; this.x = x; this.y = y; - this.scratch1 = gen.newVariable(x.getKind()); - this.scratch2 = gen.newVariable(x.getKind()); + this.scratch1 = gen.newVariable(x.getLIRKind()); + this.scratch2 = gen.newVariable(x.getLIRKind()); this.state = state; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -62,7 +62,7 @@ this.result = result; this.input = input; if (opcode == IntrinsicOpcode.IBSR || opcode == IntrinsicOpcode.LBSR) { - scratch = gen.newVariable(input.getKind()); + scratch = gen.newVariable(input.getLIRKind()); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -192,16 +192,14 @@ emitCompare(masm, target, condition, CC.Icc); break; case Long: { - Register temp = asLongReg(scratch); - SPARCMove.move(crb, masm, temp.asValue(Kind.Long), keyConstants[index]); - new Cmp(keyRegister, temp).emit(masm); + SPARCMove.move(crb, masm, scratch, keyConstants[index]); + new Cmp(keyRegister, asLongReg(scratch)).emit(masm); emitCompare(masm, target, condition, CC.Xcc); break; } case Object: { - Register temp = asObjectReg(scratch); - SPARCMove.move(crb, masm, temp.asValue(Kind.Object), keyConstants[index]); - new Cmp(keyRegister, temp).emit(masm); + SPARCMove.move(crb, masm, scratch, keyConstants[index]); + new Cmp(keyRegister, asObjectReg(scratch)).emit(masm); emitCompare(masm, target, condition, CC.Ptrcc); break; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -34,7 +34,7 @@ * *
  *   Base       Contents
- * 
+ *
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -98,7 +98,7 @@
     }
 
     @Override
-    protected StackSlot allocateNewSpillSlot(PlatformKind kind, int additionalOffset) {
+    protected StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset) {
         return StackSlot.get(kind, -spillSize + additionalOffset, true);
     }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Mon Jun 30 12:02:19 2014 +0200
@@ -67,7 +67,7 @@
     }
 
     private static void saveRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, StackSlot result, Register register) {
-        RegisterValue input = register.asValue(result.getKind());
+        RegisterValue input = register.asValue(result.getLIRKind());
         SPARCMove.move(crb, masm, result, input);
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -26,9 +26,9 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 /**
  * Base class to represent values that need to be stored in more than one register.
@@ -48,14 +48,14 @@
 
     private static final DebugMetric COMPOSITE_VALUE_COUNT = Debug.metric("CompositeValues");
 
-    public CompositeValue(PlatformKind kind) {
+    public CompositeValue(LIRKind kind) {
         super(kind);
         COMPOSITE_VALUE_COUNT.increment();
         valueClass = CompositeValueClass.get(getClass());
     }
 
-    public final void forEachComponent(OperandMode mode, ValueProcedure proc) {
-        valueClass.forEachComponent(this, mode, proc);
+    public final void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
+        valueClass.forEachComponent(inst, this, mode, proc);
     }
 
     @Override
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Jun 30 12:02:19 2014 +0200
@@ -27,9 +27,9 @@
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.CompositeValue.Component;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 /**
  * Lazily associated metadata for every {@link CompositeValue} type. The metadata includes:
@@ -139,8 +139,8 @@
         return str.toString();
     }
 
-    public final void forEachComponent(CompositeValue obj, OperandMode mode, ValueProcedure proc) {
-        forEach(obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
+    public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) {
+        forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
     }
 
     public String toString(CompositeValue obj) {
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -259,17 +259,17 @@
      * @param additionalOffset
      * @return A spill slot denoting the reserved memory area.
      */
-    protected abstract StackSlot allocateNewSpillSlot(PlatformKind kind, int additionalOffset);
+    protected abstract StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset);
 
     /**
-     * Returns the spill slot size for the given {@link PlatformKind}. The default value is the size
-     * in bytes for the target architecture.
+     * Returns the spill slot size for the given {@link LIRKind}. The default value is the size in
+     * bytes for the target architecture.
      *
-     * @param kind the {@link PlatformKind} to be stored in the spill slot.
+     * @param kind the {@link LIRKind} to be stored in the spill slot.
      * @return the size in bytes
      */
-    public int spillSlotSize(PlatformKind kind) {
-        return target.getSizeInBytes(kind);
+    public int spillSlotSize(LIRKind kind) {
+        return target.getSizeInBytes(kind.getPlatformKind());
     }
 
     /**
@@ -280,12 +280,12 @@
      * @param kind The kind of the spill slot to be reserved.
      * @return A spill slot denoting the reserved memory area.
      */
-    public StackSlot allocateSpillSlot(PlatformKind kind) {
+    public StackSlot allocateSpillSlot(LIRKind kind) {
         assert frameSize == -1 : "frame size must not yet be fixed";
         if (freedSlots != null) {
             for (Iterator iter = freedSlots.iterator(); iter.hasNext();) {
                 StackSlot s = iter.next();
-                if (s.getPlatformKind() == kind) {
+                if (s.getLIRKind().equals(kind)) {
                     iter.remove();
                     if (freedSlots.isEmpty()) {
                         freedSlots = null;
@@ -302,8 +302,8 @@
     private Set freedSlots;
 
     /**
-     * Frees a spill slot that was obtained via {@link #allocateSpillSlot(PlatformKind)} such that
-     * it can be reused for the next allocation request for the same kind of slot.
+     * Frees a spill slot that was obtained via {@link #allocateSpillSlot(LIRKind)} such that it can
+     * be reused for the next allocation request for the same kind of slot.
      */
     public void freeSpillSlot(StackSlot slot) {
         if (freedSlots == null) {
@@ -338,7 +338,7 @@
             for (int slotIndex = 0; slotIndex < slots; slotIndex++) {
                 StackSlot objectSlot = null;
                 if (objects.get(slotIndex)) {
-                    objectSlot = allocateNewSpillSlot(Kind.Object, slotIndex * stackSlotSize());
+                    objectSlot = allocateNewSpillSlot(LIRKind.reference(Kind.Object), slotIndex * stackSlotSize());
                     objectStackSlots.add(objectSlot);
                     if (outObjectStackSlots != null) {
                         outObjectStackSlots.add(objectSlot);
@@ -348,7 +348,7 @@
                     if (objectSlot != null) {
                         result = objectSlot;
                     } else {
-                        result = allocateNewSpillSlot(target.wordKind, 0);
+                        result = allocateNewSpillSlot(LIRKind.value(target.wordKind), 0);
                     }
                 }
             }
@@ -356,7 +356,7 @@
             return result;
 
         } else {
-            return allocateNewSpillSlot(target.wordKind, 0);
+            return allocateNewSpillSlot(LIRKind.value(target.wordKind), 0);
         }
     }
 
@@ -377,9 +377,9 @@
      * @param refMap A reference map, as created by {@link #initReferenceMap(boolean)}.
      */
     public void setReference(Value location, ReferenceMap refMap) {
-        PlatformKind kind = location.getPlatformKind();
+        LIRKind kind = location.getLIRKind();
         if (isRegister(location)) {
-            refMap.setRegister(asRegister(location).number, kind);
+            refMap.setRegister(asRegister(location).getReferenceMapIndex(), kind);
         } else if (isStackSlot(location)) {
             int offset = offsetForStackSlot(asStackSlot(location));
             refMap.setStackSlot(offset, kind);
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Mon Jun 30 12:02:19 2014 +0200
@@ -28,9 +28,9 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 /**
  * This class represents garbage collection and deoptimization information attached to a LIR
@@ -59,17 +59,17 @@
     }
 
     /**
-     * Iterates the frame state and calls the {@link ValueProcedure} for every variable.
-     * 
+     * Iterates the frame state and calls the {@link InstructionValueProcedure} for every variable.
+     *
      * @param proc The procedure called for variables.
      */
-    public void forEachState(ValueProcedure proc) {
+    public void forEachState(LIRInstruction inst, InstructionValueProcedure proc) {
         for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) {
-            processValues(cur.values, proc);
+            processValues(inst, cur.values, proc);
         }
         if (virtualObjects != null) {
             for (VirtualObject obj : virtualObjects) {
-                processValues(obj.getValues(), proc);
+                processValues(inst, obj.getValues(), proc);
             }
         }
     }
@@ -80,16 +80,16 @@
      */
     protected static final EnumSet STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
 
-    protected void processValues(Value[] values, ValueProcedure proc) {
+    protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedure proc) {
         for (int i = 0; i < values.length; i++) {
             Value value = values[i];
-            values[i] = processValue(proc, value);
+            values[i] = processValue(inst, proc, value);
         }
     }
 
-    protected Value processValue(ValueProcedure proc, Value value) {
+    protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) {
         if (processed(value)) {
-            return proc.doValue(value, OperandMode.ALIVE, STATE_FLAGS);
+            return proc.doValue(inst, value, OperandMode.ALIVE, STATE_FLAGS);
         }
         return value;
     }
@@ -111,7 +111,7 @@
 
     /**
      * Called by the register allocator before {@link #markLocation} to initialize the frame state.
-     * 
+     *
      * @param frameMap The frame map.
      * @param canHaveRegisters True if there can be any register map entries.
      */
@@ -123,7 +123,7 @@
      * Called by the register allocator to mark the specified location as a reference in the
      * reference map of the debug information. The tracked location can be a {@link RegisterValue}
      * or a {@link StackSlot}. Note that a {@link Constant} is automatically tracked.
-     * 
+     *
      * @param location The location to be added to the reference map.
      * @param frameMap The frame map.
      */
@@ -133,7 +133,7 @@
 
     /**
      * Called by the register allocator after all locations are marked.
-     * 
+     *
      * @param op The instruction to which this frame state belongs.
      * @param frameMap The frame map.
      */
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Jun 30 12:02:19 2014 +0200
@@ -46,12 +46,44 @@
      * methods. Clients of the class must only call the doValue method that takes additional
      * parameters.
      */
-    public abstract static class ValueProcedure {
+    public abstract static class InstructionValueProcedure {
 
         /**
          * Iterator method to be overwritten. This version of the iterator does not take additional
          * parameters to keep the signature short.
-         * 
+         *
+         * @param instruction The current instruction.
+         * @param value The value that is iterated.
+         * @return The new value to replace the value that was passed in.
+         */
+        protected Value doValue(LIRInstruction instruction, Value value) {
+            throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
+        }
+
+        /**
+         * Iterator method to be overwritten. This version of the iterator gets additional
+         * parameters about the processed value.
+         *
+         * @param instruction The current instruction.
+         * @param value The value that is iterated.
+         * @param mode The operand mode for the value.
+         * @param flags A set of flags for the value.
+         * @return The new value to replace the value that was passed in.
+         */
+        public Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) {
+            return doValue(instruction, value);
+        }
+    }
+
+    /**
+     * Similar to {@link InstructionValueProcedure} but without an {@link LIRInstruction} parameter.
+     */
+    public abstract static class ValueProcedure extends InstructionValueProcedure {
+
+        /**
+         * Iterator method to be overwritten. This version of the iterator does not take additional
+         * parameters to keep the signature short.
+         *
          * @param value The value that is iterated.
          * @return The new value to replace the value that was passed in.
          */
@@ -62,15 +94,25 @@
         /**
          * Iterator method to be overwritten. This version of the iterator gets additional
          * parameters about the processed value.
-         * 
+         *
          * @param value The value that is iterated.
          * @param mode The operand mode for the value.
          * @param flags A set of flags for the value.
          * @return The new value to replace the value that was passed in.
          */
-        public Value doValue(Value value, OperandMode mode, EnumSet flags) {
+        protected Value doValue(Value value, OperandMode mode, EnumSet flags) {
             return doValue(value);
         }
+
+        @Override
+        final protected Value doValue(LIRInstruction instruction, Value value) {
+            throw GraalInternalError.shouldNotReachHere("This doValue() methods should never be called");
+        }
+
+        @Override
+        final public Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) {
+            return doValue(value, mode, flags);
+        }
     }
 
     public abstract static class StateProcedure {
@@ -255,23 +297,23 @@
         return false;
     }
 
-    public final void forEachInput(ValueProcedure proc) {
+    public final void forEachInput(InstructionValueProcedure proc) {
         instructionClass.forEachUse(this, proc);
     }
 
-    public final void forEachAlive(ValueProcedure proc) {
+    public final void forEachAlive(InstructionValueProcedure proc) {
         instructionClass.forEachAlive(this, proc);
     }
 
-    public final void forEachTemp(ValueProcedure proc) {
+    public final void forEachTemp(InstructionValueProcedure proc) {
         instructionClass.forEachTemp(this, proc);
     }
 
-    public final void forEachOutput(ValueProcedure proc) {
+    public final void forEachOutput(InstructionValueProcedure proc) {
         instructionClass.forEachDef(this, proc);
     }
 
-    public final void forEachState(ValueProcedure proc) {
+    public final void forEachState(InstructionValueProcedure proc) {
         instructionClass.forEachState(this, proc);
     }
 
@@ -286,7 +328,7 @@
      * Subclasses can override this method. The default implementation processes all Input operands
      * as the hints for an Output operand, and all Output operands as the hints for an Input
      * operand.
-     * 
+     *
      * @param value The value the hints are needed for.
      * @param mode The operand mode of the value.
      * @param proc The procedure invoked for all the hints. If the procedure returns a non-null
@@ -294,7 +336,7 @@
      *            clients can stop the iteration once a suitable hint has been found.
      * @return The non-null value returned by the procedure, or null.
      */
-    public Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) {
+    public Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc) {
         return instructionClass.forEachRegisterHint(this, mode, proc);
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Jun 30 12:02:19 2014 +0200
@@ -28,10 +28,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 public class LIRInstructionClass extends LIRIntrospection {
 
@@ -262,27 +262,27 @@
         return false;
     }
 
-    public final void forEachUse(LIRInstruction obj, ValueProcedure proc) {
-        forEach(obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
+    public final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
     }
 
-    public final void forEachAlive(LIRInstruction obj, ValueProcedure proc) {
-        forEach(obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc);
+    public final void forEachAlive(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc);
     }
 
-    public final void forEachTemp(LIRInstruction obj, ValueProcedure proc) {
-        forEach(obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc);
+    public final void forEachTemp(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc);
     }
 
-    public final void forEachDef(LIRInstruction obj, ValueProcedure proc) {
-        forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
+    public final void forEachDef(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
     }
 
-    public final void forEachState(LIRInstruction obj, ValueProcedure proc) {
+    public final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) {
         for (int i = 0; i < stateOffsets.length; i++) {
             LIRFrameState state = getState(obj, stateOffsets[i]);
             if (state != null) {
-                state.forEachState(proc);
+                state.forEachState(obj, proc);
             }
         }
     }
@@ -296,7 +296,7 @@
         }
     }
 
-    public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) {
+    public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) {
         int hintDirectCount = 0;
         long[] hintOffsets = null;
         if (mode == OperandMode.USE) {
@@ -312,7 +312,7 @@
         for (int i = 0; i < hintOffsets.length; i++) {
             if (i < hintDirectCount) {
                 Value hintValue = getValue(obj, hintOffsets[i]);
-                Value result = proc.doValue(hintValue, null, null);
+                Value result = proc.doValue(obj, hintValue, null, null);
                 if (result != null) {
                     return result;
                 }
@@ -320,7 +320,7 @@
                 Value[] hintValues = getValueArray(obj, hintOffsets[i]);
                 for (int j = 0; j < hintValues.length; j++) {
                     Value hintValue = hintValues[j];
-                    Value result = proc.doValue(hintValue, null, null);
+                    Value result = proc.doValue(obj, hintValue, null, null);
                     if (result != null) {
                         return result;
                     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Jun 30 12:02:19 2014 +0200
@@ -32,9 +32,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 abstract class LIRIntrospection extends FieldIntrospection {
 
@@ -119,7 +119,7 @@
         }
     }
 
-    protected static void forEach(Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, ValueProcedure proc) {
+    protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, InstructionValueProcedure proc) {
         for (int i = 0; i < offsets.length; i++) {
             assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
 
@@ -127,9 +127,9 @@
                 Value value = getValue(obj, offsets[i]);
                 if (value instanceof CompositeValue) {
                     CompositeValue composite = (CompositeValue) value;
-                    composite.forEachComponent(mode, proc);
+                    composite.forEachComponent(inst, mode, proc);
                 } else {
-                    setValue(obj, offsets[i], proc.doValue(value, mode, flags[i]));
+                    setValue(obj, offsets[i], proc.doValue(inst, value, mode, flags[i]));
                 }
             } else {
                 Value[] values = getValueArray(obj, offsets[i]);
@@ -137,9 +137,9 @@
                     Value value = values[j];
                     if (value instanceof CompositeValue) {
                         CompositeValue composite = (CompositeValue) value;
-                        composite.forEachComponent(mode, proc);
+                        composite.forEachComponent(inst, mode, proc);
                     } else {
-                        values[j] = proc.doValue(value, mode, flags[i]);
+                        values[j] = proc.doValue(inst, value, mode, flags[i]);
                     }
                 }
             }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Mon Jun 30 12:02:19 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
@@ -62,14 +63,15 @@
         return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable();
     }
 
-    public static boolean verify(final LIRInstruction op) {
-        ValueProcedure allowedProc = new ValueProcedure() {
+    private static InstructionValueProcedure allowedProc = new InstructionValueProcedure() {
 
-            @Override
-            public Value doValue(Value value, OperandMode mode, EnumSet flags) {
-                return allowed(op, value, mode, flags);
-            }
-        };
+        @Override
+        public Value doValue(LIRInstruction op, Value value, OperandMode mode, EnumSet flags) {
+            return allowed(op, value, mode, flags);
+        }
+    };
+
+    public static boolean verify(final LIRInstruction op) {
 
         op.forEachInput(allowedProc);
         op.forEachAlive(allowedProc);
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -340,7 +340,7 @@
                 int sourceIdx = getStateIdx(moveOp.getInput());
                 int destIdx = getStateIdx(moveOp.getResult());
                 if (sourceIdx >= 0 && destIdx >= 0) {
-                    assert isObjectValue(state[sourceIdx]) || (moveOp.getInput().getKind() != Kind.Object) : "move op moves object but input is not defined as object";
+                    assert isObjectValue(state[sourceIdx]) || moveOp.getInput().getLIRKind().isValue() : "move op moves object but input is not defined as object";
                     state[destIdx] = state[sourceIdx];
                     Debug.log("move value %d from %d to %d", state[sourceIdx], sourceIdx, destIdx);
                     return initValueNum;
@@ -378,7 +378,7 @@
                         /*
                          * Assign a unique number to the output or temp location.
                          */
-                        state[stateIdx] = encodeValueNum(opValueNum++, operand.getKind() == Kind.Object);
+                        state[stateIdx] = encodeValueNum(opValueNum++, !operand.getLIRKind().isValue());
                         Debug.log("set def %d for register %s(%d): %d", opValueNum, operand, stateIdx, state[stateIdx]);
                     }
                     return operand;
@@ -510,7 +510,7 @@
             /*
              * Moves with mismatching kinds are not moves, but memory loads/stores!
              */
-            return source.getKind() == dest.getKind() && source.getPlatformKind() == dest.getPlatformKind() && source.getKind() != Kind.Illegal;
+            return source.getLIRKind().equals(dest.getLIRKind());
         }
         return false;
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, 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
@@ -42,11 +42,11 @@
 
     /**
      * Creates a new variable.
-     * 
+     *
      * @param kind
      * @param index
      */
-    public Variable(PlatformKind kind, int index) {
+    public Variable(LIRKind kind, int index) {
         super(kind);
         assert index >= 0;
         this.index = index;
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -32,7 +32,7 @@
  */
 public interface ArithmeticLIRGenerator {
 
-    PlatformKind getPlatformKind(Stamp stamp);
+    LIRKind getLIRKind(Stamp stamp);
 
     Value emitNegate(Value input);
 
@@ -70,7 +70,7 @@
 
     Value emitFloatConvert(FloatConvert op, Value inputVal);
 
-    Value emitReinterpret(PlatformKind to, Value inputVal);
+    Value emitReinterpret(LIRKind to, Value inputVal);
 
     Value emitNarrow(Value inputVal, int bits);
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -23,9 +23,6 @@
 package com.oracle.graal.lir.gen;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.api.meta.Value.*;
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-import static com.oracle.graal.lir.LIR.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
 
 import java.util.*;
@@ -42,13 +39,12 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.StandardOp.LabelOp;
-import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.options.*;
 
 /**
  * This class traverses the HIR instructions and generates LIR instructions from them.
  */
-public abstract class LIRGenerator implements LIRGeneratorTool, PlatformKindTool {
+public abstract class LIRGenerator implements LIRGeneratorTool, LIRKindTool {
 
     public static class Options {
         // @formatter:off
@@ -64,97 +60,6 @@
 
     private AbstractBlock currentBlock;
 
-    /**
-     * Handle for an operation that loads a constant into a variable. The operation starts in the
-     * first block where the constant is used but will eventually be
-     * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the
-     * constant.
-     */
-    public static class LoadConstant implements Comparable {
-        /**
-         * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is
-         * to be moved to a dominator block.
-         */
-        int index;
-
-        /**
-         * The operation that loads the constant.
-         */
-        private final LIRInstruction op;
-
-        /**
-         * The block that does or will contain {@link #op}. This is initially the block where the
-         * first usage of the constant is seen during LIR generation.
-         */
-        AbstractBlock block;
-
-        /**
-         * The variable into which the constant is loaded.
-         */
-        final Variable variable;
-
-        public LoadConstant(Variable variable, AbstractBlock block, int index, LIRInstruction op) {
-            this.variable = variable;
-            this.block = block;
-            this.index = index;
-            this.op = op;
-        }
-
-        /**
-         * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to
-         * group loads per block in {@link LIRGenerator#insertConstantLoads()}.
-         */
-        public int compareTo(LoadConstant o) {
-            if (block.getId() < o.block.getId()) {
-                return -1;
-            }
-            if (block.getId() > o.block.getId()) {
-                return 1;
-            }
-            return 0;
-        }
-
-        @Override
-        public String toString() {
-            return block + "#" + op;
-        }
-
-        /**
-         * Removes the {@link #op} from its original location if it is still at that location.
-         */
-        public void unpin(LIR lir) {
-            if (index >= 0) {
-                // Replace the move with a filler op so that the operation
-                // list does not need to be adjusted.
-                List instructions = lir.getLIRforBlock(block);
-                instructions.set(index, new NoOp(null, -1));
-                index = -1;
-            }
-        }
-
-        public AbstractBlock getBlock() {
-            return block;
-        }
-
-        public void setBlock(AbstractBlock block) {
-            this.block = block;
-        }
-
-        public Variable getVariable() {
-            return variable;
-        }
-
-        public int getIndex() {
-            return index;
-        }
-
-        public void setIndex(int index) {
-            this.index = index;
-        }
-    }
-
-    private Map constantLoads;
-
     private LIRGenerationResult res;
 
     public LIRGenerator(CodeGenProviders providers, CallingConvention cc, LIRGenerationResult res) {
@@ -198,12 +103,12 @@
     /**
      * Creates a new {@linkplain Variable variable}.
      *
-     * @param platformKind The kind of the new variable.
+     * @param lirKind The kind of the new variable.
      * @return a new variable
      */
     @Override
-    public Variable newVariable(PlatformKind platformKind) {
-        return new Variable(platformKind, res.getLIR().nextVariable());
+    public Variable newVariable(LIRKind lirKind) {
+        return new Variable(lirKind, res.getLIR().nextVariable());
     }
 
     @Override
@@ -250,11 +155,8 @@
      * @return the operand representing the ABI defined location used return a value of kind
      *         {@code kind}
      */
-    public AllocatableValue resultOperandFor(Kind kind) {
-        if (kind == Kind.Void) {
-            return ILLEGAL;
-        }
-        return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind);
+    public AllocatableValue resultOperandFor(LIRKind kind) {
+        return res.getFrameMap().registerConfig.getReturnRegister((Kind) kind.getPlatformKind()).asValue(kind);
     }
 
     public void append(LIRInstruction op) {
@@ -328,10 +230,11 @@
         if (value.getKind().getStackKind() != value.getKind()) {
             // We only have stack-kinds in the LIR, so convert the operand kind for values from the
             // calling convention.
+            LIRKind stackKind = value.getLIRKind().changeType(value.getKind().getStackKind());
             if (isRegister(value)) {
-                return asRegister(value).asValue(value.getKind().getStackKind());
+                return asRegister(value).asValue(stackKind);
             } else if (isStackSlot(value)) {
-                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
+                return StackSlot.get(stackKind, asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
@@ -409,83 +312,6 @@
 
     @Override
     public void beforeRegisterAllocation() {
-        insertConstantLoads();
-    }
-
-    /**
-     * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages
-     * of the constant. Any operations inserted into a block are guaranteed to be immediately prior
-     * to the first control flow instruction near the end of the block.
-     */
-    private void insertConstantLoads() {
-        if (constantLoads != null) {
-            // Remove loads where all usages are in the same block.
-            for (Iterator> iter = constantLoads.entrySet().iterator(); iter.hasNext();) {
-                LoadConstant lc = iter.next().getValue();
-
-                // Move loads of constant outside of loops
-                if (OptScheduleOutOfLoops.getValue()) {
-                    AbstractBlock outOfLoopDominator = lc.block;
-                    while (outOfLoopDominator.getLoop() != null) {
-                        outOfLoopDominator = outOfLoopDominator.getDominator();
-                    }
-                    if (outOfLoopDominator != lc.block) {
-                        lc.unpin(res.getLIR());
-                        lc.block = outOfLoopDominator;
-                    }
-                }
-
-                if (lc.index != -1) {
-                    assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op;
-                    iter.remove();
-                }
-            }
-            if (constantLoads.isEmpty()) {
-                return;
-            }
-
-            // Sorting groups the loads per block.
-            LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]);
-            Arrays.sort(groupedByBlock);
-
-            int groupBegin = 0;
-            while (true) {
-                int groupEnd = groupBegin + 1;
-                AbstractBlock block = groupedByBlock[groupBegin].block;
-                while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) {
-                    groupEnd++;
-                }
-                int groupSize = groupEnd - groupBegin;
-
-                List ops = res.getLIR().getLIRforBlock(block);
-                int lastIndex = ops.size() - 1;
-                assert ops.get(lastIndex) instanceof BlockEndOp;
-                int insertionIndex = lastIndex;
-                for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) {
-                    if (getExceptionEdge(ops.get(i)) != null) {
-                        insertionIndex = i;
-                        break;
-                    }
-                }
-
-                if (groupSize == 1) {
-                    ops.add(insertionIndex, groupedByBlock[groupBegin].op);
-                } else {
-                    assert groupSize > 1;
-                    List moves = new ArrayList<>(groupSize);
-                    for (int i = groupBegin; i < groupEnd; i++) {
-                        moves.add(groupedByBlock[i].op);
-                    }
-                    ops.addAll(insertionIndex, moves);
-                }
-
-                if (groupEnd == groupedByBlock.length) {
-                    break;
-                }
-                groupBegin = groupEnd;
-            }
-            constantLoads = null;
-        }
     }
 
     /**
@@ -520,47 +346,47 @@
     /**
      * Default implementation: Return the Java stack kind for each stamp.
      */
-    public PlatformKind getPlatformKind(Stamp stamp) {
-        return stamp.getPlatformKind(this);
+    public LIRKind getLIRKind(Stamp stamp) {
+        return stamp.getLIRKind(this);
     }
 
-    public PlatformKind getIntegerKind(int bits) {
+    public LIRKind getIntegerKind(int bits) {
         if (bits <= 8) {
-            return Kind.Byte;
+            return LIRKind.value(Kind.Byte);
         } else if (bits <= 16) {
-            return Kind.Short;
+            return LIRKind.value(Kind.Short);
         } else if (bits <= 32) {
-            return Kind.Int;
+            return LIRKind.value(Kind.Int);
         } else {
             assert bits <= 64;
-            return Kind.Long;
+            return LIRKind.value(Kind.Long);
         }
     }
 
-    public PlatformKind getFloatingKind(int bits) {
+    public LIRKind getFloatingKind(int bits) {
         switch (bits) {
             case 32:
-                return Kind.Float;
+                return LIRKind.value(Kind.Float);
             case 64:
-                return Kind.Double;
+                return LIRKind.value(Kind.Double);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
 
-    public PlatformKind getObjectKind() {
-        return Kind.Object;
+    public LIRKind getObjectKind() {
+        return LIRKind.reference(Kind.Object);
     }
 
-    public abstract void emitBitCount(Variable result, Value operand);
-
-    public abstract void emitBitScanForward(Variable result, Value operand);
-
-    public abstract void emitBitScanReverse(Variable result, Value operand);
-
-    public abstract void emitByteSwap(Variable result, Value operand);
-
-    public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+    protected LIRKind getAddressKind(Value base, long displacement, Value index) {
+        if (base.getLIRKind().isValue() && (index.equals(Value.ILLEGAL) || index.getLIRKind().isValue())) {
+            return LIRKind.value(target().wordKind);
+        } else if (base.getLIRKind().isReference(0) && displacement == 0L && index.equals(Value.ILLEGAL)) {
+            return LIRKind.reference(target().wordKind);
+        } else {
+            return LIRKind.derivedReference(target().wordKind);
+        }
+    }
 
     public AbstractBlock getCurrentBlock() {
         return currentBlock;
@@ -573,12 +399,4 @@
     public LIRGenerationResult getResult() {
         return res;
     }
-
-    public Map getConstantLoads() {
-        return constantLoads;
-    }
-
-    public void setConstantLoads(Map constantLoads) {
-        this.constantLoads = constantLoads;
-    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, 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
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.lir.gen;
 
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
@@ -31,7 +29,6 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.common.spi.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.gen.LIRGenerator.*;
 
 public interface LIRGeneratorTool extends ArithmeticLIRGenerator {
 
@@ -55,13 +52,9 @@
 
     void doBlockEnd(AbstractBlock block);
 
-    Map getConstantLoads();
-
-    void setConstantLoads(Map constantLoads);
+    Value emitLoad(LIRKind kind, Value address, LIRFrameState state);
 
-    Value emitLoad(PlatformKind kind, Value address, LIRFrameState state);
-
-    void emitStore(PlatformKind kind, Value address, Value input, LIRFrameState state);
+    void emitStore(LIRKind kind, Value address, Value input, LIRFrameState state);
 
     void emitNullCheck(Value address, LIRFrameState state);
 
@@ -113,7 +106,7 @@
 
     RegisterAttributes attributes(Register register);
 
-    Variable newVariable(PlatformKind kind);
+    Variable newVariable(LIRKind kind);
 
     Variable emitMove(Value input);
 
@@ -173,7 +166,7 @@
      * @return the operand representing the ABI defined location used return a value of kind
      *         {@code kind}
      */
-    AllocatableValue resultOperandFor(Kind kind);
+    AllocatableValue resultOperandFor(LIRKind kind);
 
     void append(LIRInstruction op);
 
@@ -196,14 +189,14 @@
 
     CallingConvention getCallingConvention();
 
-    void emitBitCount(Variable result, Value operand);
+    Value emitBitCount(Value operand);
 
-    void emitBitScanForward(Variable result, Value operand);
+    Value emitBitScanForward(Value operand);
 
-    void emitBitScanReverse(Variable result, Value operand);
+    Value emitBitScanReverse(Value operand);
 
-    void emitByteSwap(Variable result, Value operand);
+    Value emitByteSwap(Value operand);
 
-    void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+    Value emitArrayEquals(Kind kind, Value array1, Value array2, Value length);
 
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Jun 30 12:02:19 2014 +0200
@@ -124,12 +124,12 @@
         ValueNode stride = strideNode();
         ValueNode initNode = this.initNode();
         if (!fromStamp.isCompatible(stamp)) {
-            stride = IntegerConvertNode.convert(stride, stamp);
-            initNode = IntegerConvertNode.convert(initNode, stamp);
+            stride = IntegerConvertNode.convert(stride, stamp, graph());
+            initNode = IntegerConvertNode.convert(initNode, stamp, graph());
         }
         ValueNode maxTripCount = loop.counted().maxTripCountNode(assumePositiveTripCount);
         if (!maxTripCount.stamp().isCompatible(stamp)) {
-            maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp);
+            maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph());
         }
         return IntegerArithmeticNode.add(graph, IntegerArithmeticNode.mul(graph, stride, IntegerArithmeticNode.sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode);
     }
@@ -139,7 +139,7 @@
         Stamp stamp = phi.stamp();
         ValueNode maxTripCount = loop.counted().maxTripCountNode(false);
         if (!maxTripCount.stamp().isCompatible(stamp)) {
-            maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp);
+            maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph());
         }
         return IntegerArithmeticNode.add(graph(), IntegerArithmeticNode.mul(graph(), strideNode(), maxTripCount), initNode());
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Jun 30 12:02:19 2014 +0200
@@ -62,7 +62,7 @@
                 range = IntegerArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph));
             }
         }
-        IntegerDivNode div = graph.add(new IntegerDivNode(iv.valueNode().stamp().unrestricted(), range, iv.strideNode()));
+        IntegerDivNode div = graph.add(new IntegerDivNode(range, iv.strideNode()));
         graph.addBeforeFixed(loop.entryPoint(), div);
         ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph);
         if (assumePositive) {
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Jun 30 12:02:19 2014 +0200
@@ -72,7 +72,7 @@
 
     @Override
     public long constantStride() {
-        if (value instanceof IntegerSubNode && base.valueNode() == value.y()) {
+        if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) {
             return -base.constantStride();
         }
         return base.constantStride();
@@ -85,7 +85,7 @@
 
     @Override
     public ValueNode strideNode() {
-        if (value instanceof IntegerSubNode && base.valueNode() == value.y()) {
+        if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) {
             return graph().unique(new NegateNode(base.strideNode()));
         }
         return base.strideNode();
@@ -93,7 +93,7 @@
 
     @Override
     public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) {
-        return op(base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(offset, stamp));
+        return op(base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(offset, stamp, graph()));
     }
 
     @Override
@@ -116,10 +116,10 @@
             return b + o;
         }
         if (value instanceof IntegerSubNode) {
-            if (base.valueNode() == value.x()) {
+            if (base.valueNode() == value.getX()) {
                 return b - o;
             } else {
-                assert base.valueNode() == value.y();
+                assert base.valueNode() == value.getY();
                 return o - b;
             }
         }
@@ -131,10 +131,10 @@
             return IntegerArithmeticNode.add(graph(), b, o);
         }
         if (value instanceof IntegerSubNode) {
-            if (base.valueNode() == value.x()) {
+            if (base.valueNode() == value.getX()) {
                 return IntegerArithmeticNode.sub(graph(), b, o);
             } else {
-                assert base.valueNode() == value.y();
+                assert base.valueNode() == value.getY();
                 return IntegerArithmeticNode.sub(graph(), o, b);
             }
         }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java	Mon Jun 30 12:02:19 2014 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.util.*;
 
 public class DerivedScaledInductionVariable extends InductionVariable {
 
@@ -102,7 +103,7 @@
 
     @Override
     public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) {
-        return IntegerArithmeticNode.mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp));
+        return IntegerArithmeticNode.mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph()));
     }
 
     @Override
@@ -119,4 +120,11 @@
     public long constantExtremum() {
         return base.constantExtremum() * scale.asConstant().asLong();
     }
+
+    @Override
+    public void deleteUnusedNodes() {
+        if (scale.isAlive() && scale.usages().isEmpty()) {
+            GraphUtil.killWithUnusedFloatingInputs(scale);
+        }
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java	Mon Jun 30 12:02:19 2014 +0200
@@ -62,7 +62,7 @@
     public abstract Direction direction();
 
     /**
-     * Returns the value node that is described by this InductionVariable instance.
+     * Returns the value node that is described by this induction variable.
      */
     public abstract ValueNode valueNode();
 
@@ -104,4 +104,10 @@
      * induction variable at the loop exit.
      */
     public abstract ValueNode exitValueNode();
+
+    /**
+     * Deletes any nodes created within the scope of this object that have no usages.
+     */
+    public void deleteUnusedNodes() {
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Mon Jun 30 12:02:19 2014 +0200
@@ -95,10 +95,10 @@
     private ValueNode addSub(ValueNode op, ValueNode base) {
         if (op instanceof IntegerAddNode || op instanceof IntegerSubNode) {
             IntegerArithmeticNode aritOp = (IntegerArithmeticNode) op;
-            if (aritOp.x() == base && loop.isOutsideLoop(aritOp.y())) {
-                return aritOp.y();
-            } else if (aritOp.y() == base && loop.isOutsideLoop(aritOp.x())) {
-                return aritOp.x();
+            if (aritOp.getX() == base && loop.isOutsideLoop(aritOp.getY())) {
+                return aritOp.getY();
+            } else if (aritOp.getY() == base && loop.isOutsideLoop(aritOp.getX())) {
+                return aritOp.getX();
             }
         }
         return null;
@@ -107,18 +107,27 @@
     private ValueNode mul(ValueNode op, ValueNode base) {
         if (op instanceof IntegerMulNode) {
             IntegerMulNode mul = (IntegerMulNode) op;
-            if (mul.x() == base && loop.isOutsideLoop(mul.y())) {
-                return mul.y();
-            } else if (mul.y() == base && loop.isOutsideLoop(mul.x())) {
-                return mul.x();
+            if (mul.getX() == base && loop.isOutsideLoop(mul.getY())) {
+                return mul.getY();
+            } else if (mul.getY() == base && loop.isOutsideLoop(mul.getX())) {
+                return mul.getX();
             }
         }
         if (op instanceof LeftShiftNode) {
             LeftShiftNode shift = (LeftShiftNode) op;
-            if (shift.x() == base && shift.y().isConstant()) {
-                return ConstantNode.forInt(1 << shift.y().asConstant().asInt(), base.graph());
+            if (shift.getX() == base && shift.getY().isConstant()) {
+                return ConstantNode.forInt(1 << shift.getY().asConstant().asInt(), base.graph());
             }
         }
         return null;
     }
+
+    /**
+     * Deletes any nodes created within the scope of this object that have no usages.
+     */
+    public void deleteUnusedNodes() {
+        for (InductionVariable iv : ivs.values()) {
+            iv.deleteUnusedNodes();
+        }
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Jun 30 12:02:19 2014 +0200
@@ -39,20 +39,20 @@
 
 public class LoopEx {
 
-    private final Loop lirLoop;
+    private final Loop loop;
     private LoopFragmentInside inside;
     private LoopFragmentWhole whole;
     private CountedLoopInfo counted; // TODO (gd) detect
     private LoopsData data;
     private InductionVariables ivs;
 
-    LoopEx(Loop lirLoop, LoopsData data) {
-        this.lirLoop = lirLoop;
+    LoopEx(Loop loop, LoopsData data) {
+        this.loop = loop;
         this.data = data;
     }
 
-    public Loop lirLoop() {
-        return lirLoop;
+    public Loop loop() {
+        return loop;
     }
 
     public LoopFragmentInside inside() {
@@ -91,7 +91,7 @@
     }
 
     public LoopBeginNode loopBegin() {
-        return (LoopBeginNode) lirLoop().getHeader().getBeginNode();
+        return (LoopBeginNode) loop().getHeader().getBeginNode();
     }
 
     public FixedNode predecessor() {
@@ -111,10 +111,10 @@
     }
 
     public LoopEx parent() {
-        if (lirLoop.getParent() == null) {
+        if (loop.getParent() == null) {
             return null;
         }
-        return data.loop(lirLoop.getParent());
+        return data.loop(loop.getParent());
     }
 
     public int size() {
@@ -123,7 +123,7 @@
 
     @Override
     public String toString() {
-        return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + lirLoop().getDepth() + ") " + loopBegin();
+        return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + loop().getDepth() + ") " + loopBegin();
     }
 
     private class InvariantPredicate implements NodePredicate {
@@ -141,11 +141,15 @@
             if (!BinaryNode.canTryReassociate(binary)) {
                 continue;
             }
-            BinaryNode result = BinaryNode.reassociate(binary, invariant);
+            BinaryNode result = BinaryNode.reassociate(binary, invariant, binary.getX(), binary.getY());
             if (result != binary) {
                 if (Debug.isLogEnabled()) {
                     Debug.log("%s : Reassociated %s into %s", MetaUtil.format("%H::%n", graph.method()), binary, result);
                 }
+                if (!result.isAlive()) {
+                    assert !result.isDeleted();
+                    result = graph.addOrUniqueWithInputs(result);
+                }
                 graph.replaceFloating(binary, result);
             }
         }
@@ -177,17 +181,17 @@
             Condition condition = null;
             InductionVariable iv = null;
             ValueNode limit = null;
-            if (isOutsideLoop(lessThan.x())) {
-                iv = getInductionVariables().get(lessThan.y());
+            if (isOutsideLoop(lessThan.getX())) {
+                iv = getInductionVariables().get(lessThan.getY());
                 if (iv != null) {
                     condition = lessThan.condition().mirror();
-                    limit = lessThan.x();
+                    limit = lessThan.getX();
                 }
-            } else if (isOutsideLoop(lessThan.y())) {
-                iv = getInductionVariables().get(lessThan.x());
+            } else if (isOutsideLoop(lessThan.getY())) {
+                iv = getInductionVariables().get(lessThan.getX());
                 if (iv != null) {
                     condition = lessThan.condition();
-                    limit = lessThan.y();
+                    limit = lessThan.getY();
                 }
             }
             if (condition == null) {
@@ -237,9 +241,9 @@
             if (b == untilBlock) {
                 continue;
             }
-            if (lirLoop().getExits().contains(b)) {
+            if (loop().getExits().contains(b)) {
                 exits.add((LoopExitNode) b.getBeginNode());
-            } else if (lirLoop().getBlocks().contains(b)) {
+            } else if (loop().getBlocks().contains(b)) {
                 blocks.add(b.getBeginNode());
                 work.addAll(b.getDominated());
             }
@@ -253,4 +257,13 @@
         }
         return ivs;
     }
+
+    /**
+     * Deletes any nodes created within the scope of this object that have no usages.
+     */
+    public void deleteUnusedNodes() {
+        if (ivs != null) {
+            ivs.deleteUnusedNodes();
+        }
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Jun 30 12:02:19 2014 +0200
@@ -302,7 +302,7 @@
     protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
-        for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().getExits())) {
+        for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) {
             LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
             FixedNode next = loopEarlyExit.next();
             if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideBefore.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInsideFrom.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Mon Jun 30 12:02:19 2014 +0200
@@ -56,8 +56,8 @@
     @Override
     public NodeBitMap nodes() {
         if (nodes == null) {
-            Loop lirLoop = loop().lirLoop();
-            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.getBlocks()), LoopFragment.toHirExits(lirLoop.getExits()));
+            Loop loop = loop().loop();
+            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirExits(loop.getExits()));
         }
         return nodes;
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Mon Jun 30 12:02:19 2014 +0200
@@ -34,7 +34,7 @@
 
 public class LoopsData {
 
-    private Map, LoopEx> lirLoopToEx = newIdentityMap();
+    private Map, LoopEx> loopToEx = newIdentityMap();
     private Map loopBeginToEx = newNodeIdentityMap();
     private ControlFlowGraph cfg;
 
@@ -45,15 +45,15 @@
             throw Debug.handle(e);
         }
 
-        for (Loop lirLoop : cfg.getLoops()) {
-            LoopEx ex = new LoopEx(lirLoop, this);
-            lirLoopToEx.put(lirLoop, ex);
+        for (Loop loop : cfg.getLoops()) {
+            LoopEx ex = new LoopEx(loop, this);
+            loopToEx.put(loop, ex);
             loopBeginToEx.put(ex.loopBegin(), ex);
         }
     }
 
-    public LoopEx loop(Loop lirLoop) {
-        return lirLoopToEx.get(lirLoop);
+    public LoopEx loop(Loop loop) {
+        return loopToEx.get(loop);
     }
 
     public LoopEx loop(LoopBeginNode loopBegin) {
@@ -61,16 +61,16 @@
     }
 
     public Collection loops() {
-        return lirLoopToEx.values();
+        return loopToEx.values();
     }
 
-    public List outterFirst() {
+    public List outerFirst() {
         ArrayList loops = new ArrayList<>(loops());
         Collections.sort(loops, new Comparator() {
 
             @Override
             public int compare(LoopEx o1, LoopEx o2) {
-                return o1.lirLoop().getDepth() - o2.lirLoop().getDepth();
+                return o1.loop().getDepth() - o2.loop().getDepth();
             }
         });
         return loops;
@@ -82,7 +82,7 @@
 
             @Override
             public int compare(LoopEx o1, LoopEx o2) {
-                return o2.lirLoop().getDepth() - o1.lirLoop().getDepth();
+                return o2.loop().getDepth() - o1.loop().getDepth();
             }
         });
         return loops;
@@ -121,4 +121,13 @@
         }
         return match;
     }
+
+    /**
+     * Deletes any nodes created within the scope of this object that have no usages.
+     */
+    public void deleteUnusedNodes() {
+        for (LoopEx loop : loops()) {
+            loop.deleteUnusedNodes();
+        }
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Mon Jun 30 12:02:19 2014 +0200
@@ -56,6 +56,7 @@
                         break;
                     }
                 }
+                dataCounted.deleteUnusedNodes();
             } while (peeled);
         }
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java	Mon Jun 30 12:02:19 2014 +0200
@@ -37,7 +37,7 @@
         if (context.getOptimisticOptimizations().useLoopLimitChecks()) {
             loops.detectedCountedLoops();
             for (LoopEx loop : loops.countedLoops()) {
-                if (loop.lirLoop().getChildren().isEmpty() && loop.counted().getStamp().getBits() <= 32) {
+                if (loop.loop().getChildren().isEmpty() && loop.counted().getStamp().getBits() <= 32) {
                     boolean hasSafepoint = false;
                     for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
                         hasSafepoint |= loopEnd.canSafepoint();
@@ -54,7 +54,7 @@
         for (LoopEx loop : loops.countedLoops()) {
             for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
                 Block b = loops.controlFlowGraph().blockFor(loopEnd);
-                blocks: while (b != loop.lirLoop().getHeader()) {
+                blocks: while (b != loop.loop().getHeader()) {
                     assert b != null;
                     for (FixedNode node : b.getNodes()) {
                         if (node instanceof Invoke || node instanceof ForeignCallNode) {
@@ -66,5 +66,6 @@
                 }
             }
         }
+        loops.deleteUnusedNodes();
     }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Mon Jun 30 12:02:19 2014 +0200
@@ -40,13 +40,14 @@
             if (LoopPeeling.getValue()) {
                 ToDoubleFunction probabilities = new FixedNodeProbabilityCache();
                 LoopsData data = new LoopsData(graph);
-                for (LoopEx loop : data.outterFirst()) {
+                for (LoopEx loop : data.outerFirst()) {
                     if (LoopPolicies.shouldPeel(loop, probabilities)) {
                         Debug.log("Peeling %s", loop);
                         LoopTransformations.peel(loop);
                         Debug.dump(graph, "After peeling %s", loop);
                     }
                 }
+                data.deleteUnusedNodes();
             }
         }
     }
diff -r 51f392557124 -r 5f01f7c48d40 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	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Mon Jun 30 12:02:19 2014 +0200
@@ -47,6 +47,7 @@
                 } catch (Throwable e) {
                     throw Debug.handle(e);
                 }
+                dataReassociate.deleteUnusedNodes();
             }
             if (LoopUnswitch.getValue()) {
                 boolean unswitched;
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2014, 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class LoopPhiCanonicalizerTest extends GraalCompilerTest {
+
+    private static int[] array = new int[1000];
+
+    @BeforeClass
+    public static void before() {
+        for (int i = 0; i < array.length; i++) {
+            array[i] = i;
+        }
+    }
+
+    public static long loopSnippet() {
+        int a = 0;
+        int b = 0;
+        int c = 0;
+        int d = 0;
+
+        long sum = 0;
+        while (d < 1000) {
+            sum += array[a++] + array[b++] + array[c++] + array[d++];
+        }
+        return sum;
+    }
+
+    @Test
+    public void test() {
+        StructuredGraph graph = parse("loopSnippet");
+        NodePredicate loopPhis = node -> node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode;
+
+        PhaseContext context = new PhaseContext(getProviders(), null);
+        Assert.assertEquals(5, graph.getNodes().filter(loopPhis).count());
+        new CanonicalizerPhase(false).apply(graph, context);
+        Assert.assertEquals(2, graph.getNodes().filter(loopPhis).count());
+
+        test("loopSnippet");
+    }
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -28,7 +28,7 @@
 
 /**
  * This node represents an unconditional explicit request for immediate deoptimization.
- * 
+ *
  * After this node, execution will continue using a fallback execution engine (such as an
  * interpreter) at the position described by the {@link #stateBefore() deoptimization state}.
  */
@@ -40,6 +40,11 @@
         super(StampFactory.forVoid());
     }
 
+    public AbstractDeoptimizeNode(FrameState stateBefore) {
+        super(StampFactory.forVoid());
+        this.stateBefore = stateBefore;
+    }
+
     @Override
     public boolean canDeoptimize() {
         return true;
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -78,7 +78,7 @@
     public void simplify(SimplifierTool tool) {
         while (condition instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition;
-            setCondition(negation.getInput());
+            setCondition(negation.getValue());
             negated = !negated;
         }
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -22,22 +22,19 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.spi.*;
 
-public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable {
+public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Binary {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public ValueNode x() {
+    public ValueNode getX() {
         return x;
     }
 
-    public ValueNode y() {
+    public ValueNode getY() {
         return y;
     }
 
@@ -57,8 +54,6 @@
         this.y = y;
     }
 
-    public abstract TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY);
-
     @Override
     public boolean verify() {
         assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
@@ -66,17 +61,6 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        switch (evaluate(tool.getConstantReflection(), x(), y())) {
-            case FALSE:
-                return LogicConstantNode.contradiction(graph());
-            case TRUE:
-                return LogicConstantNode.tautology(graph());
-        }
-        return this;
-    }
-
-    @Override
     public void generate(NodeLIRBuilderTool gen) {
     }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, 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
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard})
-public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable, Lowerable, GuardingNode {
+public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, GuardingNode {
 
     @Input(InputType.Condition) private LogicNode condition;
     private boolean negated;
@@ -48,11 +48,6 @@
         return condition;
     }
 
-    private void setCondition(LogicNode x) {
-        updateUsages(condition, x);
-        condition = x;
-    }
-
     public boolean isNegated() {
         return negated;
     }
@@ -66,24 +61,19 @@
         }
     }
 
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public Node canonical(CanonicalizerTool tool, Node forValue) {
         if (condition instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition;
-            setCondition(negation.getInput());
-            negated = !negated;
+            return new ConditionAnchorNode(negation.getValue(), !negated);
         }
-
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
             if (c.getValue() != negated) {
-                this.replaceAtUsages(null);
                 return null;
             } else {
-                return graph().add(new ValueAnchorNode(null));
+                return new ValueAnchorNode(null);
             }
         }
-
         return this;
     }
 
@@ -94,4 +84,8 @@
             graph().replaceFixedWithFixed(this, newAnchor);
         }
     }
+
+    public Node getValue() {
+        return condition;
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -68,34 +68,6 @@
     }
 
     /**
-     * Used to measure the impact of ConstantNodes not recording their usages. This and all code
-     * predicated on this value being true will be removed at some point.
-     */
-    public static final boolean ConstantNodeRecordsUsages = Boolean.parseBoolean(System.getProperty("graal.constantNodeRecordsUsages", "true"));
-
-    @Override
-    public boolean recordsUsages() {
-        return ConstantNodeRecordsUsages;
-    }
-
-    /**
-     * Computes the usages of this node by iterating over all the nodes in the graph, searching for
-     * those that have this node as an input.
-     */
-    public List gatherUsages(StructuredGraph graph) {
-        assert !ConstantNodeRecordsUsages;
-        List usages = new ArrayList<>();
-        for (Node node : graph.getNodes()) {
-            for (Node input : node.inputs()) {
-                if (input == this) {
-                    usages.add(node);
-                }
-            }
-        }
-        return usages;
-    }
-
-    /**
      * Gathers all the {@link ConstantNode}s that are inputs to the
      * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph.
      */
@@ -104,25 +76,15 @@
     }
 
     /**
-     * Replaces this node at its usages with another node. If {@link #ConstantNodeRecordsUsages} is
-     * false, this is an expensive operation that should only be used in test/verification/AOT code.
+     * Replaces this node at its usages with another node.
      */
     public void replace(StructuredGraph graph, Node replacement) {
-        if (!recordsUsages()) {
-            List usages = gatherUsages(graph);
-            for (Node usage : usages) {
-                usage.replaceFirstInput(this, replacement);
-            }
-            graph.removeFloating(this);
-        } else {
-            assert graph == graph();
-            graph().replaceFloating(this, replacement);
-        }
+        assert graph == graph();
+        graph().replaceFloating(this, replacement);
     }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        assert ConstantNodeRecordsUsages : "LIR generator should generate constants per-usage";
         if (gen.getLIRGeneratorTool().canInlineConstant(value) || onlyUsedInVirtualState()) {
             gen.setResult(this, value);
         } else {
@@ -152,10 +114,25 @@
         }
     }
 
+    public static ConstantNode forConstant(Constant constant, MetaAccessProvider metaAccess) {
+        if (constant.getKind().getStackKind() == Kind.Int && constant.getKind() != Kind.Int) {
+            return forInt(constant.asInt());
+        }
+        if (constant.getKind() == Kind.Object) {
+            return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess));
+        } else {
+            return createPrimitive(constant);
+        }
+    }
+
     public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) {
         return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess)));
     }
 
+    public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) {
+        return new ConstantNode(constant, stamp.constant(constant, metaAccess));
+    }
+
     /**
      * Returns a node for a Java primitive.
      */
@@ -165,6 +142,14 @@
     }
 
     /**
+     * Returns a node for a Java primitive.
+     */
+    public static ConstantNode forPrimitive(Constant constant) {
+        assert constant.getKind() != Kind.Object;
+        return forConstant(constant, null);
+    }
+
+    /**
      * Returns a node for a primitive of a given type.
      */
     public static ConstantNode forPrimitive(Stamp stamp, Constant constant, StructuredGraph graph) {
@@ -179,6 +164,20 @@
     }
 
     /**
+     * Returns a node for a primitive of a given type.
+     */
+    public static ConstantNode forPrimitive(Stamp stamp, Constant constant) {
+        if (stamp instanceof IntegerStamp) {
+            assert constant.getKind().isNumericInteger() && stamp.getStackKind() == constant.getKind().getStackKind();
+            IntegerStamp istamp = (IntegerStamp) stamp;
+            return forIntegerBits(istamp.getBits(), constant);
+        } else {
+            assert constant.getKind().isNumericFloat() && stamp.getStackKind() == constant.getKind();
+            return forConstant(constant, null);
+        }
+    }
+
+    /**
      * Returns a node for a double constant.
      *
      * @param d the double value for which to create the instruction
@@ -189,6 +188,16 @@
     }
 
     /**
+     * Returns a node for a double constant.
+     *
+     * @param d the double value for which to create the instruction
+     * @return a node for a double constant
+     */
+    public static ConstantNode forDouble(double d) {
+        return createPrimitive(Constant.forDouble(d));
+    }
+
+    /**
      * Returns a node for a float constant.
      *
      * @param f the float value for which to create the instruction
@@ -199,6 +208,16 @@
     }
 
     /**
+     * Returns a node for a float constant.
+     *
+     * @param f the float value for which to create the instruction
+     * @return a node for a float constant
+     */
+    public static ConstantNode forFloat(float f) {
+        return createPrimitive(Constant.forFloat(f));
+    }
+
+    /**
      * Returns a node for an long constant.
      *
      * @param i the long value for which to create the instruction
@@ -209,6 +228,16 @@
     }
 
     /**
+     * Returns a node for an long constant.
+     *
+     * @param i the long value for which to create the instruction
+     * @return a node for an long constant
+     */
+    public static ConstantNode forLong(long i) {
+        return createPrimitive(Constant.forLong(i));
+    }
+
+    /**
      * Returns a node for an integer constant.
      *
      * @param i the integer value for which to create the instruction
@@ -219,6 +248,16 @@
     }
 
     /**
+     * Returns a node for an integer constant.
+     *
+     * @param i the integer value for which to create the instruction
+     * @return a node for an integer constant
+     */
+    public static ConstantNode forInt(int i) {
+        return createPrimitive(Constant.forInt(i));
+    }
+
+    /**
      * Returns a node for a boolean constant.
      *
      * @param i the boolean value for which to create the instruction
@@ -229,6 +268,16 @@
     }
 
     /**
+     * Returns a node for a boolean constant.
+     *
+     * @param i the boolean value for which to create the instruction
+     * @return a node representing the boolean
+     */
+    public static ConstantNode forBoolean(boolean i) {
+        return createPrimitive(Constant.forInt(i ? 1 : 0));
+    }
+
+    /**
      * Returns a node for a byte constant.
      *
      * @param i the byte value for which to create the instruction
@@ -276,6 +325,20 @@
         return forIntegerBits(bits, Constant.forPrimitiveInt(bits, value), graph);
     }
 
+    private static ConstantNode forIntegerBits(int bits, Constant constant) {
+        long value = constant.asLong();
+        long bounds = SignExtendNode.signExtend(value, bits);
+        return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds));
+    }
+
+    /**
+     * Returns a node for a constant integer that's not directly representable as Java primitive
+     * (e.g. short).
+     */
+    public static ConstantNode forIntegerBits(int bits, long value) {
+        return forIntegerBits(bits, Constant.forPrimitiveInt(bits, value));
+    }
+
     /**
      * Returns a node for a constant integer that's compatible to a given stamp.
      */
@@ -288,6 +351,18 @@
         }
     }
 
+    /**
+     * Returns a node for a constant integer that's compatible to a given stamp.
+     */
+    public static ConstantNode forIntegerStamp(Stamp stamp, long value) {
+        if (stamp instanceof IntegerStamp) {
+            IntegerStamp intStamp = (IntegerStamp) stamp;
+            return forIntegerBits(intStamp.getBits(), value);
+        } else {
+            return forIntegerKind(stamp.getStackKind(), value);
+        }
+    }
+
     public static ConstantNode forIntegerKind(Kind kind, long value, StructuredGraph graph) {
         switch (kind) {
             case Byte:
@@ -301,6 +376,19 @@
         }
     }
 
+    public static ConstantNode forIntegerKind(Kind kind, long value) {
+        switch (kind) {
+            case Byte:
+            case Short:
+            case Int:
+                return createPrimitive(Constant.forInt((int) value));
+            case Long:
+                return createPrimitive(Constant.forLong(value));
+            default:
+                throw GraalInternalError.shouldNotReachHere("unknown kind " + kind);
+        }
+    }
+
     public static ConstantNode forFloatingKind(Kind kind, double value, StructuredGraph graph) {
         switch (kind) {
             case Float:
@@ -312,6 +400,17 @@
         }
     }
 
+    public static ConstantNode forFloatingKind(Kind kind, double value) {
+        switch (kind) {
+            case Float:
+                return ConstantNode.forFloat((float) value);
+            case Double:
+                return ConstantNode.forDouble(value);
+            default:
+                throw GraalInternalError.shouldNotReachHere("unknown kind " + kind);
+        }
+    }
+
     /**
      * Returns a node for a constant double that's compatible to a given stamp.
      */
@@ -319,6 +418,13 @@
         return forFloatingKind(stamp.getStackKind(), value, graph);
     }
 
+    /**
+     * Returns a node for a constant double that's compatible to a given stamp.
+     */
+    public static ConstantNode forFloatingStamp(Stamp stamp, double value) {
+        return forFloatingKind(stamp.getStackKind(), value);
+    }
+
     public static ConstantNode defaultForKind(Kind kind, StructuredGraph graph) {
         switch (kind) {
             case Boolean:
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -35,10 +35,11 @@
     private final Constant speculation;
 
     public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) {
-        this(action, reason, 0, Constant.NULL_OBJECT);
+        this(action, reason, 0, Constant.NULL_OBJECT, null);
     }
 
-    public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation) {
+    public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation, FrameState stateBefore) {
+        super(stateBefore);
         assert action != null;
         assert reason != null;
         assert speculation.getKind() == Kind.Object;
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -33,6 +33,11 @@
         super(stamp);
     }
 
+    public DeoptimizingFixedWithNextNode(Stamp stamp, FrameState stateBefore) {
+        super(stamp);
+        this.stateBefore = stateBefore;
+    }
+
     @Override
     public FrameState stateBefore() {
         return stateBefore;
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -63,10 +63,8 @@
         if (actionAndReason.isConstant() && speculation.isConstant()) {
             Constant constant = actionAndReason.asConstant();
             Constant speculationConstant = speculation.asConstant();
-            DeoptimizeNode newDeopt = graph().add(
-                            new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId(constant),
-                                            speculationConstant));
-            newDeopt.setStateBefore(stateBefore());
+            DeoptimizeNode newDeopt = new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId(
+                            constant), speculationConstant, stateBefore());
             return newDeopt;
         }
         return this;
diff -r 51f392557124 -r 5f01f7c48d40 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	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.java.*;
@@ -40,6 +41,8 @@
 @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}")
 public final class FrameState extends VirtualState implements IterableNodeType {
 
+    private static final DebugMetric METRIC_FRAMESTATE_COUNT = Debug.metric("FrameStateCount");
+
     protected final int localsSize;
 
     protected final int stackSize;
@@ -97,6 +100,7 @@
         this.duringCall = duringCall;
         assert !this.rethrowException || this.stackSize == 1 : "must have exception on top of the stack";
         assert this.locksSize() == this.monitorIds.size();
+        METRIC_FRAMESTATE_COUNT.increment();
     }
 
     /**
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -65,11 +65,6 @@
         return condition;
     }
 
-    public void setCondition(LogicNode x) {
-        updateUsages(condition, x);
-        condition = x;
-    }
-
     public boolean negated() {
         return negated;
     }
@@ -103,11 +98,11 @@
     public Node canonical(CanonicalizerTool tool) {
         if (condition() instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition();
-            return graph().unique(new GuardNode(negation.getInput(), getAnchor(), reason, action, !negated, speculation));
-        } else if (condition() instanceof LogicConstantNode) {
+            return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation);
+        }
+        if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() != negated) {
-                this.replaceAtUsages(null);
                 return null;
             }
         }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -83,7 +83,7 @@
             if (stamp().equals(object().stamp())) {
                 return object();
             } else {
-                return graph().unique(new PiNode(object(), stamp()));
+                return new PiNode(object(), stamp());
             }
         }
         return this;
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -94,8 +94,10 @@
     public void lower(LoweringTool tool) {
         GuardingNode guard = tool.createGuard(next(), condition, reason, action, negated);
         ValueAnchorNode anchor = graph().add(new ValueAnchorNode((ValueNode) guard));
-        PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard));
-        replaceAtUsages(pi);
+        if (usages().isNotEmpty()) {
+            PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard));
+            replaceAtUsages(pi);
+        }
         graph().replaceFixedWithFixed(this, anchor);
     }
 
@@ -116,19 +118,19 @@
     public Node canonical(CanonicalizerTool tool) {
         if (stamp() == StampFactory.illegal(object.getKind())) {
             // The guard always fails
-            return graph().add(new DeoptimizeNode(action, reason));
+            return new DeoptimizeNode(action, reason);
         }
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
             if (c.getValue() == negated) {
                 // The guard always fails
-                return graph().add(new DeoptimizeNode(action, reason));
+                return new DeoptimizeNode(action, reason);
             } else if (stamp().equals(object().stamp())) {
                 // The guard always succeeds, and does not provide new type information
                 return object;
             } else {
                 // The guard always succeeds, and provides new type information
-                return graph().unique(new PiNode(object, stamp()));
+                return new PiNode(object, stamp());
             }
         }
         return this;
diff -r 51f392557124 -r 5f01f7c48d40 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	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -147,7 +147,7 @@
             setTrueSuccessor(null);
             setFalseSuccessor(null);
             LogicNegationNode negation = (LogicNegationNode) condition();
-            IfNode newIfNode = graph().add(new IfNode(negation.getInput(), falseSucc, trueSucc, 1 - trueSuccessorProbability));
+            IfNode newIfNode = graph().add(new IfNode(negation.getValue(), falseSucc, trueSucc, 1 - trueSuccessorProbability));
             predecessor().replaceFirstSuccessor(this, newIfNode);
             GraphUtil.killWithUnusedFloatingInputs(this);
             return;
@@ -229,15 +229,17 @@
                         trueNext.replaceAtPredecessor(next);
                         graph().addBeforeFixed(this, trueNext);
                         for (Node usage : trueNext.usages().snapshot()) {
-                            if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) {
-                                Node newNode = graph().findDuplicate(usage);
-                                if (newNode != null) {
-                                    usage.replaceAtUsages(newNode);
-                                    usage.safeDelete();
+                            if (usage.isAlive()) {
+                                if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) {
+                                    Node newNode = graph().findDuplicate(usage);
+                                    if (newNode != null) {
+                                        usage.replaceAtUsages(newNode);
+                                        usage.safeDelete();
+                                    }
                                 }
-                            }
-                            if (usage.isAlive()) {
-                                tool.addToWorkList(usage);
+                                if (usage.isAlive()) {
+                                    tool.addToWorkList(usage);
+                                }
                             }
                         }
                         continue;
@@ -257,7 +259,7 @@
         assert trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty();
         if (condition() instanceof IntegerLessThanNode) {
             IntegerLessThanNode lessThan = (IntegerLessThanNode) condition();
-            Constant y = lessThan.y().stamp().asConstant();
+            Constant y = lessThan.getY().stamp().asConstant();
             if (y != null && y.asLong() == 0 && falseSuccessor().next() instanceof IfNode) {
                 IfNode ifNode2 = (IfNode) falseSuccessor().next();
                 if (ifNode2.condition() instanceof IntegerLessThanNode) {
@@ -269,24 +271,24 @@
                      * Convert x >= 0 && x < positive which is represented as !(x < 0) && x <
                      *  into an unsigned compare.
                      */
-                    if (lessThan2.x() == lessThan.x() && lessThan2.y().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.y().stamp()).isPositive() &&
+                    if (lessThan2.getX() == lessThan.getX() && lessThan2.getY().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.getY().stamp()).isPositive() &&
                                     sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) {
-                        below = graph().unique(new IntegerBelowThanNode(lessThan2.x(), lessThan2.y()));
+                        below = graph().unique(new IntegerBelowThanNode(lessThan2.getX(), lessThan2.getY()));
                         // swap direction
                         BeginNode tmp = falseSucc;
                         falseSucc = trueSucc;
                         trueSucc = tmp;
-                    } else if (lessThan2.y() == lessThan.x() && sameDestination(trueSuccessor(), ifNode2.trueSuccessor)) {
+                    } else if (lessThan2.getY() == lessThan.getX() && sameDestination(trueSuccessor(), ifNode2.trueSuccessor)) {
                         /*
                          * Convert x >= 0 && x <= positive which is represented as !(x < 0) &&
                          * !( > x), into x <| positive + 1. This can only be done for
                          * constants since there isn't a IntegerBelowEqualThanNode but that doesn't
                          * appear to be interesting.
                          */
-                        Constant positive = lessThan2.x().asConstant();
+                        Constant positive = lessThan2.getX().asConstant();
                         if (positive != null && positive.asLong() > 0 && positive.asLong() < positive.getKind().getMaxValue()) {
                             ConstantNode newLimit = ConstantNode.forIntegerKind(positive.getKind(), positive.asLong() + 1, graph());
-                            below = graph().unique(new IntegerBelowThanNode(lessThan.x(), newLimit));
+                            below = graph().unique(new IntegerBelowThanNode(lessThan.getX(), newLimit));
                         }
                     }
                     if (below != null) {
@@ -353,7 +355,7 @@
             InstanceOfNode instanceOfA = (InstanceOfNode) a;
             if (b instanceof IsNullNode) {
                 IsNullNode isNullNode = (IsNullNode) b;
-                if (isNullNode.object() == instanceOfA.object()) {
+                if (isNullNode.getValue() == instanceOfA.getValue()) {
                     if (instanceOfA.profile() != null && instanceOfA.profile().getNullSeen() != TriState.FALSE) {
                         instanceOfA.setProfile(new JavaTypeProfile(TriState.FALSE, instanceOfA.profile().getNotRecordedProbability(), instanceOfA.profile().getTypes()));
                     }
@@ -362,7 +364,7 @@
                 }
             } else if (b instanceof InstanceOfNode) {
                 InstanceOfNode instanceOfB = (InstanceOfNode) b;
-                if (instanceOfA.object() == instanceOfB.object() && !instanceOfA.type().isInterface() && !instanceOfB.type().isInterface() &&
+                if (instanceOfA.getValue() == instanceOfB.getValue() && !instanceOfA.type().isInterface() && !instanceOfB.type().isInterface() &&
                                 !instanceOfA.type().isAssignableFrom(instanceOfB.type()) && !instanceOfB.type().isAssignableFrom(instanceOfA.type())) {
                     // Two instanceof on the same value with mutually exclusive types.
                     JavaTypeProfile profileA = instanceOfA.profile();
@@ -423,9 +425,9 @@
                 }
                 Condition comparableCondition = null;
                 Condition conditionB = compareB.condition();
-                if (compareB.x() == compareA.x() && compareB.y() == compareA.y()) {
+                if (compareB.getX() == compareA.getX() && compareB.getY() == compareA.getY()) {
                     comparableCondition = conditionB;
-                } else if (compareB.x() == compareA.y() && compareB.y() == compareA.x()) {
+                } else if (compareB.getX() == compareA.getY() && compareB.getY() == compareA.getX()) {
                     comparableCondition = conditionB.mirror();
                 }
 
@@ -438,13 +440,13 @@
                     }
                 } else if (conditionA == Condition.EQ && conditionB == Condition.EQ) {
                     boolean canSwap = false;
-                    if ((compareA.x() == compareB.x() && valuesDistinct(constantReflection, compareA.y(), compareB.y()))) {
+                    if ((compareA.getX() == compareB.getX() && valuesDistinct(constantReflection, compareA.getY(), compareB.getY()))) {
                         canSwap = true;
-                    } else if ((compareA.x() == compareB.y() && valuesDistinct(constantReflection, compareA.y(), compareB.x()))) {
+                    } else if ((compareA.getX() == compareB.getY() && valuesDistinct(constantReflection, compareA.getY(), compareB.getX()))) {
                         canSwap = true;
-                    } else if ((compareA.y() == compareB.x() && valuesDistinct(constantReflection, compareA.x(), compareB.y()))) {
+                    } else if ((compareA.getY() == compareB.getX() && valuesDistinct(constantReflection, compareA.getX(), compareB.getY()))) {
                         canSwap = true;
-                    } else if ((compareA.y() == compareB.y() && valuesDistinct(constantReflection, compareA.x(), compareB.x()))) {
+                    } else if ((compareA.getY() == compareB.getY() && valuesDistinct(constantReflection, compareA.getX(), compareB.getX()))) {
                         canSwap = true;
                     }
 
@@ -558,11 +560,11 @@
             }
             boolean negateConditionalCondition;
             ValueNode otherValue;
-            if (constant == conditional.x()) {
-                otherValue = conditional.y();
+            if (constant == conditional.trueValue()) {
+                otherValue = conditional.falseValue();
                 negateConditionalCondition = false;
-            } else if (constant == conditional.y()) {
-                otherValue = conditional.x();
+            } else if (constant == conditional.falseValue()) {
+                otherValue = conditional.trueValue();
                 negateConditionalCondition = true;
             } else {
                 return null;
@@ -643,7 +645,7 @@
             return false;
         }
         Node singleUsage = mergeUsages.first();
-        if (!(singleUsage instanceof ValuePhiNode) || (singleUsage != compare.x() && singleUsage != compare.y())) {
+        if (!(singleUsage instanceof ValuePhiNode) || (singleUsage != compare.getX() && singleUsage != compare.getY())) {
             return false;
         }
 
@@ -662,8 +664,8 @@
         List mergePredecessors = merge.cfgPredecessors().snapshot();
         assert phi.valueCount() == merge.forwardEndCount();
 
-        Constant[] xs = constantValues(compare.x(), merge, false);
-        Constant[] ys = constantValues(compare.y(), merge, false);
+        Constant[] xs = constantValues(compare.getX(), merge, false);
+        Constant[] ys = constantValues(compare.getY(), merge, false);
         if (xs == null || ys == null) {
             return false;
         }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -165,9 +165,9 @@
         } else {
             graph().replaceFixed(this, node);
         }
-        call.safeDelete();
+        GraphUtil.killWithUnusedFloatingInputs(call);
         if (stateAfter.usages().isEmpty()) {
-            stateAfter.safeDelete();
+            GraphUtil.killWithUnusedFloatingInputs(stateAfter);
         }
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 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	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -189,9 +189,9 @@
         } else {
             graph().replaceSplit(this, node, next());
         }
-        call.safeDelete();
+        GraphUtil.killWithUnusedFloatingInputs(call);
         if (state.usages().isEmpty()) {
-            state.safeDelete();
+            GraphUtil.killWithUnusedFloatingInputs(state);
         }
     }
 
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -40,7 +40,7 @@
 
     /**
      * Returns a node for a boolean constant.
-     * 
+     *
      * @param v the boolean value for which to create the instruction
      * @param graph
      * @return a node representing the boolean
@@ -50,6 +50,16 @@
     }
 
     /**
+     * Returns a node for a boolean constant.
+     *
+     * @param v the boolean value for which to create the instruction
+     * @return a node representing the boolean
+     */
+    public static LogicConstantNode forBoolean(boolean v) {
+        return new LogicConstantNode(v);
+    }
+
+    /**
      * Gets a constant for {@code true}.
      */
     public static LogicConstantNode tautology(Graph graph) {
@@ -63,6 +73,20 @@
         return forBoolean(false, graph);
     }
 
+    /**
+     * Gets a constant for {@code true}.
+     */
+    public static LogicConstantNode tautology() {
+        return forBoolean(true);
+    }
+
+    /**
+     * Gets a constant for {@code false}.
+     */
+    public static LogicConstantNode contradiction() {
+        return forBoolean(false);
+    }
+
     public boolean getValue() {
         return value;
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -28,22 +28,22 @@
 /**
  * Logic node that negates its argument.
  */
-public class LogicNegationNode extends LogicNode implements Canonicalizable {
+public class LogicNegationNode extends LogicNode implements Canonicalizable.Unary {
 
-    @Input(InputType.Condition) private LogicNode input;
+    @Input(InputType.Condition) private LogicNode value;
 
-    public LogicNegationNode(LogicNode input) {
-        this.input = input;
+    public LogicNegationNode(LogicNode value) {
+        this.value = value;
     }
 
-    public LogicNode getInput() {
-        return input;
+    public LogicNode getValue() {
+        return value;
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (input instanceof LogicNegationNode) {
-            return ((LogicNegationNode) input).getInput();
+    public LogicNode canonical(CanonicalizerTool tool, LogicNode forValue) {
+        if (forValue instanceof LogicNegationNode) {
+            return ((LogicNegationNode) forValue).getValue();
         } else {
             return this;
         }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, 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
@@ -29,6 +29,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
@@ -175,7 +176,8 @@
 
     @Override
     public void simplify(SimplifierTool tool) {
-        // nothing yet
+        removeDeadPhis();
+        canonicalizePhis(tool);
     }
 
     public boolean isLoopExit(BeginNode begin) {
@@ -209,19 +211,101 @@
      * alive. This allows the removal of dead phi loops.
      */
     public void removeDeadPhis() {
-        Set alive = new HashSet<>();
-        for (PhiNode phi : phis()) {
-            NodePredicate isAlive = u -> !isPhiAtMerge(u) || alive.contains(u);
-            if (phi.usages().filter(isAlive).isNotEmpty()) {
-                alive.add(phi);
-                for (PhiNode keptAlive : phi.values().filter(PhiNode.class).filter(isAlive.negate())) {
-                    alive.add(keptAlive);
+        if (phis().isNotEmpty()) {
+            Set alive = new HashSet<>();
+            for (PhiNode phi : phis()) {
+                NodePredicate isAlive = u -> !isPhiAtMerge(u) || alive.contains(u);
+                if (phi.usages().filter(isAlive).isNotEmpty()) {
+                    alive.add(phi);
+                    for (PhiNode keptAlive : phi.values().filter(PhiNode.class).filter(isAlive.negate())) {
+                        alive.add(keptAlive);
+                    }
+                }
+            }
+            for (PhiNode phi : phis().filter(((NodePredicate) alive::contains).negate()).snapshot()) {
+                phi.replaceAtUsages(null);
+                phi.safeDelete();
+            }
+        }
+    }
+
+    private static final int NO_INCREMENT = Integer.MIN_VALUE;
+
+    /**
+     * Returns an array with one entry for each input of the phi, which is either
+     * {@link #NO_INCREMENT} or the increment, i.e., the value by which the phi is incremented in
+     * the corresponding branch.
+     */
+    private static int[] getSelfIncrements(PhiNode phi) {
+        int[] selfIncrement = new int[phi.valueCount()];
+        for (int i = 0; i < phi.valueCount(); i++) {
+            ValueNode input = phi.valueAt(i);
+            long increment = NO_INCREMENT;
+            if (input != null && input instanceof IntegerAddNode) {
+                IntegerAddNode add = (IntegerAddNode) input;
+                if (add.getX() == phi && add.getY().isConstant()) {
+                    increment = add.getY().asConstant().asLong();
+                } else if (add.getY() == phi && add.getX().isConstant()) {
+                    increment = add.getX().asConstant().asLong();
+                }
+            } else if (input == phi) {
+                increment = 0;
+            }
+            if (increment < Integer.MIN_VALUE || increment > Integer.MAX_VALUE || increment == NO_INCREMENT) {
+                increment = NO_INCREMENT;
+            }
+            selfIncrement[i] = (int) increment;
+        }
+        return selfIncrement;
+    }
+
+    /**
+     * Coalesces loop phis that represent the same value (which is not handled by normal Global
+     * Value Numbering).
+     */
+    public void canonicalizePhis(SimplifierTool tool) {
+        int phiCount = phis().count();
+        if (phiCount > 1) {
+            int phiInputCount = phiPredecessorCount();
+            int phiIndex = 0;
+            int[][] selfIncrement = new int[phiCount][];
+            PhiNode[] phis = this.phis().snapshot().toArray(new PhiNode[phiCount]);
+
+            for (phiIndex = 0; phiIndex < phiCount; phiIndex++) {
+                PhiNode phi = phis[phiIndex];
+                if (phi != null) {
+                    nextPhi: for (int otherPhiIndex = phiIndex + 1; otherPhiIndex < phiCount; otherPhiIndex++) {
+                        PhiNode otherPhi = phis[otherPhiIndex];
+                        if (otherPhi == null || phi.getNodeClass() != otherPhi.getNodeClass() || !phi.getNodeClass().valueEqual(phi, otherPhi)) {
+                            continue nextPhi;
+                        }
+                        if (selfIncrement[phiIndex] == null) {
+                            selfIncrement[phiIndex] = getSelfIncrements(phi);
+                        }
+                        if (selfIncrement[otherPhiIndex] == null) {
+                            selfIncrement[otherPhiIndex] = getSelfIncrements(otherPhi);
+                        }
+                        int[] phiIncrement = selfIncrement[phiIndex];
+                        int[] otherPhiIncrement = selfIncrement[otherPhiIndex];
+                        for (int inputIndex = 0; inputIndex < phiInputCount; inputIndex++) {
+                            if (phiIncrement[inputIndex] == NO_INCREMENT) {
+                                if (phi.valueAt(inputIndex) != otherPhi.valueAt(inputIndex)) {
+                                    continue nextPhi;
+                                }
+                            }
+                            if (phiIncrement[inputIndex] != otherPhiIncrement[inputIndex]) {
+                                continue nextPhi;
+                            }
+                        }
+                        if (tool != null) {
+                            tool.addToWorkList(otherPhi.usages());
+                        }
+                        otherPhi.replaceAtUsages(phi);
+                        GraphUtil.killWithUnusedFloatingInputs(otherPhi);
+                        phis[otherPhiIndex] = null;
+                    }
                 }
             }
         }
-        for (PhiNode phi : phis().filter(((NodePredicate) alive::contains).negate()).snapshot()) {
-            phi.replaceAtUsages(null);
-            phi.safeDelete();
-        }
     }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMap.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMap.java	Mon Jun 30 12:02:19 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Maps a {@linkplain LocationIdentity location} to the last node that (potentially) wrote to the
+ * location.
+ */
+public interface MemoryMap {
+
+    /**
+     * Gets the last node that that (potentially) wrote to {@code locationIdentity}.
+     */
+    MemoryNode getLastLocationAccess(LocationIdentity locationIdentity);
+
+    /**
+     * Gets the location identities in the domain of this map.
+     */
+    Collection getLocations();
+}
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -29,17 +31,68 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
-public abstract class MemoryMapNode extends FloatingNode {
+public class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable {
+
+    private final List locationIdentities;
+    @Input(InputType.Memory) private final NodeInputList nodes;
 
-    public MemoryMapNode() {
+    private boolean checkOrder(Map mmap) {
+        for (int i = 0; i < locationIdentities.size(); i++) {
+            LocationIdentity locationIdentity = locationIdentities.get(i);
+            ValueNode n = nodes.get(i);
+            assertTrue(mmap.get(locationIdentity) == n, "iteration order of keys differs from values in input map");
+        }
+        return true;
+    }
+
+    public MemoryMapNode(Map mmap) {
         super(StampFactory.forVoid());
+        locationIdentities = new ArrayList<>(mmap.keySet());
+        nodes = new NodeInputList<>(this, mmap.values());
+        assert checkOrder(mmap);
     }
 
-    public abstract MemoryNode getLastLocationAccess(LocationIdentity locationIdentity);
+    public boolean isEmpty() {
+        if (locationIdentities.isEmpty()) {
+            return true;
+        }
+        if (locationIdentities.size() == 1) {
+            if (nodes.get(0) instanceof StartNode) {
+                return true;
+            }
+        }
+        return false;
+    }
 
-    public abstract Set getLocations();
+    public MemoryNode getLastLocationAccess(LocationIdentity locationIdentity) {
+        if (locationIdentity == FINAL_LOCATION) {
+            return null;
+        } else {
+            int index = locationIdentities.indexOf(locationIdentity);
+            if (index == -1) {
+                index = locationIdentities.indexOf(ANY_LOCATION);
+            }
+            assert index != -1;
+            return (MemoryNode) nodes.get(index);
+        }
+    }
 
-    public abstract boolean replaceLastLocationAccess(MemoryNode oldNode, MemoryNode newNode);
+    public Collection getLocations() {
+        return locationIdentities;
+    }
+
+    public Map toMap() {
+        HashMap res = new HashMap<>(locationIdentities.size());
+        for (int i = 0; i < nodes.size(); i++) {
+            res.put(locationIdentities.get(i), (MemoryNode) nodes.get(i));
+        }
+        return res;
+    }
+
+    public void generate(NodeLIRBuilderTool generator) {
+        // nothing to do...
+    }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -158,14 +158,19 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public void simplify(SimplifierTool tool) {
         ValueNode singleValue = singleValue();
 
         if (singleValue != null) {
-            return singleValue;
+            for (Node node : usages().snapshot()) {
+                if (node instanceof ProxyNode && ((ProxyNode) node).proxyPoint() instanceof LoopExitNode && ((LoopExitNode) ((ProxyNode) node).proxyPoint()).loopBegin() == merge) {
+                    tool.addToWorkList(node.usages());
+                    graph().replaceFloating((FloatingNode) node, singleValue);
+                }
+            }
+            graph().replaceFloating(this, singleValue);
+            usages().forEach(tool::addToWorkList);
         }
-
-        return this;
     }
 
     public ValueNode firstValue() {
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 
-public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable {
+public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary {
 
     @Input(InputType.Condition) private LogicNode x;
     @Input(InputType.Condition) private LogicNode y;
@@ -65,36 +65,35 @@
         return shortCircuitProbability;
     }
 
-    protected ShortCircuitOrNode canonicalizeNegation() {
-        LogicNode xCond = x;
+    protected ShortCircuitOrNode canonicalizeNegation(LogicNode forX, LogicNode forY) {
+        LogicNode xCond = forX;
         boolean xNeg = xNegated;
         while (xCond instanceof LogicNegationNode) {
-            xCond = ((LogicNegationNode) xCond).getInput();
+            xCond = ((LogicNegationNode) xCond).getValue();
             xNeg = !xNeg;
         }
 
-        LogicNode yCond = y;
+        LogicNode yCond = forY;
         boolean yNeg = yNegated;
         while (yCond instanceof LogicNegationNode) {
-            yCond = ((LogicNegationNode) yCond).getInput();
+            yCond = ((LogicNegationNode) yCond).getValue();
             yNeg = !yNeg;
         }
 
-        if (xCond != x || yCond != y) {
-            return graph().unique(new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability));
+        if (xCond != forX || yCond != forY) {
+            return new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability);
         } else {
-            return null;
+            return this;
         }
     }
 
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ShortCircuitOrNode ret = canonicalizeNegation();
-        if (ret != null) {
+    public LogicNode canonical(CanonicalizerTool tool, LogicNode forX, LogicNode forY) {
+        ShortCircuitOrNode ret = canonicalizeNegation(forX, forY);
+        if (ret != this) {
             return ret;
         }
 
-        if (getX() == getY()) {
+        if (forX == forY) {
             // @formatter:off
             //  a ||  a = a
             //  a || !a = true
@@ -104,40 +103,40 @@
             if (isXNegated()) {
                 if (isYNegated()) {
                     // !a || !a = !a
-                    return graph().unique(new LogicNegationNode(getX()));
+                    return new LogicNegationNode(forX);
                 } else {
                     // !a || a = true
-                    return LogicConstantNode.tautology(graph());
+                    return LogicConstantNode.tautology();
                 }
             } else {
                 if (isYNegated()) {
                     // a || !a = true
-                    return LogicConstantNode.tautology(graph());
+                    return LogicConstantNode.tautology();
                 } else {
                     // a || a = a
-                    return getX();
+                    return forX;
                 }
             }
         }
-        if (getX() instanceof LogicConstantNode) {
-            if (((LogicConstantNode) getX()).getValue() ^ isXNegated()) {
-                return LogicConstantNode.tautology(graph());
+        if (forX instanceof LogicConstantNode) {
+            if (((LogicConstantNode) forX).getValue() ^ isXNegated()) {
+                return LogicConstantNode.tautology();
             } else {
                 if (isYNegated()) {
-                    return graph().unique(new LogicNegationNode(getY()));
+                    return new LogicNegationNode(forY);
                 } else {
-                    return getY();
+                    return forY;
                 }
             }
         }
-        if (getY() instanceof LogicConstantNode) {
-            if (((LogicConstantNode) getY()).getValue() ^ isYNegated()) {
-                return LogicConstantNode.tautology(graph());
+        if (forY instanceof LogicConstantNode) {
+            if (((LogicConstantNode) forY).getValue() ^ isYNegated()) {
+                return LogicConstantNode.tautology();
             } else {
                 if (isXNegated()) {
-                    return graph().unique(new LogicNegationNode(getX()));
+                    return new LogicNegationNode(forX);
                 } else {
-                    return getX();
+                    return forX;
                 }
             }
         }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -35,18 +35,16 @@
 /**
  * A node that attaches a type profile to a proxied input node.
  */
-public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, IterableNodeType, ValueProxy {
+public final class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy {
 
-    @Input private ValueNode object;
     private final JavaTypeProfile profile;
     private transient ResolvedJavaType lastCheckedType;
     private transient JavaTypeProfile lastCheckedProfile;
 
-    public ValueNode getObject() {
-        return object;
-    }
-
     public static ValueNode create(ValueNode object, JavaTypeProfile profile) {
+        if (StampTool.isExactType(object)) {
+            return object;
+        }
         if (profile == null) {
             // No profile, so create no node.
             return object;
@@ -58,9 +56,8 @@
         return object.graph().addWithoutUnique(new TypeProfileProxyNode(object, profile));
     }
 
-    private TypeProfileProxyNode(ValueNode object, JavaTypeProfile profile) {
-        super(object.stamp());
-        this.object = object;
+    private TypeProfileProxyNode(ValueNode value, JavaTypeProfile profile) {
+        super(value.stamp(), value);
         this.profile = profile;
     }
 
@@ -70,16 +67,16 @@
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(object.stamp());
+        return updateStamp(getValue().stamp());
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (StampTool.isExactType(object)) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (StampTool.isExactType(forValue)) {
             // The profile is useless - we know the type!
-            return object;
-        } else if (object instanceof TypeProfileProxyNode) {
-            TypeProfileProxyNode other = (TypeProfileProxyNode) object;
+            return forValue;
+        } else if (forValue instanceof TypeProfileProxyNode) {
+            TypeProfileProxyNode other = (TypeProfileProxyNode) forValue;
             JavaTypeProfile otherProfile = other.getProfile();
             if (otherProfile == lastCheckedProfile) {
                 // We have already incorporated the knowledge about this profile => abort.
@@ -90,33 +87,33 @@
             if (newProfile.equals(otherProfile)) {
                 // We are useless - just use the other proxy node.
                 Debug.log("Canonicalize with other proxy node.");
-                return object;
+                return forValue;
             }
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via other profile.");
-                return TypeProfileProxyNode.create(object, newProfile);
+                return new TypeProfileProxyNode(forValue, newProfile);
             }
-        } else if (StampTool.typeOrNull(object) != null) {
-            ResolvedJavaType type = StampTool.typeOrNull(object);
+        } else if (StampTool.typeOrNull(forValue) != null) {
+            ResolvedJavaType type = StampTool.typeOrNull(forValue);
             ResolvedJavaType uniqueConcrete = type.findUniqueConcreteSubtype();
             if (uniqueConcrete != null) {
                 // Profile is useless => remove.
                 Debug.log("Profile useless, there is enough static type information available.");
-                return object;
+                return forValue;
             }
             if (Objects.equals(type, lastCheckedType)) {
                 // We have already incorporate the knowledge about this type => abort.
                 return this;
             }
             lastCheckedType = type;
-            JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(object));
+            JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(forValue));
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via static type information.");
                 if (newProfile.getTypes().length == 0) {
                     // Only null profiling is not beneficial enough to keep the node around.
-                    return object;
+                    return forValue;
                 }
-                return TypeProfileProxyNode.create(object, newProfile);
+                return new TypeProfileProxyNode(forValue, newProfile);
             }
         }
         return this;
@@ -124,6 +121,6 @@
 
     @Override
     public ValueNode getOriginalNode() {
-        return object;
+        return getValue();
     }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -22,29 +22,22 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.spi.*;
 
-public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable {
+public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Unary {
 
-    @Input private ValueNode object;
+    @Input private ValueNode value;
 
-    public ValueNode object() {
-        return object;
+    public ValueNode getValue() {
+        return value;
     }
 
-    protected void setX(ValueNode object) {
-        updateUsages(this.object, object);
-        this.object = object;
+    public UnaryOpLogicNode(ValueNode value) {
+        assert value != null;
+        this.value = value;
     }
 
-    public UnaryOpLogicNode(ValueNode object) {
-        assert object != null;
-        this.object = object;
-    }
-
-    public abstract TriState evaluate(ValueNode forObject);
-
     @Override
     public void generate(NodeLIRBuilderTool gen) {
     }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -32,9 +32,9 @@
  * variable.
  */
 @NodeInfo(nameTemplate = "ValuePhi({i#values})")
-public class ValuePhiNode extends PhiNode implements Canonicalizable {
+public class ValuePhiNode extends PhiNode implements Simplifiable {
 
-    @Input final NodeInputList values = new NodeInputList<>(this);
+    @Input final NodeInputList values;
 
     /**
      * Create a value phi with the specified stamp.
@@ -45,6 +45,20 @@
     public ValuePhiNode(Stamp stamp, MergeNode merge) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
+        values = new NodeInputList<>(this);
+    }
+
+    /**
+     * Create a value phi with the specified stamp and the given values.
+     *
+     * @param stamp the stamp of the value
+     * @param merge the merge that the new phi belongs to
+     * @param values the initial values of the phi
+     */
+    public ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) {
+        super(stamp, merge);
+        assert stamp != StampFactory.forVoid();
+        this.values = new NodeInputList<>(this, values);
     }
 
     @Override
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -30,17 +30,19 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "&")
-public final class AndNode extends BitLogicNode implements Canonicalizable, NarrowableArithmeticNode {
+public final class AndNode extends BitLogicNode implements NarrowableArithmeticNode {
 
-    public AndNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public AndNode(ValueNode x, ValueNode y) {
+        super(StampTool.and(x.stamp(), y.stamp()), x, y);
+        assert x.stamp().isCompatible(y.stamp());
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.and(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.and(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -50,46 +52,45 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return x();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return forX;
         }
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new AndNode(stamp(), y(), x()));
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new AndNode(forY, forX);
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            long rawY = y().asConstant().asLong();
+        if (forX.isConstant()) {
+            return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            long rawY = forY.asConstant().asLong();
             long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp()));
             if ((rawY & mask) == mask) {
-                return x();
+                return forX;
             }
             if ((rawY & mask) == 0) {
-                return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+                return ConstantNode.forIntegerStamp(stamp(), 0);
             }
-            if (x() instanceof SignExtendNode) {
-                SignExtendNode ext = (SignExtendNode) x();
+            if (forX instanceof SignExtendNode) {
+                SignExtendNode ext = (SignExtendNode) forX;
                 if (rawY == ((1L << ext.getInputBits()) - 1)) {
-                    ValueNode result = graph().unique(new ZeroExtendNode(ext.getInput(), ext.getResultBits()));
-                    return result;
+                    return new ZeroExtendNode(ext.getValue(), ext.getResultBits());
                 }
             }
-            if (x().stamp() instanceof IntegerStamp) {
-                IntegerStamp xStamp = (IntegerStamp) x().stamp();
+            if (forX.stamp() instanceof IntegerStamp) {
+                IntegerStamp xStamp = (IntegerStamp) forX.stamp();
                 if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) {
                     // No bits are set which are outside the mask, so the mask will have no effect.
-                    return x();
+                    return forX;
                 }
             }
 
-            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitAnd(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitAnd(builder.operand(getX()), builder.operand(getY())));
     }
 }
diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Mon Jun 30 08:50:26 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Mon Jun 30 12:02:19 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, 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
@@ -25,21 +25,22 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * The {@code BinaryNode} class is the base of arithmetic and logic operations with two inputs.
  */
-public abstract class BinaryNode extends FloatingNode {
+public abstract class BinaryNode extends FloatingNode implements Canonicalizable.Binary {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public ValueNode x() {
+    public ValueNode getX() {
         return x;
     }
 
-    public ValueNode y() {
+    public ValueNode getY() {
         return y;
     }
 
@@ -63,9 +64,9 @@
         public ValueNode getValue(BinaryNode binary) {
             switch (this) {
                 case x:
-                    return binary.x();
+                    return binary.getX();
                 case y:
-                    return binary.y();
+                    return binary.getY();
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
@@ -74,9 +75,9 @@
         public ValueNode getOtherValue(BinaryNode binary) {
             switch (this) {
                 case x:
-                    return binary.y();
+                    return binary.getY();
                 case y:
-                    return binary.x();
+                    return binary.getX();
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
@@ -89,7 +90,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.add(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatAddNode(stamp, x, y, false));
+            return graph.unique(new FloatAddNode(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -101,7 +102,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.sub(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatSubNode(stamp, x, y, false));
+            return graph.unique(new FloatSubNode(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -113,7 +114,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.mul(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatMulNode(stamp, x, y, false));
+            return graph.unique(new FloatMulNode(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -124,8 +125,8 @@
     }
 
     public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) {
-        boolean resultX = criterion.apply(binary.x());
-        boolean resultY = criterion.apply(binary.y());
+        boolean resultX = criterion.apply(binary.getX());
+        boolean resultY = criterion.apply(binary.getY());
         if (resultX && !resultY) {
             return ReassociateMatch.x;
         }
@@ -157,8 +158,11 @@
      * 

* This method accepts only {@linkplain #canTryReassociate(BinaryNode) reassociable} operations * such as +, -, *, &, | and ^ + * + * @param forY + * @param forX */ - public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion) { + public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) { assert canTryReassociate(node); ReassociateMatch match1 = findReassociate(node, criterion); if (match1 == null) { @@ -203,29 +207,28 @@ ValueNode a = match2.getOtherValue(other); if (node instanceof IntegerAddNode || node instanceof IntegerSubNode) { BinaryNode associated; - StructuredGraph graph = node.graph(); if (invertM1) { - associated = IntegerArithmeticNode.sub(graph, m2, m1); + associated = IntegerArithmeticNode.sub(m2, m1); } else if (invertM2) { - associated = IntegerArithmeticNode.sub(graph, m1, m2); + associated = IntegerArithmeticNode.sub(m1, m2); } else { - associated = IntegerArithmeticNode.add(graph, m1, m2); + associated = IntegerArithmeticNode.add(m1, m2); } if (invertA) { - return IntegerArithmeticNode.sub(graph, associated, a); + return IntegerArithmeticNode.sub(associated, a); } if (aSub) { - return IntegerArithmeticNode.sub(graph, a, associated); + return IntegerArithmeticNode.sub(a, associated); } - return IntegerArithmeticNode.add(graph, a, associated); + return IntegerArithmeticNode.add(a, associated); } else if (node instanceof IntegerMulNode) { - return IntegerArithmeticNode.mul(node.graph(), a, IntegerAddNode.mul(node.graph(), m1, m2)); + return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2)); } else if (node instanceof AndNode) { - return BitLogicNode.and(node.graph(), a, BitLogicNode.and(node.graph(), m1, m2)); + return BitLogicNode.and(a, BitLogicNode.and(m1, m2)); } else if (node instanceof OrNode) { - return BitLogicNode.or(node.graph(), a, BitLogicNode.or(node.graph(), m1, m2)); + return BitLogicNode.or(a, BitLogicNode.or(m1, m2)); } else if (node instanceof XorNode) { - return BitLogicNode.xor(node.graph(), a, BitLogicNode.xor(node.graph(), m1, m2)); + return BitLogicNode.xor(a, BitLogicNode.xor(m1, m2)); } else { throw GraalInternalError.shouldNotReachHere(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -25,7 +25,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code LogicNode} class definition. @@ -34,7 +33,7 @@ /** * Constructs a new logic operation node. - * + * * @param x the first input into this node * @param y the second input into this node */ @@ -44,17 +43,26 @@ } public static BitLogicNode and(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.stamp().isCompatible(v2.stamp()); - return graph.unique(new AndNode(StampTool.and(v1.stamp(), v2.stamp()), v1, v2)); + return graph.unique(new AndNode(v1, v2)); + } + + public static BitLogicNode and(ValueNode v1, ValueNode v2) { + return new AndNode(v1, v2); } public static BitLogicNode or(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.stamp().isCompatible(v2.stamp()); - return graph.unique(new OrNode(StampTool.or(v1.stamp(), v2.stamp()), v1, v2)); + return graph.unique(new OrNode(v1, v2)); + } + + public static BitLogicNode or(ValueNode v1, ValueNode v2) { + return new OrNode(v1, v2); } public static BitLogicNode xor(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.stamp().isCompatible(v2.stamp()); - return graph.unique(new XorNode(StampTool.xor(v1.stamp(), v2.stamp()), v1, v2)); + return graph.unique(new XorNode(v1, v2)); + } + + public static BitLogicNode xor(ValueNode v1, ValueNode v2) { + return new XorNode(v1, v2); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,10 +23,8 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -62,7 +60,7 @@ */ public abstract boolean unorderedIsTrue(); - private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) { + private ValueNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) { Constant trueConstant = conditionalNode.trueValue().asConstant(); Constant falseConstant = conditionalNode.falseValue().asConstant(); @@ -71,14 +69,14 @@ boolean falseResult = cond.foldCondition(falseConstant, constant, constantReflection, unorderedIsTrue()); if (trueResult == falseResult) { - return LogicConstantNode.forBoolean(trueResult, graph()); + return LogicConstantNode.forBoolean(trueResult); } else { if (trueResult) { assert falseResult == false; return conditionalNode.condition(); } else { assert falseResult == true; - return graph().unique(new LogicNegationNode(conditionalNode.condition())); + return new LogicNegationNode(conditionalNode.condition()); } } @@ -86,60 +84,49 @@ return this; } - protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { + protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { throw new GraalInternalError("NormalizeCompareNode connected to %s (%s %s %s)", this, constant, normalizeNode, mirrored); } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && forY.isConstant()) { - return TriState.get(condition().foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue())); + return LogicConstantNode.forBoolean(condition().foldCondition(forX.asConstant(), forY.asConstant(), tool.getConstantReflection(), unorderedIsTrue())); } - return TriState.UNKNOWN; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - Node result = super.canonical(tool); - if (result != this) { - return result; - } - if (x().isConstant()) { - if ((result = canonicalizeSymmetricConstant(tool, x().asConstant(), y(), true)) != this) { + ValueNode result; + if (forX.isConstant()) { + if ((result = canonicalizeSymmetricConstant(tool, forX.asConstant(), forY, true)) != this) { return result; } - } else if (y().isConstant()) { - if ((result = canonicalizeSymmetricConstant(tool, y().asConstant(), x(), false)) != this) { + } else if (forY.isConstant()) { + if ((result = canonicalizeSymmetricConstant(tool, forY.asConstant(), forX, false)) != this) { return result; } - } else if (x() instanceof ConvertNode && y() instanceof ConvertNode) { - ConvertNode convertX = (ConvertNode) x(); - ConvertNode convertY = (ConvertNode) y(); - if (convertX.preservesOrder(condition()) && convertY.preservesOrder(condition()) && convertX.getInput().stamp().isCompatible(convertY.getInput().stamp())) { - return graph().unique(duplicateModified(convertX.getInput(), convertY.getInput())); + } else if (forX instanceof ConvertNode && forY instanceof ConvertNode) { + ConvertNode convertX = (ConvertNode) forX; + ConvertNode convertY = (ConvertNode) forY; + if (convertX.preservesOrder(condition()) && convertY.preservesOrder(condition()) && convertX.getValue().stamp().isCompatible(convertY.getValue().stamp())) { + return duplicateModified(convertX.getValue(), convertY.getValue()); } - } return this; } protected abstract CompareNode duplicateModified(ValueNode newX, ValueNode newY); - protected Node canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { - if (nonConstant instanceof BinaryNode) { - if (nonConstant instanceof ConditionalNode) { - return optimizeConditional(constant, (ConditionalNode) nonConstant, tool.getConstantReflection(), mirrored ? condition().mirror() : condition()); - } else if (nonConstant instanceof NormalizeCompareNode) { - return optimizeNormalizeCmp(constant, (NormalizeCompareNode) nonConstant, mirrored); - } + protected ValueNode canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { + if (nonConstant instanceof ConditionalNode) { + return optimizeConditional(constant, (ConditionalNode) nonConstant, tool.getConstantReflection(), mirrored ? condition().mirror() : condition()); + } else if (nonConstant instanceof NormalizeCompareNode) { + return optimizeNormalizeCmp(constant, (NormalizeCompareNode) nonConstant, mirrored); } else if (nonConstant instanceof ConvertNode) { ConvertNode convert = (ConvertNode) nonConstant; ConstantNode newConstant = canonicalConvertConstant(tool, convert, constant); if (newConstant != null) { if (mirrored) { - return graph().unique(duplicateModified(newConstant, convert.getInput())); + return duplicateModified(newConstant, convert.getValue()); } else { - return graph().unique(duplicateModified(convert.getInput(), newConstant)); + return duplicateModified(convert.getValue(), newConstant); } } } @@ -150,13 +137,17 @@ if (convert.preservesOrder(condition())) { Constant reverseConverted = convert.reverse(constant); if (convert.convert(reverseConverted).equals(constant)) { - return ConstantNode.forConstant(convert.getInput().stamp(), reverseConverted, tool.getMetaAccess(), convert.graph()); + return ConstantNode.forConstant(convert.getValue().stamp(), reverseConverted, tool.getMetaAccess()); } } return null; } public static CompareNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { + return graph.unique(createCompareNode(condition, x, y)); + } + + public static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) { assert x.getKind() == y.getKind(); assert condition.isCanonical() : "condition is not canonical: " + condition; assert !x.getKind().isNumericFloat(); @@ -178,6 +169,6 @@ comparison = new IntegerBelowThanNode(x, y); } - return graph.unique(comparison); + return comparison; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -37,9 +37,11 @@ * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note * that these nodes are not built directly from the bytecode but are introduced by canonicalization. */ -public final class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable { +public final class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable { @Input(InputType.Condition) private LogicNode condition; + @Input private ValueNode trueValue; + @Input private ValueNode falseValue; public LogicNode condition() { return condition; @@ -50,39 +52,41 @@ } public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { - super(trueValue.stamp().meet(falseValue.stamp()), trueValue, falseValue); + super(trueValue.stamp().meet(falseValue.stamp())); assert trueValue.stamp().isCompatible(falseValue.stamp()); this.condition = condition; + this.trueValue = trueValue; + this.falseValue = falseValue; } @Override public boolean inferStamp() { - return updateStamp(x().stamp().meet(y().stamp())); + return updateStamp(trueValue.stamp().meet(falseValue.stamp())); } public ValueNode trueValue() { - return x(); + return trueValue; } public ValueNode falseValue() { - return y(); + return falseValue; } @Override - public Node canonical(CanonicalizerTool tool) { + public ValueNode canonical(CanonicalizerTool tool) { if (condition instanceof LogicNegationNode) { LogicNegationNode negated = (LogicNegationNode) condition; - return graph().unique(new ConditionalNode(negated.getInput(), falseValue(), trueValue())); + return new ConditionalNode(negated.getValue(), falseValue(), trueValue()); } // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1 - if (x().isConstant() && y().isConstant() && condition instanceof IntegerEqualsNode) { + if (trueValue().isConstant() && falseValue().isConstant() && condition instanceof IntegerEqualsNode) { IntegerEqualsNode equals = (IntegerEqualsNode) condition; - if (equals.y().isConstant() && equals.y().asConstant().equals(Constant.INT_0) && equals.x().stamp() instanceof IntegerStamp) { - IntegerStamp equalsXStamp = (IntegerStamp) equals.x().stamp(); + if (equals.getY().isConstant() && equals.getY().asConstant().equals(Constant.INT_0) && equals.getX().stamp() instanceof IntegerStamp) { + IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp(); if (equalsXStamp.upMask() == 1) { - if (x().asConstant().equals(Constant.INT_0) && y().asConstant().equals(Constant.INT_1)) { - return IntegerConvertNode.convertUnsigned(equals.x(), stamp()); + if (trueValue().asConstant().equals(Constant.INT_0) && falseValue().asConstant().equals(Constant.INT_1)) { + return IntegerConvertNode.convertUnsigned(equals.getX(), stamp()); } } } @@ -98,7 +102,7 @@ if (condition instanceof CompareNode && ((CompareNode) condition).condition() == Condition.EQ) { // optimize the pattern (x == y) ? x : y CompareNode compare = (CompareNode) condition; - if ((compare.x() == trueValue() && compare.y() == falseValue()) || (compare.x() == falseValue() && compare.y() == trueValue())) { + if ((compare.getX() == trueValue() && compare.getY() == falseValue()) || (compare.getX() == falseValue() && compare.getY() == trueValue())) { return falseValue(); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,17 +31,10 @@ /** * Represents a conversion between primitive types. */ -public abstract class ConvertNode extends FloatingNode implements ArithmeticOperation { - - @Input private ValueNode input; +public abstract class ConvertNode extends UnaryNode implements ArithmeticOperation { - protected ConvertNode(Stamp stamp, ValueNode input) { - super(stamp); - this.input = input; - } - - public ValueNode getInput() { - return input; + protected ConvertNode(Stamp stamp, ValueNode value) { + super(stamp, value); } public abstract Constant convert(Constant c); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,24 +23,25 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; -public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode { +public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode implements Canonicalizable.Binary { @Input private ValueNode x; @Input private ValueNode y; - public ValueNode x() { - return x; - } - - public ValueNode y() { - return y; - } - public FixedBinaryNode(Stamp stamp, ValueNode x, ValueNode y) { super(stamp); this.x = x; this.y = y; } + + public ValueNode getX() { + return x; + } + + public ValueNode getY() { + return y; + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; @@ -31,10 +30,10 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "+") -public final class FloatAddNode extends FloatArithmeticNode implements Canonicalizable { +public final class FloatAddNode extends FloatArithmeticNode { - public FloatAddNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { - super(stamp, x, y, isStrictFP); + public FloatAddNode(ValueNode x, ValueNode y, boolean isStrictFP) { + super(x.stamp().unrestricted(), x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { @@ -49,26 +48,22 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new FloatAddNode(stamp(), y(), x(), isStrictFP())); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && !forY.isConstant()) { + return new FloatAddNode(forY, forX, isStrictFP()); } - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - Constant c = y().asConstant(); - if ((c.getKind() == Kind.Float && c.asFloat() == 0.0f) || (c.getKind() == Kind.Double && c.asDouble() == 0.0)) { - return x(); - } + if (forX.isConstant()) { + return ConstantNode.forConstant(evalConst(forX.asConstant(), forY.asConstant()), null); } + // Constant 0.0 can't be eliminated since it can affect the sign of the result. return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value op1 = builder.operand(x()); - Value op2 = builder.operand(y()); - if (!y().isConstant() && !livesLonger(this, y(), builder)) { + Value op1 = builder.operand(getX()); + Value op2 = builder.operand(getY()); + if (!getY().isConstant() && !livesLonger(this, getY(), builder)) { Value op = op1; op1 = op2; op2 = op; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -36,7 +35,7 @@ * A {@code FloatConvert} converts between integers and floating point numbers according to Java * semantics. */ -public class FloatConvertNode extends ConvertNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable { +public class FloatConvertNode extends ConvertNode implements Lowerable, ArithmeticLIRLowerable { private final FloatConvert op; @@ -95,7 +94,7 @@ @Override public boolean inferStamp() { - return updateStamp(createStamp(op, getInput())); + return updateStamp(createStamp(op, getValue())); } private static Constant convert(FloatConvert op, Constant value) { @@ -147,13 +146,13 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (getInput().isConstant()) { - return ConstantNode.forPrimitive(evalConst(getInput().asConstant()), graph()); - } else if (getInput() instanceof FloatConvertNode) { - FloatConvertNode other = (FloatConvertNode) getInput(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forConstant(evalConst(forValue.asConstant()), null); + } else if (forValue instanceof FloatConvertNode) { + FloatConvertNode other = (FloatConvertNode) forValue; if (other.isLossless() && other.op == this.op.reverse()) { - return other.getInput(); + return other.getValue(); } } return this; @@ -164,6 +163,6 @@ } public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getInput()))); + builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; @@ -31,10 +30,10 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "/") -public final class FloatDivNode extends FloatArithmeticNode implements Canonicalizable { +public final class FloatDivNode extends FloatArithmeticNode { - public FloatDivNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { - super(stamp, x, y, isStrictFP); + public FloatDivNode(ValueNode x, ValueNode y, boolean isStrictFP) { + super(x.stamp().unrestricted(), x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { @@ -49,15 +48,15 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitDiv(builder.operand(x()), builder.operand(y()), null)); + builder.setResult(this, gen.emitDiv(builder.operand(getX()), builder.operand(getY()), null)); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -22,12 +22,11 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @@ -57,17 +56,21 @@ } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode result = super.canonical(tool, forX, forY); + if (result != this) { + return result; + } if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) { FloatStamp xStamp = (FloatStamp) forX.stamp(); FloatStamp yStamp = (FloatStamp) forY.stamp(); if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) { - return TriState.TRUE; + return LogicConstantNode.tautology(); } else if (xStamp.alwaysDistinct(yStamp)) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } } - return super.evaluate(constantReflection, forX, forY); + return this; } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -22,12 +22,11 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @@ -62,11 +61,15 @@ } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode result = super.canonical(tool, forX, forY); + if (result != this) { + return result; + } if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && !unorderedIsTrue()) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } - return super.evaluate(constantReflection, forX, forY); + return this; } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; @@ -31,10 +30,10 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "*") -public final class FloatMulNode extends FloatArithmeticNode implements Canonicalizable { +public final class FloatMulNode extends FloatArithmeticNode { - public FloatMulNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { - super(stamp, x, y, isStrictFP); + public FloatMulNode(ValueNode x, ValueNode y, boolean isStrictFP) { + super(x.stamp().unrestricted(), x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { @@ -49,21 +48,21 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new FloatMulNode(stamp(), y(), x(), isStrictFP())); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && !forY.isConstant()) { + return new FloatMulNode(forY, forX, isStrictFP()); } - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + if (forX.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value op1 = builder.operand(x()); - Value op2 = builder.operand(y()); - if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) { + Value op1 = builder.operand(getX()); + Value op2 = builder.operand(getY()); + if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) { Value op = op1; op1 = op2; op2 = op; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; @@ -31,10 +30,10 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "%") -public class FloatRemNode extends FloatArithmeticNode implements Canonicalizable, Lowerable { +public class FloatRemNode extends FloatArithmeticNode implements Lowerable { - public FloatRemNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { - super(stamp, x, y, isStrictFP); + public FloatRemNode(ValueNode x, ValueNode y, boolean isStrictFP) { + super(x.stamp().unrestricted(), x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { @@ -49,9 +48,9 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + return ConstantNode.forPrimitive(evalConst(getX().asConstant(), getY().asConstant())); } return this; } @@ -63,6 +62,6 @@ @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitRem(builder.operand(x()), builder.operand(y()), null)); + builder.setResult(this, gen.emitRem(builder.operand(getX()), builder.operand(getY()), null)); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,18 +23,18 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "-") -public final class FloatSubNode extends FloatArithmeticNode implements Canonicalizable { +public final class FloatSubNode extends FloatArithmeticNode { - public FloatSubNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { - super(stamp, x, y, isStrictFP); + public FloatSubNode(ValueNode x, ValueNode y, boolean isStrictFP) { + super(x.stamp().unrestricted(), x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { @@ -49,34 +49,19 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return ConstantNode.forFloatingStamp(stamp(), 0.0f, graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return ConstantNode.forFloatingStamp(stamp(), 0.0f); } - if (x().isConstant() && y().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - Constant c = y().asConstant(); - if (c.getKind() == Kind.Float) { - float f = c.asFloat(); - if (f == 0.0f) { - return x(); - } - return graph().unique(new FloatAddNode(stamp(), x(), ConstantNode.forFloat(-f, graph()), isStrictFP())); - } else { - assert c.getKind() == Kind.Double; - double d = c.asDouble(); - if (d == 0.0) { - return x(); - } - return graph().unique(new FloatAddNode(stamp(), x(), ConstantNode.forDouble(-d, graph()), isStrictFP())); - } + if (forX.isConstant() && forY.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); } + // Constant 0.0 can't be eliminated since it can affect the sign of the result. return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y()))); + builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -32,15 +32,15 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "+") -public class IntegerAddNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode { +public class IntegerAddNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - public IntegerAddNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public IntegerAddNode(ValueNode x, ValueNode y) { + super(StampTool.add(x.stamp(), y.stamp()), x, y); } @Override public boolean inferStamp() { - return updateStamp(StampTool.add(x().stamp(), y().stamp())); + return updateStamp(StampTool.add(getX().stamp(), getY().stamp())); } @Override @@ -50,51 +50,51 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new IntegerAddNode(stamp(), y(), x())); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && !forY.isConstant()) { + return new IntegerAddNode(forY, forX); } - if (x() instanceof IntegerSubNode) { - IntegerSubNode sub = (IntegerSubNode) x(); - if (sub.y() == y()) { + if (forX instanceof IntegerSubNode) { + IntegerSubNode sub = (IntegerSubNode) forX; + if (sub.getY() == forY) { // (a - b) + b - return sub.x(); + return sub.getX(); } } - if (y() instanceof IntegerSubNode) { - IntegerSubNode sub = (IntegerSubNode) y(); - if (sub.y() == x()) { + if (forY instanceof IntegerSubNode) { + IntegerSubNode sub = (IntegerSubNode) forY; + if (sub.getY() == forX) { // b + (a - b) - return sub.x(); + return sub.getX(); } } - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + if (forX.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 0) { - return x(); + return forX; } // canonicalize expressions like "(a + 1) + 2" - BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); if (reassociated != this) { return reassociated; } } - if (x() instanceof NegateNode) { - return IntegerArithmeticNode.sub(graph(), y(), ((NegateNode) x()).x()); - } else if (y() instanceof NegateNode) { - return IntegerArithmeticNode.sub(graph(), x(), ((NegateNode) y()).x()); + if (forX instanceof NegateNode) { + return IntegerArithmeticNode.sub(forY, ((NegateNode) forX).getValue()); + } else if (forY instanceof NegateNode) { + return IntegerArithmeticNode.sub(forX, ((NegateNode) forY).getValue()); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value op1 = builder.operand(x()); - assert op1 != null : x() + ", this=" + this; - Value op2 = builder.operand(y()); - if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) { + Value op1 = builder.operand(getX()); + assert op1 != null : getX() + ", this=" + this; + Value op2 = builder.operand(getY()); + if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) { Value op = op1; op1 = op2; op2 = op; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -25,7 +25,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { @@ -35,15 +34,26 @@ } public static IntegerAddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new IntegerAddNode(StampTool.add(v1.stamp(), v2.stamp()), v1, v2)); + return graph.unique(new IntegerAddNode(v1, v2)); + } + + public static IntegerAddNode add(ValueNode v1, ValueNode v2) { + return new IntegerAddNode(v1, v2); } public static IntegerMulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.stamp().isCompatible(v2.stamp()); - return graph.unique(new IntegerMulNode(v1.stamp().unrestricted(), v1, v2)); + return graph.unique(new IntegerMulNode(v1, v2)); + } + + public static IntegerMulNode mul(ValueNode v1, ValueNode v2) { + return new IntegerMulNode(v1, v2); } public static IntegerSubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(new IntegerSubNode(StampTool.sub(v1.stamp(), v2.stamp()), v1, v2)); + return graph.unique(new IntegerSubNode(v1, v2)); + } + + public static IntegerSubNode sub(ValueNode v1, ValueNode v2) { + return new IntegerSubNode(v1, v2); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -57,32 +55,27 @@ } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode result = super.canonical(tool, forX, forY); + if (result != this) { + return result; + } if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { IntegerStamp xStamp = (IntegerStamp) forX.stamp(); IntegerStamp yStamp = (IntegerStamp) forY.stamp(); if (yStamp.isPositive()) { if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) { - return TriState.TRUE; + return LogicConstantNode.tautology(); } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } } } - return super.evaluate(constantReflection, forX, forY); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - Node result = super.canonical(tool); - if (result != this) { - return result; - } - if (x().isConstant() && x().asConstant().asLong() == 0) { + if (forX.isConstant() && forX.asConstant().asLong() == 0) { // 0 |<| y is the same as 0 != y - return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y()))); + return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY)); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -22,16 +22,14 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * An {@code IntegerConvert} converts an integer to an integer of different width. */ -public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable, Canonicalizable { +public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable { private final int resultBits; @@ -45,8 +43,8 @@ } public int getInputBits() { - if (getInput().stamp() instanceof IntegerStamp) { - return ((IntegerStamp) getInput().stamp()).getBits(); + if (getValue().stamp() instanceof IntegerStamp) { + return ((IntegerStamp) getValue().stamp()).getBits(); } else { return 0; } @@ -60,30 +58,36 @@ } } - protected ValueNode canonicalConvert() { - if (getInput().stamp() instanceof IntegerStamp) { - int inputBits = ((IntegerStamp) getInput().stamp()).getBits(); + protected ValueNode canonicalConvert(ValueNode value) { + if (value.stamp() instanceof IntegerStamp) { + int inputBits = ((IntegerStamp) value.stamp()).getBits(); if (inputBits == resultBits) { - return getInput(); - } else if (getInput().isConstant()) { - Constant ret = evalConst(getInput().asConstant()); - return ConstantNode.forIntegerBits(resultBits, ret.asLong(), graph()); + return value; + } else if (value.isConstant()) { + return ConstantNode.forIntegerBits(resultBits, evalConst(value.asConstant()).asLong()); } } - - return null; + return this; } public static ValueNode convert(ValueNode input, Stamp stamp) { return convert(input, stamp, false); } + public static ValueNode convert(ValueNode input, Stamp stamp, StructuredGraph graph) { + ValueNode convert = convert(input, stamp, false); + if (!convert.isAlive()) { + assert !convert.isDeleted(); + convert = graph.addOrUnique(convert); + } + return convert; + } + public static ValueNode convertUnsigned(ValueNode input, Stamp stamp) { return convert(input, stamp, true); } public static ValueNode convert(ValueNode input, Stamp stamp, boolean zeroExtend) { - StructuredGraph graph = input.graph(); IntegerStamp fromStamp = (IntegerStamp) input.stamp(); IntegerStamp toStamp = (IntegerStamp) stamp; @@ -91,13 +95,13 @@ if (toStamp.getBits() == fromStamp.getBits()) { result = input; } else if (toStamp.getBits() < fromStamp.getBits()) { - result = graph.unique(new NarrowNode(input, toStamp.getBits())); + result = new NarrowNode(input, toStamp.getBits()); } else if (zeroExtend) { // toStamp.getBits() > fromStamp.getBits() - result = graph.unique(new ZeroExtendNode(input, toStamp.getBits())); + result = new ZeroExtendNode(input, toStamp.getBits()); } else { // toStamp.getBits() > fromStamp.getBits() - result = graph.unique(new SignExtendNode(input, toStamp.getBits())); + result = new SignExtendNode(input, toStamp.getBits()); } IntegerStamp resultStamp = (IntegerStamp) result.stamp(); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -31,62 +31,61 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "/") -public class IntegerDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { +public class IntegerDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - public IntegerDivNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public IntegerDivNode(ValueNode x, ValueNode y) { + super(StampTool.div(x.stamp(), y.stamp()), x, y); } @Override public boolean inferStamp() { - return updateStamp(StampTool.div(x().stamp(), y().stamp())); + return updateStamp(StampTool.div(getX().stamp(), getY().stamp())); } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - long y = y().asConstant().asLong(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + long y = forY.asConstant().asLong(); if (y == 0) { return this; // this will trap, can not canonicalize } - return ConstantNode.forIntegerStamp(stamp(), x().asConstant().asLong() / y, graph()); - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + return ConstantNode.forIntegerStamp(stamp(), forX.asConstant().asLong() / y); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 1) { - return x(); + return forX; } if (c == -1) { - return graph().unique(new NegateNode(x())); + return new NegateNode(forX); } long abs = Math.abs(c); - if (CodeUtil.isPowerOf2(abs) && x().stamp() instanceof IntegerStamp) { - Stamp unrestricted = stamp().unrestricted(); - ValueNode dividend = x(); - IntegerStamp stampX = (IntegerStamp) x().stamp(); + if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) { + ValueNode dividend = forX; + IntegerStamp stampX = (IntegerStamp) forX.stamp(); int log2 = CodeUtil.log2(abs); // no rounding if dividend is positive or if its low bits are always 0 if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) { int bits = PrimitiveStamp.getBits(stamp()); - RightShiftNode sign = graph().unique(new RightShiftNode(unrestricted, x(), ConstantNode.forInt(bits - 1, graph()))); - UnsignedRightShiftNode round = graph().unique(new UnsignedRightShiftNode(unrestricted, sign, ConstantNode.forInt(bits - log2, graph()))); - dividend = IntegerArithmeticNode.add(graph(), dividend, round); + RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1)); + UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2)); + dividend = IntegerArithmeticNode.add(dividend, round); } - RightShiftNode shift = graph().unique(new RightShiftNode(unrestricted, dividend, ConstantNode.forInt(log2, graph()))); + RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2)); if (c < 0) { - return graph().unique(new NegateNode(shift)); + return new NegateNode(shift); } return shift; } } // Convert the expression ((a - a % b) / b) into (a / b). - if (x() instanceof IntegerSubNode) { - IntegerSubNode integerSubNode = (IntegerSubNode) x(); - if (integerSubNode.y() instanceof IntegerRemNode) { - IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.y(); - if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.x() == integerRemNode.x() && - this.y() == integerRemNode.y()) { - return graph().add(new IntegerDivNode(stamp(), integerSubNode.x(), this.y())); + if (forX instanceof IntegerSubNode) { + IntegerSubNode integerSubNode = (IntegerSubNode) forX; + if (integerSubNode.getY() instanceof IntegerRemNode) { + IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.getY(); + if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.getX() == integerRemNode.getX() && + forY == integerRemNode.getY()) { + return new IntegerDivNode(integerSubNode.getX(), forY); } } } @@ -108,11 +107,11 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), gen.state(this))); + gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this))); } @Override public boolean canDeoptimize() { - return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0); + return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; @@ -58,15 +57,15 @@ } @Override - protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { + protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { if (constant.getKind() == Kind.Int && constant.asInt() == 0) { - ValueNode a = mirrored ? normalizeNode.y() : normalizeNode.x(); - ValueNode b = mirrored ? normalizeNode.x() : normalizeNode.y(); + ValueNode a = mirrored ? normalizeNode.getY() : normalizeNode.getX(); + ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY(); - if (normalizeNode.x().getKind() == Kind.Double || normalizeNode.x().getKind() == Kind.Float) { - return graph().unique(new FloatEqualsNode(a, b)); + if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) { + return new FloatEqualsNode(a, b); } else { - return graph().unique(new IntegerEqualsNode(a, b)); + return new IntegerEqualsNode(a, b); } } return this; @@ -83,56 +82,56 @@ } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return TriState.TRUE; + return LogicConstantNode.tautology(); } else if (forX.stamp().alwaysDistinct(forY.stamp())) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } - return super.evaluate(constantReflection, forX, forY); + return super.canonical(tool, forX, forY); } @Override - protected Node canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { + protected ValueNode canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { if (constant.asLong() == 0) { if (nonConstant instanceof AndNode) { AndNode andNode = (AndNode) nonConstant; - return graph().unique(new IntegerTestNode(andNode.x(), andNode.y())); + return new IntegerTestNode(andNode.getX(), andNode.getY()); } else if (nonConstant instanceof ShiftNode) { if (nonConstant instanceof LeftShiftNode) { LeftShiftNode shift = (LeftShiftNode) nonConstant; - if (shift.y().isConstant()) { + if (shift.getY().isConstant()) { int mask = shift.getShiftAmountMask(); - int amount = shift.y().asConstant().asInt() & mask; - if (shift.x().getKind() == Kind.Int) { - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 >>> amount, graph()))); + int amount = shift.getY().asConstant().asInt() & mask; + if (shift.getX().getKind() == Kind.Int) { + return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 >>> amount)); } else { - assert shift.x().getKind() == Kind.Long; - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L >>> amount, graph()))); + assert shift.getX().getKind() == Kind.Long; + return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L >>> amount)); } } } else if (nonConstant instanceof RightShiftNode) { RightShiftNode shift = (RightShiftNode) nonConstant; - if (shift.y().isConstant() && ((IntegerStamp) shift.x().stamp()).isPositive()) { + if (shift.getY().isConstant() && ((IntegerStamp) shift.getX().stamp()).isPositive()) { int mask = shift.getShiftAmountMask(); - int amount = shift.y().asConstant().asInt() & mask; - if (shift.x().getKind() == Kind.Int) { - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph()))); + int amount = shift.getY().asConstant().asInt() & mask; + if (shift.getX().getKind() == Kind.Int) { + return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); } else { - assert shift.x().getKind() == Kind.Long; - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph()))); + assert shift.getX().getKind() == Kind.Long; + return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); } } } else if (nonConstant instanceof UnsignedRightShiftNode) { UnsignedRightShiftNode shift = (UnsignedRightShiftNode) nonConstant; - if (shift.y().isConstant()) { + if (shift.getY().isConstant()) { int mask = shift.getShiftAmountMask(); - int amount = shift.y().asConstant().asInt() & mask; - if (shift.x().getKind() == Kind.Int) { - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph()))); + int amount = shift.getY().asConstant().asInt() & mask; + if (shift.getX().getKind() == Kind.Int) { + return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); } else { - assert shift.x().getKind() == Kind.Long; - return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph()))); + assert shift.getX().getKind() == Kind.Long; + return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; @@ -58,46 +57,41 @@ } @Override - protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { + protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { assert condition() == Condition.LT; if (constant.getKind() == Kind.Int && constant.asInt() == 0) { - ValueNode a = mirrored ? normalizeNode.y() : normalizeNode.x(); - ValueNode b = mirrored ? normalizeNode.x() : normalizeNode.y(); + ValueNode a = mirrored ? normalizeNode.getY() : normalizeNode.getX(); + ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY(); - if (normalizeNode.x().getKind() == Kind.Double || normalizeNode.x().getKind() == Kind.Float) { - return graph().unique(new FloatLessThanNode(a, b, mirrored ^ normalizeNode.isUnorderedLess)); + if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) { + return new FloatLessThanNode(a, b, mirrored ^ normalizeNode.isUnorderedLess); } else { - return graph().unique(new IntegerLessThanNode(a, b)); + return new IntegerLessThanNode(a, b); } } return this; } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode result = super.canonical(tool, forX, forY); + if (result != this) { + return result; + } if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { IntegerStamp xStamp = (IntegerStamp) forX.stamp(); IntegerStamp yStamp = (IntegerStamp) forY.stamp(); if (xStamp.upperBound() < yStamp.lowerBound()) { - return TriState.TRUE; + return LogicConstantNode.tautology(); } else if (xStamp.lowerBound() >= yStamp.upperBound()) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } } - return super.evaluate(constantReflection, forX, forY); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - Node result = super.canonical(tool); - if (result != this) { - return result; - } - if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { - if (IntegerStamp.sameSign((IntegerStamp) x().stamp(), (IntegerStamp) y().stamp())) { - return graph().unique(new IntegerBelowThanNode(x(), y())); + if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { + if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) { + return new IntegerBelowThanNode(forX, forY); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -32,10 +32,11 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "*") -public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode { +public class IntegerMulNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - public IntegerMulNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public IntegerMulNode(ValueNode x, ValueNode y) { + super(x.stamp().unrestricted(), x, y); + assert x.stamp().isCompatible(y.stamp()); } @Override @@ -45,40 +46,40 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new IntegerMulNode(stamp(), y(), x())); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && !forY.isConstant()) { + return new IntegerMulNode(forY, forX); } - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + if (forX.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 1) { - return x(); + return forX; } if (c == 0) { - return ConstantNode.forIntegerStamp(stamp(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0); } long abs = Math.abs(c); if (abs > 0 && CodeUtil.isPowerOf2(abs)) { - LeftShiftNode shift = graph().unique(new LeftShiftNode(stamp().unrestricted(), x(), ConstantNode.forInt(CodeUtil.log2(abs), graph()))); + LeftShiftNode shift = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(abs))); if (c < 0) { - return graph().unique(new NegateNode(shift)); + return new NegateNode(shift); } else { return shift; } } // canonicalize expressions like "(a * 1) * 2" - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value op1 = builder.operand(x()); - Value op2 = builder.operand(y()); - if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) { + Value op1 = builder.operand(getX()); + Value op2 = builder.operand(getY()); + if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) { Value op = op1; op1 = op2; op2 = op; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -31,31 +31,31 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "%") -public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { +public class IntegerRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - public IntegerRemNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public IntegerRemNode(ValueNode x, ValueNode y) { + super(StampTool.rem(x.stamp(), y.stamp()), x, y); } @Override public boolean inferStamp() { - return updateStamp(StampTool.rem(x().stamp(), y().stamp())); + return updateStamp(StampTool.rem(getX().stamp(), getY().stamp())); } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - long y = y().asConstant().asLong(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + long y = forY.asConstant().asLong(); if (y == 0) { return this; // this will trap, can not canonicalize } - return ConstantNode.forIntegerStamp(stamp(), x().asConstant().asLong() % y, graph()); - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + return ConstantNode.forIntegerStamp(stamp(), forX.asConstant().asLong() % y); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 1 || c == -1) { - return ConstantNode.forIntegerStamp(stamp(), 0, graph()); - } else if (c > 0 && CodeUtil.isPowerOf2(c) && x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) { - return graph().unique(new AndNode(stamp(), x(), ConstantNode.forIntegerStamp(stamp(), c - 1, graph()))); + return ConstantNode.forIntegerStamp(stamp(), 0); + } else if (c > 0 && CodeUtil.isPowerOf2(c) && forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) { + return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1)); } } return this; @@ -68,11 +68,11 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), gen.state(this))); + gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(getX()), gen.operand(getY()), gen.state(this))); } @Override public boolean canDeoptimize() { - return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0); + return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -30,17 +30,18 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "-") -public class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode { +public class IntegerSubNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - public IntegerSubNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public IntegerSubNode(ValueNode x, ValueNode y) { + super(StampTool.sub(x.stamp(), y.stamp()), x, y); } @Override public boolean inferStamp() { - return updateStamp(StampTool.sub(x().stamp(), y().stamp())); + return updateStamp(StampTool.sub(getX().stamp(), getY().stamp())); } @Override @@ -50,75 +51,75 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return ConstantNode.forIntegerStamp(stamp(), 0, graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return ConstantNode.forIntegerStamp(stamp(), 0); } - if (x() instanceof IntegerAddNode) { - IntegerAddNode x = (IntegerAddNode) x(); - if (x.y() == y()) { + if (forX instanceof IntegerAddNode) { + IntegerAddNode x = (IntegerAddNode) forX; + if (x.getY() == forY) { // (a + b) - b - return x.x(); + return x.getX(); } - if (x.x() == y()) { + if (x.getX() == forY) { // (a + b) - a - return x.y(); + return x.getY(); } - } else if (x() instanceof IntegerSubNode) { - IntegerSubNode x = (IntegerSubNode) x(); - if (x.x() == y()) { + } else if (forX instanceof IntegerSubNode) { + IntegerSubNode x = (IntegerSubNode) forX; + if (x.getX() == forY) { // (a - b) - a - return graph().unique(new NegateNode(x.y())); + return new NegateNode(x.getY()); } } - if (y() instanceof IntegerAddNode) { - IntegerAddNode y = (IntegerAddNode) y(); - if (y.x() == x()) { + if (forY instanceof IntegerAddNode) { + IntegerAddNode y = (IntegerAddNode) forY; + if (y.getX() == forX) { // a - (a + b) - return graph().unique(new NegateNode(y.y())); + return new NegateNode(y.getY()); } - if (y.y() == x()) { + if (y.getY() == forX) { // b - (a + b) - return graph().unique(new NegateNode(y.x())); + return new NegateNode(y.getX()); } - } else if (y() instanceof IntegerSubNode) { - IntegerSubNode y = (IntegerSubNode) y(); - if (y.x() == x()) { + } else if (forY instanceof IntegerSubNode) { + IntegerSubNode y = (IntegerSubNode) forY; + if (y.getX() == forX) { // a - (a - b) - return y.y(); + return y.getY(); } } - if (x().isConstant() && y().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + if (forX.isConstant() && forY.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 0) { - return x(); + return forX; } - BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); if (reassociated != this) { return reassociated; } - if (c < 0 || ((IntegerStamp) StampFactory.forKind(y().getKind())).contains(-c)) { + if (c < 0 || ((IntegerStamp) StampFactory.forKind(forY.getKind())).contains(-c)) { // Adding a negative is more friendly to the backend since adds are // commutative, so prefer add when it fits. - return IntegerArithmeticNode.add(graph(), x(), ConstantNode.forIntegerStamp(stamp(), -c, graph())); + return IntegerArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp(), -c)); } - } else if (x().isConstant()) { - long c = x().asConstant().asLong(); + } else if (forX.isConstant()) { + long c = forX.asConstant().asLong(); if (c == 0) { - return graph().unique(new NegateNode(y())); + return new NegateNode(forY); } - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } - if (y() instanceof NegateNode) { - return IntegerArithmeticNode.add(graph(), x(), ((NegateNode) y()).x()); + if (forY instanceof NegateNode) { + return IntegerArithmeticNode.add(forX, ((NegateNode) forY).getValue()); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y()))); + builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -22,9 +22,8 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; /** @@ -45,19 +44,19 @@ } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && forY.isConstant()) { - return TriState.get((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0); + return LogicConstantNode.forBoolean((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0); } - if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { + if (getX().stamp() instanceof IntegerStamp && getY().stamp() instanceof IntegerStamp) { IntegerStamp xStamp = (IntegerStamp) forX.stamp(); IntegerStamp yStamp = (IntegerStamp) forY.stamp(); if ((xStamp.upMask() & yStamp.upMask()) == 0) { - return TriState.TRUE; + return LogicConstantNode.tautology(); } else if ((xStamp.downMask() & yStamp.downMask()) != 0) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } } - return TriState.UNKNOWN; + return this; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -23,9 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,7 +32,7 @@ /** * An IsNullNode will be true if the supplied value is null, and false if it is non-null. */ -public final class IsNullNode extends UnaryOpLogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable { +public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable { /** * Constructs a new IsNullNode instruction. @@ -52,38 +50,27 @@ @Override public boolean verify() { - assertTrue(object() != null, "is null input must not be null"); - assertTrue(object().stamp() instanceof AbstractObjectStamp, "is null input must be an object"); + assertTrue(getValue() != null, "is null input must not be null"); + assertTrue(getValue().stamp() instanceof AbstractObjectStamp, "is null input must be an object"); return super.verify(); } @Override - public Node canonical(CanonicalizerTool tool) { - switch (evaluate(object())) { - case FALSE: - return LogicConstantNode.contradiction(graph()); - case TRUE: - return LogicConstantNode.tautology(graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + Constant constant = forValue.asConstant(); + if (constant != null) { + assert constant.getKind() == Kind.Object; + return LogicConstantNode.forBoolean(constant.isNull()); + } + if (StampTool.isObjectNonNull(forValue.stamp())) { + return LogicConstantNode.contradiction(); } return this; } @Override - public TriState evaluate(ValueNode forObject) { - Constant constant = forObject.asConstant(); - if (constant != null) { - assert constant.getKind() == Kind.Object; - return TriState.get(constant.isNull()); - } - if (StampTool.isObjectNonNull(forObject.stamp())) { - return TriState.FALSE; - } - return TriState.UNKNOWN; - } - - @Override public void virtualize(VirtualizerTool tool) { - if (tool.getObjectState(object()) != null) { + if (tool.getObjectState(getValue()) != null) { tool.replaceWithValue(LogicConstantNode.contradiction(graph())); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; @@ -32,15 +31,15 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "<<") -public final class LeftShiftNode extends ShiftNode implements Canonicalizable { +public final class LeftShiftNode extends ShiftNode { - public LeftShiftNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public LeftShiftNode(ValueNode x, ValueNode y) { + super(x, y); } @Override public boolean inferStamp() { - return updateStamp(StampTool.leftShift(x().stamp(), y().stamp())); + return updateStamp(StampTool.leftShift(getX().stamp(), getY().stamp())); } @Override @@ -55,39 +54,39 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - int amount = y().asConstant().asInt(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + int amount = forY.asConstant().asInt(); int originalAmout = amount; int mask = getShiftAmountMask(); amount &= mask; if (amount == 0) { - return x(); + return forX; } - if (x() instanceof ShiftNode) { - ShiftNode other = (ShiftNode) x(); - if (other.y().isConstant()) { - int otherAmount = other.y().asConstant().asInt() & mask; + if (forX instanceof ShiftNode) { + ShiftNode other = (ShiftNode) forX; + if (other.getY().isConstant()) { + int otherAmount = other.getY().asConstant().asInt() & mask; if (other instanceof LeftShiftNode) { int total = amount + otherAmount; if (total != (total & mask)) { - return ConstantNode.forIntegerKind(getKind(), 0, graph()); + return ConstantNode.forIntegerKind(getKind(), 0); } - return graph().unique(new LeftShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph()))); + return new LeftShiftNode(other.getX(), ConstantNode.forInt(total)); } else if ((other instanceof RightShiftNode || other instanceof UnsignedRightShiftNode) && otherAmount == amount) { if (getKind() == Kind.Long) { - return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forLong(-1L << amount, graph()))); + return new AndNode(other.getX(), ConstantNode.forLong(-1L << amount)); } else { assert getKind() == Kind.Int; - return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forInt(-1 << amount, graph()))); + return new AndNode(other.getX(), ConstantNode.forInt(-1 << amount)); } } } } if (originalAmout != amount) { - return graph().unique(new LeftShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph()))); + return new LeftShiftNode(forX, ConstantNode.forInt(amount)); } } return this; @@ -95,6 +94,6 @@ @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitShl(builder.operand(x()), builder.operand(y()))); + builder.setResult(this, gen.emitShl(builder.operand(getX()), builder.operand(getY()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -62,51 +61,50 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode ret = canonicalConvert(); - if (ret != null) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode ret = canonicalConvert(forValue); + if (ret != this) { return ret; } - if (getInput() instanceof NarrowNode) { + if (forValue instanceof NarrowNode) { // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx - NarrowNode other = (NarrowNode) getInput(); - return graph().unique(new NarrowNode(other.getInput(), getResultBits())); - } else if (getInput() instanceof IntegerConvertNode) { + NarrowNode other = (NarrowNode) forValue; + return new NarrowNode(other.getValue(), getResultBits()); + } else if (forValue instanceof IntegerConvertNode) { // SignExtendNode or ZeroExtendNode - IntegerConvertNode other = (IntegerConvertNode) getInput(); + IntegerConvertNode other = (IntegerConvertNode) forValue; if (getResultBits() == other.getInputBits()) { // xxxx -(extend)-> yyyy xxxx -(narrow)-> xxxx // ==> no-op - return other.getInput(); + return other.getValue(); } else if (getResultBits() < other.getInputBits()) { // yyyyxxxx -(extend)-> zzzzzzzz yyyyxxxx -(narrow)-> xxxx // ==> yyyyxxxx -(narrow)-> xxxx - return graph().unique(new NarrowNode(other.getInput(), getResultBits())); + return new NarrowNode(other.getValue(), getResultBits()); } else { if (other instanceof SignExtendNode) { // sxxx -(sign-extend)-> ssssssss sssssxxx -(narrow)-> sssssxxx // ==> sxxx -(sign-extend)-> sssssxxx - return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); + return new SignExtendNode(other.getValue(), getResultBits()); } else if (other instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx // ==> xxxx -(zero-extend)-> 0000xxxx - return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + return new ZeroExtendNode(other.getValue(), getResultBits()); } } } - return this; } @Override public boolean inferStamp() { - return updateStamp(StampTool.narrowingConversion(getInput().stamp(), getResultBits())); + return updateStamp(StampTool.narrowingConversion(getValue().stamp(), getResultBits())); } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitNarrow(builder.operand(getInput()), getResultBits())); + builder.setResult(this, gen.emitNarrow(builder.operand(getValue()), getResultBits())); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -34,27 +33,20 @@ /** * The {@code NegateNode} node negates its operand. */ -public final class NegateNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { - - @Input private ValueNode x; - - public ValueNode x() { - return x; - } +public final class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { @Override public boolean inferStamp() { - return updateStamp(StampTool.negate(x().stamp())); + return updateStamp(StampTool.negate(getValue().stamp())); } /** * Creates new NegateNode instance. * - * @param x the instruction producing the value that is input to this instruction + * @param value the instruction producing the value that is input to this instruction */ - public NegateNode(ValueNode x) { - super(StampTool.negate(x.stamp())); - this.x = x; + public NegateNode(ValueNode value) { + super(StampTool.negate(value.stamp()), value); } public Constant evalConst(Constant... inputs) { @@ -75,22 +67,22 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x.asConstant()), graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forConstant(evalConst(forValue.asConstant()), null); } - if (x() instanceof NegateNode) { - return ((NegateNode) x()).x(); + if (forValue instanceof NegateNode) { + return ((NegateNode) forValue).getValue(); } - if (x() instanceof IntegerSubNode) { - IntegerSubNode sub = (IntegerSubNode) x; - return IntegerArithmeticNode.sub(graph(), sub.y(), sub.x()); + if (forValue instanceof IntegerSubNode) { + IntegerSubNode sub = (IntegerSubNode) forValue; + return new IntegerSubNode(sub.getY(), sub.getX()); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitNegate(builder.operand(x()))); + builder.setResult(this, gen.emitNegate(builder.operand(getValue()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -50,15 +51,21 @@ } @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + // nothing to do + return this; + } + + @Override public void lower(LoweringTool tool) { LogicNode equalComp; LogicNode lessComp; - if (x().stamp() instanceof FloatStamp) { - equalComp = graph().unique(new FloatEqualsNode(x(), y())); - lessComp = graph().unique(new FloatLessThanNode(x(), y(), isUnorderedLess)); + if (getX().stamp() instanceof FloatStamp) { + equalComp = graph().unique(new FloatEqualsNode(getX(), getY())); + lessComp = graph().unique(new FloatLessThanNode(getX(), getY(), isUnorderedLess)); } else { - equalComp = graph().unique(new IntegerEqualsNode(x(), y())); - lessComp = graph().unique(new IntegerLessThanNode(x(), y())); + equalComp = graph().unique(new IntegerEqualsNode(getX(), getY())); + lessComp = graph().unique(new IntegerLessThanNode(getX(), getY())); } ConditionalNode equalValue = graph().unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph()))); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -34,17 +33,11 @@ /** * Binary negation of long or integer values. */ -public final class NotNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { - - @Input private ValueNode x; - - public ValueNode x() { - return x; - } +public final class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { @Override public boolean inferStamp() { - return updateStamp(StampTool.not(x().stamp())); + return updateStamp(StampTool.not(getValue().stamp())); } @Override @@ -59,23 +52,22 @@ * @param x the instruction producing the value that is input to this instruction */ public NotNode(ValueNode x) { - super(StampTool.not(x.stamp())); - this.x = x; + super(StampTool.not(x.stamp()), x); } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant()), graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forConstant(evalConst(forValue.asConstant()), null); } - if (x() instanceof NotNode) { - return ((NotNode) x()).x(); + if (forValue instanceof NotNode) { + return ((NotNode) forValue).getValue(); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitNot(builder.operand(x()))); + builder.setResult(this, gen.emitNot(builder.operand(getValue()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -58,26 +57,20 @@ } @Override - public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { - if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return TriState.TRUE; - } else if (forX.stamp().alwaysDistinct(forY.stamp())) { - return TriState.FALSE; - } else { - return super.evaluate(constantReflection, forX, forY); - } - } - - @Override - public Node canonical(CanonicalizerTool tool) { - Node result = super.canonical(tool); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode result = super.canonical(tool, forX, forY); if (result != this) { return result; } - if (StampTool.isObjectAlwaysNull(x())) { - return graph().unique(new IsNullNode(y())); - } else if (StampTool.isObjectAlwaysNull(y())) { - return graph().unique(new IsNullNode(x())); + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return LogicConstantNode.tautology(); + } else if (forX.stamp().alwaysDistinct(forY.stamp())) { + return LogicConstantNode.contradiction(); + } + if (StampTool.isObjectAlwaysNull(forX)) { + return new IsNullNode(forY); + } else if (StampTool.isObjectAlwaysNull(forY)) { + return new IsNullNode(forX); } return this; } @@ -103,15 +96,15 @@ @Override public void virtualize(VirtualizerTool tool) { - State stateX = tool.getObjectState(x()); - State stateY = tool.getObjectState(y()); + State stateX = tool.getObjectState(getX()); + State stateY = tool.getObjectState(getY()); boolean xVirtual = stateX != null && stateX.getState() == EscapeState.Virtual; boolean yVirtual = stateY != null && stateY.getState() == EscapeState.Virtual; if (xVirtual && !yVirtual) { - virtualizeNonVirtualComparison(stateX, stateY != null ? stateY.getMaterializedValue() : y(), tool); + virtualizeNonVirtualComparison(stateX, stateY != null ? stateY.getMaterializedValue() : getY(), tool); } else if (!xVirtual && yVirtual) { - virtualizeNonVirtualComparison(stateY, stateX != null ? stateX.getMaterializedValue() : x(), tool); + virtualizeNonVirtualComparison(stateY, stateX != null ? stateX.getMaterializedValue() : getX(), tool); } else if (xVirtual && yVirtual) { boolean xIdentity = stateX.getVirtualObject().hasIdentity(); boolean yIdentity = stateY.getVirtualObject().hasIdentity(); @@ -119,7 +112,7 @@ /* * One of the two objects has identity, the other doesn't. In code, this looks like * "Integer.valueOf(a) == new Integer(b)", which is always false. - * + * * In other words: an object created via valueOf can never be equal to one created * by new in the same compilation unit. */ diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -30,17 +30,19 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|") -public final class OrNode extends BitLogicNode implements Canonicalizable { +public final class OrNode extends BitLogicNode { - public OrNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public OrNode(ValueNode x, ValueNode y) { + super(StampTool.or(x.stamp(), y.stamp()), x, y); + assert x.stamp().isCompatible(y.stamp()); } @Override public boolean inferStamp() { - return updateStamp(StampTool.or(x().stamp(), y().stamp())); + return updateStamp(StampTool.or(getX().stamp(), getY().stamp())); } @Override @@ -50,31 +52,31 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return x(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return forX; } - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new OrNode(stamp(), y(), x())); + if (forX.isConstant() && !forY.isConstant()) { + return new OrNode(forY, forX); } - if (x().isConstant()) { - return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - long rawY = y().asConstant().asLong(); + if (forX.isConstant()) { + return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + long rawY = forY.asConstant().asLong(); long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp())); if ((rawY & mask) == mask) { - return ConstantNode.forIntegerStamp(stamp(), mask, graph()); + return ConstantNode.forIntegerStamp(stamp(), mask); } if ((rawY & mask) == 0) { - return x(); + return forX; } - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitOr(builder.operand(x()), builder.operand(y()))); + builder.setResult(this, gen.emitOr(builder.operand(getX()), builder.operand(getY()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -36,22 +35,15 @@ * of a primitive value to some other incompatible stamp. The new stamp must have the same width as * the old stamp. */ -public class ReinterpretNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { - - @Input private ValueNode value; - - public ValueNode value() { - return value; - } +public class ReinterpretNode extends UnaryNode implements ArithmeticLIRLowerable { private ReinterpretNode(Kind to, ValueNode value) { this(StampFactory.forKind(to), value); } public ReinterpretNode(Stamp to, ValueNode value) { - super(to); + super(to, value); assert to instanceof PrimitiveStamp; - this.value = value; } public Constant evalConst(Constant... inputs) { @@ -88,24 +80,24 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - return ConstantNode.forPrimitive(evalConst(value.asConstant()), graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forConstant(evalConst(forValue.asConstant()), null); } - if (stamp().isCompatible(value.stamp())) { - return value; + if (stamp().isCompatible(forValue.stamp())) { + return forValue; } - if (value instanceof ReinterpretNode) { - ReinterpretNode reinterpret = (ReinterpretNode) value; - return value.graph().unique(new ReinterpretNode(stamp(), reinterpret.value())); + if (forValue instanceof ReinterpretNode) { + ReinterpretNode reinterpret = (ReinterpretNode) forValue; + return new ReinterpretNode(stamp(), reinterpret.getValue()); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - PlatformKind kind = gen.getPlatformKind(stamp()); - builder.setResult(this, gen.emitReinterpret(kind, builder.operand(value()))); + LIRKind kind = gen.getLIRKind(stamp()); + builder.setResult(this, gen.emitReinterpret(kind, builder.operand(getValue()))); } public static ValueNode reinterpret(Kind toKind, ValueNode value) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -31,10 +31,10 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = ">>") -public final class RightShiftNode extends ShiftNode implements Canonicalizable { +public final class RightShiftNode extends ShiftNode { - public RightShiftNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public RightShiftNode(ValueNode x, ValueNode y) { + super(x, y); } @Override @@ -49,35 +49,35 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) { - return graph().unique(new UnsignedRightShiftNode(stamp(), x(), y())); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) { + return new UnsignedRightShiftNode(forX, forY); } - if (x().isConstant() && y().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - int amount = y().asConstant().asInt(); + if (forX.isConstant() && forY.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + int amount = forY.asConstant().asInt(); int originalAmout = amount; int mask = getShiftAmountMask(); amount &= mask; if (amount == 0) { - return x(); + return forX; } - if (x() instanceof ShiftNode) { - ShiftNode other = (ShiftNode) x(); - if (other.y().isConstant()) { - int otherAmount = other.y().asConstant().asInt() & mask; + if (forX instanceof ShiftNode) { + ShiftNode other = (ShiftNode) forX; + if (other.getY().isConstant()) { + int otherAmount = other.getY().asConstant().asInt() & mask; if (other instanceof RightShiftNode) { int total = amount + otherAmount; if (total != (total & mask)) { - assert other.x().stamp() instanceof IntegerStamp; - IntegerStamp istamp = (IntegerStamp) other.x().stamp(); + assert other.getX().stamp() instanceof IntegerStamp; + IntegerStamp istamp = (IntegerStamp) other.getX().stamp(); if (istamp.isPositive()) { - return ConstantNode.forIntegerKind(getKind(), 0, graph()); + return ConstantNode.forIntegerKind(getKind(), 0); } if (istamp.isStrictlyNegative()) { - return ConstantNode.forIntegerKind(getKind(), -1L, graph()); + return ConstantNode.forIntegerKind(getKind(), -1L); } /* @@ -85,14 +85,14 @@ * full shift for this kind */ assert total >= mask; - return graph().unique(new RightShiftNode(stamp(), other.x(), ConstantNode.forInt(mask, graph()))); + return new RightShiftNode(other.getX(), ConstantNode.forInt(mask)); } - return graph().unique(new RightShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph()))); + return new RightShiftNode(other.getX(), ConstantNode.forInt(total)); } } } if (originalAmout != amount) { - return graph().unique(new RightShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph()))); + return new RightShiftNode(forX, ConstantNode.forInt(amount)); } } return this; @@ -100,6 +100,6 @@ @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitShr(builder.operand(x()), builder.operand(y()))); + builder.setResult(this, gen.emitShr(builder.operand(getX()), builder.operand(getY()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,12 +33,13 @@ /** * Creates a new shift operation. - * + * * @param x the first input value * @param s the second input value */ - public ShiftNode(Stamp stamp, ValueNode x, ValueNode s) { - super(stamp, x, s); + public ShiftNode(ValueNode x, ValueNode s) { + super(x.stamp().unrestricted(), x, s); + assert s.getKind() == Kind.Int; } public int getShiftAmountMask() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -68,32 +67,32 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode ret = canonicalConvert(); - if (ret != null) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode ret = canonicalConvert(forValue); + if (ret != this) { return ret; } - if (getInput() instanceof SignExtendNode) { + if (forValue instanceof SignExtendNode) { // sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx // ==> sxxx -(sign-extend)-> ssssssss sssssxxx - SignExtendNode other = (SignExtendNode) getInput(); - return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); - } else if (getInput() instanceof ZeroExtendNode) { - ZeroExtendNode other = (ZeroExtendNode) getInput(); + SignExtendNode other = (SignExtendNode) forValue; + return new SignExtendNode(other.getValue(), getResultBits()); + } else if (forValue instanceof ZeroExtendNode) { + ZeroExtendNode other = (ZeroExtendNode) forValue; if (other.getResultBits() > other.getInputBits()) { // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx // ==> sxxx -(zero-extend)-> 00000000 0000sxxx - return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + return new ZeroExtendNode(other.getValue(), getResultBits()); } } - if (getInput().stamp() instanceof IntegerStamp) { - IntegerStamp inputStamp = (IntegerStamp) getInput().stamp(); + if (forValue.stamp() instanceof IntegerStamp) { + IntegerStamp inputStamp = (IntegerStamp) forValue.stamp(); if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) { // 0xxx -(sign-extend)-> 0000 0xxx // ==> 0xxx -(zero-extend)-> 0000 0xxx - return graph().unique(new ZeroExtendNode(getInput(), getResultBits())); + return new ZeroExtendNode(forValue, getResultBits()); } } @@ -102,11 +101,11 @@ @Override public boolean inferStamp() { - return updateStamp(StampTool.signExtend(getInput().stamp(), getResultBits())); + return updateStamp(StampTool.signExtend(getValue().stamp(), getResultBits())); } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitSignExtend(builder.operand(getInput()), getInputBits(), getResultBits())); + builder.setResult(this, gen.emitSignExtend(builder.operand(getValue()), getInputBits(), getResultBits())); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, 2014, 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.calc; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.*; + +/** + * The {@code UnaryNode} class is the base of arithmetic and bit logic operations with exactly one + * input. + */ +public abstract class UnaryNode extends FloatingNode implements Canonicalizable.Unary { + + @Input private ValueNode value; + + public ValueNode getValue() { + return value; + } + + /** + * Creates a new UnaryNode instance. + * + * @param stamp the result type of this instruction + * @param value the input instruction + */ + public UnaryNode(Stamp stamp, ValueNode value) { + super(stamp); + this.value = value; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -31,35 +30,27 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|/|") -public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { +public class UnsignedDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - /** - * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}. - */ - @SuppressWarnings("unused") - private UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) { - this(StampFactory.forKind(kind), x, y); - } - - public UnsignedDivNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public UnsignedDivNode(ValueNode x, ValueNode y) { + super(x.stamp().unrestricted(), x, y); } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - long yConst = y().asConstant().asLong(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + long yConst = forY.asConstant().asLong(); if (yConst == 0) { return this; // this will trap, cannot canonicalize } - return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.divide(x().asConstant().asLong(), yConst), graph()); - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.divide(forX.asConstant().asLong(), yConst)); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 1) { - return x(); + return forX; } if (CodeUtil.isPowerOf2(c)) { - return graph().unique(new UnsignedRightShiftNode(stamp(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph()))); + return new UnsignedRightShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(c))); } } return this; @@ -72,11 +63,17 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), gen.state(this))); + gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this))); } @Override public boolean canDeoptimize() { - return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0); + return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0); } + + @NodeIntrinsic + public static native int unsignedDivide(int a, int b); + + @NodeIntrinsic + public static native long unsignedDivide(long a, long b); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -31,34 +30,26 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|%|") -public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { +public class UnsignedRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { - /** - * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}. - */ - @SuppressWarnings("unused") - private UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) { - this(StampFactory.forKind(kind), x, y); - } - - public UnsignedRemNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public UnsignedRemNode(ValueNode x, ValueNode y) { + super(x.stamp().unrestricted(), x, y); } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - long yConst = y().asConstant().asLong(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + long yConst = forY.asConstant().asLong(); if (yConst == 0) { return this; // this will trap, cannot canonicalize } - return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.remainder(x().asConstant().asLong(), yConst), graph()); - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.remainder(forX.asConstant().asLong(), yConst)); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 1) { - return ConstantNode.forIntegerStamp(stamp(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0); } else if (CodeUtil.isPowerOf2(c)) { - return graph().unique(new AndNode(stamp(), x(), ConstantNode.forIntegerStamp(stamp(), c - 1, graph()))); + return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1)); } } return this; @@ -71,11 +62,17 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), gen.state(this))); + gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(getX()), gen.operand(getY()), gen.state(this))); } @Override public boolean canDeoptimize() { - return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0); + return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0); } + + @NodeIntrinsic + public static native int unsignedRemainder(int a, int b); + + @NodeIntrinsic + public static native long unsignedRemainder(long a, long b); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; @@ -32,15 +31,15 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = ">>>") -public final class UnsignedRightShiftNode extends ShiftNode implements Canonicalizable { +public final class UnsignedRightShiftNode extends ShiftNode { - public UnsignedRightShiftNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public UnsignedRightShiftNode(ValueNode x, ValueNode y) { + super(x, y); } @Override public boolean inferStamp() { - return updateStamp(StampTool.unsignedRightShift(x().stamp(), y().stamp())); + return updateStamp(StampTool.unsignedRightShift(getX().stamp(), getY().stamp())); } @Override @@ -55,39 +54,39 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - int amount = y().asConstant().asInt(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + int amount = forY.asConstant().asInt(); int originalAmout = amount; int mask = getShiftAmountMask(); amount &= mask; if (amount == 0) { - return x(); + return forX; } - if (x() instanceof ShiftNode) { - ShiftNode other = (ShiftNode) x(); - if (other.y().isConstant()) { - int otherAmount = other.y().asConstant().asInt() & mask; + if (forX instanceof ShiftNode) { + ShiftNode other = (ShiftNode) forX; + if (other.getY().isConstant()) { + int otherAmount = other.getY().asConstant().asInt() & mask; if (other instanceof UnsignedRightShiftNode) { int total = amount + otherAmount; if (total != (total & mask)) { - return ConstantNode.forIntegerKind(getKind(), 0, graph()); + return ConstantNode.forIntegerKind(getKind(), 0); } - return graph().unique(new UnsignedRightShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph()))); + return new UnsignedRightShiftNode(other.getX(), ConstantNode.forInt(total)); } else if (other instanceof LeftShiftNode && otherAmount == amount) { if (getKind() == Kind.Long) { - return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forLong(-1L >>> amount, graph()))); + return new AndNode(other.getX(), ConstantNode.forLong(-1L >>> amount)); } else { assert getKind() == Kind.Int; - return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forInt(-1 >>> amount, graph()))); + return new AndNode(other.getX(), ConstantNode.forInt(-1 >>> amount)); } } } } if (originalAmout != amount) { - return graph().unique(new UnsignedRightShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph()))); + return new UnsignedRightShiftNode(forX, ConstantNode.forInt(amount)); } } return this; @@ -95,6 +94,6 @@ @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitUShr(builder.operand(x()), builder.operand(y()))); + builder.setResult(this, gen.emitUShr(builder.operand(getX()), builder.operand(getY()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,17 +30,19 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "^") -public final class XorNode extends BitLogicNode implements Canonicalizable { +public final class XorNode extends BitLogicNode { - public XorNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + public XorNode(ValueNode x, ValueNode y) { + super(StampTool.xor(x.stamp(), y.stamp()), x, y); + assert x.stamp().isCompatible(y.stamp()); } @Override public boolean inferStamp() { - return updateStamp(StampTool.xor(x().stamp(), y().stamp())); + return updateStamp(StampTool.xor(getX().stamp(), getY().stamp())); } @Override @@ -50,30 +52,30 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return ConstantNode.forIntegerStamp(stamp(), 0, graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return ConstantNode.forIntegerStamp(stamp(), 0); } - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new XorNode(stamp(), y(), x())); + if (forX.isConstant() && !forY.isConstant()) { + return new XorNode(forY, forX); } - if (x().isConstant()) { - return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph()); - } else if (y().isConstant()) { - long rawY = y().asConstant().asLong(); + if (forX.isConstant()) { + return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); + } else if (forY.isConstant()) { + long rawY = forY.asConstant().asLong(); long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp())); if ((rawY & mask) == 0) { - return x(); + return forX; } else if ((rawY & mask) == mask) { - return graph().unique(new NotNode(x())); + return new NotNode(forX); } - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitXor(builder.operand(x()), builder.operand(y()))); + builder.setResult(this, gen.emitXor(builder.operand(getX()), builder.operand(getY()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; @@ -78,28 +77,28 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode ret = canonicalConvert(); - if (ret != null) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode ret = canonicalConvert(forValue); + if (ret != this) { return ret; } - if (getInput() instanceof ZeroExtendNode) { + if (forValue instanceof ZeroExtendNode) { // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx // ==> xxxx -(zero-extend)-> 00000000 0000xxxx - ZeroExtendNode other = (ZeroExtendNode) getInput(); - return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + ZeroExtendNode other = (ZeroExtendNode) forValue; + return new ZeroExtendNode(other.getValue(), getResultBits()); } - if (getInput() instanceof NarrowNode) { - NarrowNode narrow = (NarrowNode) getInput(); - Stamp inputStamp = narrow.getInput().stamp(); + if (forValue instanceof NarrowNode) { + NarrowNode narrow = (NarrowNode) forValue; + Stamp inputStamp = narrow.getValue().stamp(); if (inputStamp instanceof IntegerStamp && inputStamp.isCompatible(stamp())) { IntegerStamp istamp = (IntegerStamp) inputStamp; long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(narrow.stamp())); if (((istamp.upMask() | istamp.downMask()) & ~mask) == 0) { // The original value is in the range of the masked zero extended result so // simply return the original input. - return narrow.getInput(); + return narrow.getValue(); } } } @@ -109,11 +108,11 @@ @Override public boolean inferStamp() { - return updateStamp(StampTool.zeroExtend(getInput().stamp(), getResultBits())); + return updateStamp(StampTool.zeroExtend(getValue().stamp(), getResultBits())); } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitZeroExtend(builder.operand(getInput()), getInputBits(), getResultBits())); + builder.setResult(this, gen.emitZeroExtend(builder.operand(getValue()), getInputBits(), getResultBits())); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,16 +36,16 @@ * [(base + x) + y] where base is a node and x and y are location nodes. */ @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}") -public final class AddLocationNode extends LocationNode implements Canonicalizable { +public final class AddLocationNode extends LocationNode implements Canonicalizable.Binary { @Input(InputType.Association) private ValueNode x; @Input(InputType.Association) private ValueNode y; - protected LocationNode getX() { + public LocationNode getX() { return (LocationNode) x; } - protected LocationNode getY() { + public LocationNode getY() { return (LocationNode) y; } @@ -70,21 +70,20 @@ return getX().getLocationIdentity(); } - @Override - public Node canonical(CanonicalizerTool tool) { - if (x instanceof ConstantLocationNode) { - return canonical((ConstantLocationNode) x, getY()); + public LocationNode canonical(CanonicalizerTool tool, LocationNode forX, LocationNode forY) { + if (forX instanceof ConstantLocationNode) { + return canonical((ConstantLocationNode) forX, forY); } - if (y instanceof ConstantLocationNode) { - return canonical((ConstantLocationNode) y, getX()); + if (forY instanceof ConstantLocationNode) { + return canonical((ConstantLocationNode) forY, forX); } - if (x instanceof IndexedLocationNode && y instanceof IndexedLocationNode) { - IndexedLocationNode xIdx = (IndexedLocationNode) x; - IndexedLocationNode yIdx = (IndexedLocationNode) y; + if (forX instanceof IndexedLocationNode && forY instanceof IndexedLocationNode) { + IndexedLocationNode xIdx = (IndexedLocationNode) forX; + IndexedLocationNode yIdx = (IndexedLocationNode) forY; if (xIdx.getIndexScaling() == yIdx.getIndexScaling()) { long displacement = xIdx.getDisplacement() + yIdx.getDisplacement(); - ValueNode index = IntegerArithmeticNode.add(graph(), xIdx.getIndex(), yIdx.getIndex()); - return IndexedLocationNode.create(getLocationIdentity(), getValueKind(), displacement, index, graph(), xIdx.getIndexScaling()); + ValueNode index = IntegerArithmeticNode.add(xIdx.getIndex(), yIdx.getIndex()); + return IndexedLocationNode.create(getLocationIdentity(), getValueKind(), displacement, index, xIdx.getIndexScaling()); } } return this; @@ -93,15 +92,15 @@ private LocationNode canonical(ConstantLocationNode constant, LocationNode other) { if (other instanceof ConstantLocationNode) { ConstantLocationNode otherConst = (ConstantLocationNode) other; - return ConstantLocationNode.create(getLocationIdentity(), getValueKind(), otherConst.getDisplacement() + constant.getDisplacement(), graph()); + return ConstantLocationNode.create(getLocationIdentity(), getValueKind(), otherConst.getDisplacement() + constant.getDisplacement()); } else if (other instanceof IndexedLocationNode) { IndexedLocationNode otherIdx = (IndexedLocationNode) other; - return IndexedLocationNode.create(getLocationIdentity(), getValueKind(), otherIdx.getDisplacement() + constant.getDisplacement(), otherIdx.getIndex(), graph(), otherIdx.getIndexScaling()); + return IndexedLocationNode.create(getLocationIdentity(), getValueKind(), otherIdx.getDisplacement() + constant.getDisplacement(), otherIdx.getIndex(), otherIdx.getIndexScaling()); } else if (other instanceof AddLocationNode) { AddLocationNode otherAdd = (AddLocationNode) other; LocationNode newInner = otherAdd.canonical(constant, otherAdd.getX()); if (newInner != otherAdd) { - return AddLocationNode.create(newInner, otherAdd.getY(), graph()); + return new AddLocationNode(newInner, otherAdd.getY()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -39,14 +38,12 @@ * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf * methods in Integer, Long, etc. */ -public class BoxNode extends FloatingNode implements VirtualizableAllocation, Lowerable, Canonicalizable { +public class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable { - @Input private ValueNode value; private final Kind boxingKind; public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) { - super(StampFactory.exactNonNull(resultType)); - this.value = value; + super(StampFactory.exactNonNull(resultType), value); this.boxingKind = boxingKind; } @@ -54,24 +51,17 @@ return boxingKind; } - public ValueNode getValue() { - return value; - } - @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); } @Override - public Node canonical(CanonicalizerTool tool) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { /* * Constant values are not canonicalized into their constant boxing objects because this * would mean that the information that they came from a valueOf is lost. */ - if (usages().isEmpty()) { - return null; - } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,6 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -35,7 +34,7 @@ * the if node's taken probability. Then the branch probability node will be removed. This node is * intended primarily for snippets, so that they can define their fast and slow paths. */ -public class BranchProbabilityNode extends FloatingNode implements Canonicalizable, Lowerable { +public class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable { public static final double LIKELY_PROBABILITY = 0.6; public static final double NOT_LIKELY_PROBABILITY = 1 - LIKELY_PROBABILITY; @@ -67,7 +66,7 @@ } @Override - public Node canonical(CanonicalizerTool tool) { + public void simplify(SimplifierTool tool) { if (probability.isConstant()) { double probabilityValue = probability.asConstant().asDouble(); if (probabilityValue < 0.0) { @@ -78,9 +77,9 @@ boolean couldSet = false; for (IntegerEqualsNode node : this.usages().filter(IntegerEqualsNode.class)) { if (node.condition() == Condition.EQ) { - ValueNode other = node.x(); - if (node.x() == this) { - other = node.y(); + ValueNode other = node.getX(); + if (node.getX() == this) { + other = node.getY(); } if (other.isConstant()) { double probabilityToSet = probabilityValue; @@ -94,15 +93,15 @@ } } } - if (!couldSet) { - if (isSubstitutionGraph()) { - return this; + if (couldSet) { + replaceAndDelete(condition); + tool.addToWorkList(condition.usages()); + } else { + if (!isSubstitutionGraph()) { + throw new GraalInternalError("Wrong usage of branch probability injection!"); } - throw new GraalInternalError("Wrong usage of branch probability injection!"); } - return condition; } - return this; } private boolean isSubstitutionGraph() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -43,6 +43,10 @@ return graph.unique(new ConstantLocationNode(identity, kind, displacement)); } + public static ConstantLocationNode create(LocationIdentity identity, Kind kind, long displacement) { + return new ConstantLocationNode(identity, kind, displacement); + } + private ConstantLocationNode(LocationIdentity identity, Kind kind, long displacement) { super(StampFactory.forVoid()); assert kind != Kind.Illegal && kind != Kind.Void; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -64,19 +64,20 @@ } public FixedAccessNode(ValueNode object, ValueNode location, Stamp stamp) { - this(object, location, stamp, null, BarrierType.NONE); + this(object, location, stamp, BarrierType.NONE); } public FixedAccessNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { - this(object, location, stamp, null, barrierType); + this(object, location, stamp, null, barrierType, false, null); } - public FixedAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { - super(stamp); + public FixedAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { + super(stamp, stateBefore); this.object = object; this.location = location; this.guard = guard; this.barrierType = barrierType; + this.nullCheck = nullCheck; } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,11 +36,11 @@ } public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { - super(object, location, stamp, guard, barrierType); + super(object, location, stamp, guard, barrierType, false, null); } - public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { - super(object, location, stamp, barrierType); + public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { + super(object, location, stamp, guard, barrierType, nullCheck, stateBefore); } public abstract FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -62,14 +62,14 @@ @Override public void generate(NodeLIRBuilderTool gen) { Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); - PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp()); + LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp()); gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, null)); } @Override public Node canonical(CanonicalizerTool tool) { if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) { - return graph().unique(new FloatingReadNode(((PiNode) object()).getOriginalNode(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType())); + return new FloatingReadNode(((PiNode) object()).getOriginalNode(), location(), getLastLocationAccess(), stamp(), getGuard(), getBarrierType()); } return ReadNode.canonicalizeRead(this, location(), object(), tool); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -66,8 +66,14 @@ return graph.unique(new IndexedLocationNode(identity, kind, displacement, index, indexScaling)); } + public static IndexedLocationNode create(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) { + return new IndexedLocationNode(identity, kind, displacement, index, indexScaling); + } + public IndexedLocationNode(LocationIdentity identity, Kind kind, long displacement, ValueNode index, int indexScaling) { super(StampFactory.forVoid()); + assert index != null; + assert indexScaling != 0; assert kind != Kind.Illegal && kind != Kind.Void; this.valueKind = kind; this.locationIdentity = identity; @@ -88,10 +94,8 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (index == null || indexScaling == 0) { - return ConstantLocationNode.create(getLocationIdentity(), getValueKind(), displacement, graph()); - } else if (index.isConstant()) { - return ConstantLocationNode.create(getLocationIdentity(), getValueKind(), index.asConstant().asLong() * indexScaling + displacement, graph()); + if (index.isConstant()) { + return ConstantLocationNode.create(getLocationIdentity(), getValueKind(), index.asConstant().asLong() * indexScaling + displacement); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -25,7 +25,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,23 +33,23 @@ * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by * this operation. */ -public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable { +public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable.Unary, Virtualizable { - @Input private ValueNode object; + @Input private ValueNode value; - public ValueNode object() { - return object; + public ValueNode getValue() { + return value; } - public LoadHubNode(ValueNode object, Kind kind) { + public LoadHubNode(ValueNode value, Kind kind) { super(getKind(kind), null); - this.object = object; + this.value = value; } - public LoadHubNode(ValueNode object, Kind kind, ValueNode guard) { + public LoadHubNode(ValueNode value, Kind kind, ValueNode guard) { super(getKind(kind), (GuardingNode) guard); - assert object != guard; - this.object = object; + assert value != guard; + this.value = value; } private static Stamp getKind(Kind kind) { @@ -63,10 +62,10 @@ } @Override - public Node canonical(CanonicalizerTool tool) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) { MetaAccessProvider metaAccess = tool.getMetaAccess(); - if (metaAccess != null && object.stamp() instanceof ObjectStamp) { - ObjectStamp stamp = (ObjectStamp) object.stamp(); + if (metaAccess != null && forObject.stamp() instanceof ObjectStamp) { + ObjectStamp stamp = (ObjectStamp) forObject.stamp(); ResolvedJavaType exactType; if (stamp.isExactType()) { @@ -81,7 +80,7 @@ } if (exactType != null) { - return ConstantNode.forConstant(exactType.getEncoding(Representation.ObjectHub), metaAccess, graph()); + return ConstantNode.forConstant(exactType.getEncoding(Representation.ObjectHub), metaAccess); } } return this; @@ -89,7 +88,7 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object); + State state = tool.getObjectState(value); if (state != null) { Constant constantHub = state.getVirtualObject().type().getEncoding(Representation.ObjectHub); tool.replaceWithValue(ConstantNode.forConstant(constantHub, tool.getMetaAccessProvider(), graph())); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -24,13 +24,16 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; /** * Loads a method from the virtual method table of a given hub. */ -public final class LoadMethodNode extends FixedWithNextNode implements Lowerable { +public final class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable { @Input private ValueNode hub; private final ResolvedJavaMethod method; @@ -55,6 +58,50 @@ tool.getLowerer().lower(this, tool); } + @Override + public Node canonical(CanonicalizerTool tool) { + if (hub instanceof LoadHubNode) { + ValueNode object = ((LoadHubNode) hub).getValue(); + ResolvedJavaType type = StampTool.typeOrNull(object); + if (StampTool.isExactType(object)) { + return resolveExactMethod(tool, type); + } + if (type != null && tool.assumptions().useOptimisticAssumptions()) { + ResolvedJavaMethod resolvedMethod = type.findUniqueConcreteMethod(method); + if (resolvedMethod != null && !type.isInterface() && method.getDeclaringClass().isAssignableFrom(type)) { + tool.assumptions().recordConcreteMethod(method, type, resolvedMethod); + return ConstantNode.forConstant(resolvedMethod.getEncoding(), tool.getMetaAccess()); + } + } + } + if (hub.isConstant()) { + return resolveExactMethod(tool, tool.getConstantReflection().asJavaType(hub.asConstant())); + } + + return this; + } + + /** + * Find the method which would be loaded. + * + * @param tool + * @param type the exact type of object being loaded from + * @return the method which would be invoked for {@code type} or null if it doesn't implement + * the method + */ + private Node resolveExactMethod(CanonicalizerTool tool, ResolvedJavaType type) { + ResolvedJavaMethod newMethod = type.resolveMethod(method, type); + if (newMethod == null) { + /* + * This really represent a misuse of LoadMethod since we're loading from a class which + * isn't known to implement the original method but for now at least fold it away. + */ + return ConstantNode.forConstant(Constant.NULL_OBJECT, null); + } else { + return ConstantNode.forConstant(newMethod.getEncoding(), tool.getMetaAccess()); + } + } + public ResolvedJavaMethod getMethod() { return method; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -37,13 +37,17 @@ public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode { public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { - super(object, location, stamp, barrierType); + super(object, location, stamp, null, barrierType); } public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { super(object, location, stamp, guard, barrierType); } + public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { + super(object, location, stamp, guard, barrierType, nullCheck, stateBefore); + } + private ReadNode(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) { /* * Used by node intrinsics. Really, you can trust me on that! Since the initial value for @@ -56,17 +60,14 @@ @Override public void generate(NodeLIRBuilderTool gen) { Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); - PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp()); + LIRKind readKind = gen.getLIRGeneratorTool().getLIRKind(stamp()); gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, gen.state(this))); } @Override public Node canonical(CanonicalizerTool tool) { if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) { - ReadNode readNode = graph().add(new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType())); - readNode.setNullCheck(getNullCheck()); - readNode.setStateBefore(stateBefore()); - return readNode; + return new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), getNullCheck(), stateBefore()); } return canonicalizeRead(this, location(), object(), tool); } @@ -87,7 +88,7 @@ GuardingNode guard = ((Access) read).getGuard(); if (guard != null && !(guard instanceof FixedNode)) { // The guard is necessary even if the read goes away. - return read.graph().add(new ValueAnchorNode((ValueNode) guard)); + return new ValueAnchorNode((ValueNode) guard); } else { // Read without usages or guard can be safely removed. return null; @@ -109,7 +110,7 @@ constant = tool.getConstantReflection().readUnsafeConstant(Kind.Object, base, displacement); } if (constant != null) { - return ConstantNode.forConstant(read.stamp(), constant, metaAccess, read.graph()); + return ConstantNode.forConstant(read.stamp(), constant, metaAccess); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,20 +24,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class UnboxNode extends FloatingNode implements Virtualizable, Lowerable, Canonicalizable { +public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable { - @Input private ValueNode value; private final Kind boxingKind; public UnboxNode(ValueNode value, Kind boxingKind) { - super(StampFactory.forKind(boxingKind.getStackKind())); - this.value = value; + super(StampFactory.forKind(boxingKind.getStackKind()), value); this.boxingKind = boxingKind; } @@ -45,10 +42,6 @@ return boxingKind; } - public ValueNode getValue() { - return value; - } - @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); @@ -56,7 +49,7 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(value); + State state = tool.getObjectState(getValue()); if (state != null && state.getState() == EscapeState.Virtual) { ResolvedJavaType objectType = state.getVirtualObject().type(); ResolvedJavaType expectedType = tool.getMetaAccessProvider().lookupJavaType(boxingKind.toBoxedJavaClass()); @@ -67,22 +60,19 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant constant = value.asConstant(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + Constant constant = forValue.asConstant(); Constant unboxed = tool.getConstantReflection().unboxPrimitive(constant); if (unboxed != null && unboxed.getKind() == boxingKind) { - return ConstantNode.forConstant(unboxed, tool.getMetaAccess(), graph()); + return ConstantNode.forConstant(unboxed, tool.getMetaAccess()); } - } else if (value instanceof BoxNode) { - BoxNode box = (BoxNode) value; + } else if (forValue instanceof BoxNode) { + BoxNode box = (BoxNode) forValue; if (boxingKind == box.getBoxingKind()) { return box.getValue(); } } - if (usages().isEmpty()) { - return null; - } return this; } diff -r 51f392557124 -r 5f01f7c48d40 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 Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -76,12 +76,12 @@ @Override protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { - return this.graph().add(new LoadFieldNode(object(), field)); + return new LoadFieldNode(object(), field); } @Override protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) { - return this.graph().add(new UnsafeLoadNode(object(), location, accessKind(), identity)); + return new UnsafeLoadNode(object(), location, accessKind(), identity); } @SuppressWarnings({"unchecked", "unused"}) diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -41,9 +41,14 @@ @Input(InputType.State) private FrameState stateAfter; public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) { + this(object, offset, value, accessKind, locationIdentity, null); + } + + public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) { super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity); + this.value = value; + this.stateAfter = stateAfter; assert accessKind != Kind.Void && accessKind != Kind.Illegal; - this.value = value; } public FrameState stateAfter() { @@ -103,14 +108,12 @@ @Override protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { - StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value())); - storeFieldNode.setStateAfter(stateAfter()); - return storeFieldNode; + return new StoreFieldNode(object(), field, value(), stateAfter()); } @Override protected ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity) { - return this.graph().add(new UnsafeStoreNode(object(), location, value, accessKind(), identity)); + return new UnsafeStoreNode(object(), location, value, accessKind(), identity); } public FrameState getState() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -53,7 +53,7 @@ } else { v = gen.operand(value()); } - PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(value().stamp()); + LIRKind writeKind = gen.getLIRGeneratorTool().getLIRKind(value().stamp()); gen.getLIRGeneratorTool().emitStore(writeKind, address, v, gen.state(this)); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,7 +32,7 @@ /** * The {@code ArrayLength} instruction gets the length of an array. */ -public final class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Virtualizable { +public final class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, Virtualizable { @Input private ValueNode array; @@ -41,14 +40,17 @@ return array; } + public ValueNode getValue() { + return array; + } + public ArrayLengthNode(ValueNode array) { super(StampFactory.positiveInt()); this.array = array; } - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode length = readArrayLength(graph(), array(), tool.getConstantReflection()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode length = readArrayLength(forValue, tool.getConstantReflection()); if (length != null) { return length; } @@ -60,7 +62,7 @@ * * @return a node representing the length of {@code array} or null if it is not available */ - public static ValueNode readArrayLength(StructuredGraph graph, ValueNode originalArray, ConstantReflectionProvider constantReflection) { + public static ValueNode readArrayLength(ValueNode originalArray, ConstantReflectionProvider constantReflection) { ArrayLengthProvider foundArrayLengthProvider = null; ValueNode result = originalArray; while (true) { @@ -87,7 +89,7 @@ if (constantValue != null && constantValue.isNonNull()) { Integer constantLength = constantReflection.readArrayLength(constantValue); if (constantLength != null) { - return ConstantNode.forInt(constantLength, graph); + return ConstantNode.forInt(constantLength); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,7 +32,7 @@ * Implements a type check where the type being checked is loaded at runtime. This is used, for * instance, to implement an object array store check. */ -public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable { +public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary, Lowerable { @Input private ValueNode object; @Input private ValueNode hub; @@ -55,6 +54,25 @@ this.forStoreCheck = forStoreCheck; } + public ValueNode object() { + return object; + } + + /** + * Gets the runtime-loaded type being cast to. + */ + public ValueNode hub() { + return hub; + } + + public ValueNode getX() { + return object; + } + + public ValueNode getY() { + return hub; + } + public boolean isForStoreCheck() { return forStoreCheck; } @@ -70,32 +88,19 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - assert object() != null : this; - - if (StampTool.isObjectAlwaysNull(object())) { - return object(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forHub) { + if (StampTool.isObjectAlwaysNull(forObject)) { + return forObject; } - if (hub.isConstant()) { - ResolvedJavaType t = tool.getConstantReflection().asJavaType(hub.asConstant()); + if (forHub.isConstant()) { + ResolvedJavaType t = tool.getConstantReflection().asJavaType(forHub.asConstant()); if (t != null) { - return graph().add(new CheckCastNode(t, object(), null, forStoreCheck)); + return new CheckCastNode(t, forObject, null, forStoreCheck); } } return this; } - public ValueNode object() { - return object; - } - - /** - * Gets the runtime-loaded type being cast to. - */ - public ValueNode hub() { - return hub; - } - @NodeIntrinsic public static native T checkCastDynamic(Class type, Object object, @ConstantNodeParameter boolean forStoreCheck); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -39,7 +39,7 @@ /** * Implements a type check against a compile-time known type. */ -public class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Virtualizable, ValueProxy { +public class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Simplifiable, Lowerable, Virtualizable, ValueProxy { @Input private ValueNode object; private final ResolvedJavaType type; @@ -141,8 +141,6 @@ @Override public Node canonical(CanonicalizerTool tool) { - assert object() != null : this; - ResolvedJavaType objectType = StampTool.typeOrNull(object()); if (objectType != null && type.isAssignableFrom(objectType)) { // we don't have to check for null types here because they will also pass the @@ -150,6 +148,24 @@ return object(); } + if (StampTool.isObjectAlwaysNull(object())) { + return object(); + } + + if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { + ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); + if (exactType != null && !exactType.equals(type)) { + // Propagate more precise type information to usages of the checkcast. + tool.assumptions().recordConcreteSubtype(type, exactType); + return new CheckCastNode(exactType, object, profile, forStoreCheck); + } + } + + return this; + } + + @Override + public void simplify(SimplifierTool tool) { // if the previous node is also a checkcast, with a less precise and compatible type, // replace both with one checkcast checking the more specific type. if (predecessor() instanceof CheckCastNode) { @@ -158,23 +174,10 @@ StructuredGraph graph = ccn.graph(); CheckCastNode newccn = graph.add(new CheckCastNode(type, ccn.object, ccn.profile, ccn.forStoreCheck)); graph.replaceFixedWithFixed(ccn, newccn); - return newccn; + replaceAtUsages(newccn); + graph.removeFixed(this); } } - - if (StampTool.isObjectAlwaysNull(object())) { - return object(); - } - if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { - ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); - if (exactType != null && !exactType.equals(type)) { - // Propagate more precise type information to usages of the checkcast. - tool.assumptions().recordConcreteSubtype(type, exactType); - return graph().add(new CheckCastNode(exactType, object, profile, forStoreCheck)); - } - } - - return this; } public ValueNode object() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -20,6 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +//JaCoCo Exclude package com.oracle.graal.nodes.java; import java.lang.reflect.*; @@ -57,7 +58,8 @@ if (isAlive() && elementType.isConstant()) { ResolvedJavaType javaType = tool.getConstantReflection().asJavaType(elementType.asConstant()); if (javaType != null && !javaType.equals(tool.getMetaAccess().lookupJavaType(void.class))) { - NewArrayNode newArray = graph().add(new NewArrayNode(javaType, length(), fillContents())); + ValueNode length = length(); + NewArrayNode newArray = graph().add(new NewArrayNode(javaType, length.isAlive() ? length : graph().addOrUniqueWithInputs(length), fillContents())); List snapshot = inputs().snapshot(); graph().replaceFixedWithFixed(this, newArray); for (Node input : snapshot) { @@ -72,4 +74,12 @@ public static Object newArray(Class componentType, int length) { return Array.newInstance(componentType, length); } + + @NodeIntrinsic + private static native Object newArray(Class componentType, int length, @ConstantNodeParameter boolean fillContents); + + public static Object newUninitializedArray(Class componentType, int length) { + return newArray(componentType, length, false); + } + } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -42,7 +42,7 @@ if (clazz.isConstant()) { ResolvedJavaType type = tool.getConstantReflection().asJavaType(clazz.asConstant()); if (type != null && type.isInitialized()) { - return graph().add(new NewInstanceNode(type, fillContents())); + return new NewInstanceNode(type, fillContents()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,7 +33,7 @@ * known at compile time. This is used, for instance, to intrinsify {@link Class#isInstance(Object)} * . */ -public final class InstanceOfDynamicNode extends LogicNode implements Canonicalizable, Lowerable { +public final class InstanceOfDynamicNode extends LogicNode implements Canonicalizable.Binary, Lowerable { @Input private ValueNode object; @Input private ValueNode mirror; @@ -56,16 +55,14 @@ tool.getLowerer().lower(this, tool); } - @Override - public Node canonical(CanonicalizerTool tool) { - assert object() != null : this; - if (mirror().isConstant()) { - ResolvedJavaType t = tool.getConstantReflection().asJavaType(mirror().asConstant()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forMirror) { + if (forMirror.isConstant()) { + ResolvedJavaType t = tool.getConstantReflection().asJavaType(forMirror.asConstant()); if (t != null) { if (t.isPrimitive()) { - return LogicConstantNode.contradiction(graph()); + return LogicConstantNode.contradiction(); } else { - return graph().unique(new InstanceOfNode(t, object(), null)); + return new InstanceOfNode(t, forObject, null); } } } @@ -79,4 +76,12 @@ public ValueNode mirror() { return mirror; } + + public ValueNode getX() { + return object; + } + + public ValueNode getY() { + return mirror; + } } diff -r 51f392557124 -r 5f01f7c48d40 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 Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -23,9 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -34,7 +32,7 @@ /** * The {@code InstanceOfNode} represents an instanceof test. */ -public class InstanceOfNode extends UnaryOpLogicNode implements Canonicalizable, Lowerable, Virtualizable { +public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable { private final ResolvedJavaType type; private JavaTypeProfile profile; @@ -58,40 +56,14 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - switch (evaluate(object())) { - case FALSE: - return LogicConstantNode.contradiction(graph()); - case TRUE: - return LogicConstantNode.tautology(graph()); - case UNKNOWN: - Stamp stamp = object().stamp(); - if (stamp instanceof ObjectStamp) { - ObjectStamp objectStamp = (ObjectStamp) stamp; - ResolvedJavaType stampType = objectStamp.type(); - if (stampType != null && type().isAssignableFrom(stampType)) { - if (!objectStamp.nonNull()) { - // the instanceof matches if the object is non-null, so return true - // depending on the null-ness. - IsNullNode isNull = graph().unique(new IsNullNode(object())); - return graph().unique(new LogicNegationNode(isNull)); - } - } - } - return this; - } - return this; - } - - @Override - public TriState evaluate(ValueNode forObject) { - Stamp stamp = forObject.stamp(); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + Stamp stamp = forValue.stamp(); if (!(stamp instanceof ObjectStamp)) { - return TriState.UNKNOWN; + return this; } ObjectStamp objectStamp = (ObjectStamp) stamp; if (objectStamp.alwaysNull()) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } ResolvedJavaType stampType = objectStamp.type(); @@ -100,25 +72,32 @@ if (subType) { if (objectStamp.nonNull()) { // the instanceOf matches, so return true - return TriState.TRUE; + return LogicConstantNode.tautology(); } } else { if (objectStamp.isExactType()) { // since this type check failed for an exact type we know that it can never // succeed at run time. we also don't care about null values, since they will // also make the check fail. - return TriState.FALSE; + return LogicConstantNode.contradiction(); } else { boolean superType = stampType.isAssignableFrom(type()); if (!superType && !stampType.isInterface() && !type().isInterface()) { - return TriState.FALSE; + return LogicConstantNode.contradiction(); } // since the subtype comparison was only performed on a declared type we don't // really know if it might be true at run time... } } } - return TriState.UNKNOWN; + if (stampType != null && type().isAssignableFrom(stampType)) { + if (!objectStamp.nonNull()) { + // the instanceof matches if the object is non-null, so return true + // depending on the null-ness. + return new LogicNegationNode(new IsNullNode(forValue)); + } + } + return this; } /** @@ -138,7 +117,7 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object()); + State state = tool.getObjectState(getValue()); if (state != null) { tool.replaceWithValue(LogicConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph())); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -37,7 +37,7 @@ * The {@code LoadFieldNode} represents a read of a static or instance field. */ @NodeInfo(nameTemplate = "LoadField#{p#field/s}") -public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, VirtualizableRoot { +public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary, VirtualizableRoot { /** * Creates a new LoadFieldNode instance. @@ -49,6 +49,10 @@ super(createStamp(field), object, field); } + public ValueNode getValue() { + return object(); + } + private static Stamp createStamp(ResolvedJavaField field) { Kind kind = field.getKind(); if (kind == Kind.Object && field.getType() instanceof ResolvedJavaType) { @@ -58,24 +62,23 @@ } } - @Override - public Node canonical(CanonicalizerTool tool) { - if (usages().isEmpty() && !isVolatile() && (isStatic() || StampTool.isObjectNonNull(object().stamp()))) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) { + if (usages().isEmpty() && !isVolatile() && (isStatic() || StampTool.isObjectNonNull(forObject.stamp()))) { return null; } MetaAccessProvider metaAccess = tool.getMetaAccess(); if (tool.canonicalizeReads() && metaAccess != null) { - ConstantNode constant = asConstant(metaAccess); + ConstantNode constant = asConstant(metaAccess, forObject); if (constant != null) { return constant; } - PhiNode phi = asPhi(metaAccess); + PhiNode phi = asPhi(metaAccess, forObject); if (phi != null) { return phi; } } - if (!isStatic() && object().isNullConstant()) { - return graph().add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.NullCheckException)); + if (!isStatic() && forObject.isNullConstant()) { + return new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.NullCheckException); } return this; } @@ -83,22 +86,22 @@ /** * Gets a constant value for this load if possible. */ - public ConstantNode asConstant(MetaAccessProvider metaAccess) { + public ConstantNode asConstant(MetaAccessProvider metaAccess, ValueNode forObject) { Constant constant = null; if (isStatic()) { constant = field().readConstantValue(null); - } else if (object().isConstant() && !object().isNullConstant()) { - constant = field().readConstantValue(object().asConstant()); + } else if (forObject.isConstant() && !forObject.isNullConstant()) { + constant = field().readConstantValue(forObject.asConstant()); } if (constant != null) { - return ConstantNode.forConstant(constant, metaAccess, graph()); + return ConstantNode.forConstant(constant, metaAccess); } return null; } - private PhiNode asPhi(MetaAccessProvider metaAccess) { - if (!isStatic() && field.isFinal() && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(isNotA(ConstantNode.class)).isEmpty()) { - PhiNode phi = (PhiNode) object(); + private PhiNode asPhi(MetaAccessProvider metaAccess, ValueNode forObject) { + if (!isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) { + PhiNode phi = (PhiNode) forObject; Constant[] constants = new Constant[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) { Constant constantValue = field().readConstantValue(phi.valueAt(i).asConstant()); @@ -107,11 +110,11 @@ } constants[i] = constantValue; } - PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(stamp(), phi.merge())); + ConstantNode[] constantNodes = new ConstantNode[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) { - newPhi.addInput(ConstantNode.forConstant(constants[i], metaAccess, graph())); + constantNodes[i] = ConstantNode.forConstant(constants[i], metaAccess); } - return newPhi; + return new ValuePhiNode(stamp(), phi.merge(), constantNodes); } return null; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -141,9 +141,12 @@ ValueNode receiver = receiver(); ResolvedJavaType type = StampTool.typeOrNull(receiver); if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) { - // either the holder class is exact, or the receiver object has an exact type + /* + * either the holder class is exact, or the receiver object has an exact type, or + * it's an array type + */ ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod, invoke().getContextType()); - if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver))) { + if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { invokeKind = InvokeKind.Special; targetMethod = resolvedMethod; return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -39,7 +39,7 @@ /** * Constructs a new NewArrayNode. - * + * * @param elementType the the type of the elements of the newly created array (not the type of * the array itself). * @param length the node that produces the length for this allocation. @@ -49,9 +49,16 @@ super(StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents); } + @NodeIntrinsic + static private native Object newArray(@ConstantNodeParameter Class elementType, int length, @ConstantNodeParameter boolean fillContents); + + public static Object newUninitializedArray(Class elementType, int length) { + return newArray(elementType, length, false); + } + /** * Gets the element type of the array. - * + * * @return the element type of the array */ public ResolvedJavaType elementType() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -35,33 +35,33 @@ * This node is used to perform the finalizer registration at the end of the java.lang.Object * constructor. */ -public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter { +public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable.Unary, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter { @Input(InputType.State) private FrameState deoptState; - @Input private ValueNode object; + @Input private ValueNode value; - public ValueNode object() { - return object; + public RegisterFinalizerNode(ValueNode value) { + super(StampFactory.forVoid()); + this.value = value; } - public RegisterFinalizerNode(ValueNode object) { - super(StampFactory.forVoid()); - this.object = object; + public ValueNode getValue() { + return value; } @Override public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(REGISTER_FINALIZER); - gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(object())); + gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(getValue())); } @Override - public Node canonical(CanonicalizerTool tool) { - if (!(object.stamp() instanceof ObjectStamp)) { + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (!(forValue.stamp() instanceof ObjectStamp)) { return this; } - ObjectStamp stamp = (ObjectStamp) object.stamp(); + ObjectStamp stamp = (ObjectStamp) forValue.stamp(); boolean needsCheck = true; if (stamp.isExactType()) { @@ -84,7 +84,7 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object); + State state = tool.getObjectState(getValue()); if (state != null && !state.getVirtualObject().type().hasFinalizer()) { tool.delete(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -68,6 +68,12 @@ this.value = value; } + public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) { + super(StampFactory.forVoid(), object, field); + this.value = value; + this.stateAfter = stateAfter; + } + @Override public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object()); diff -r 51f392557124 -r 5f01f7c48d40 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 Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -121,8 +121,8 @@ tool.addToWorkList(blockSuccessor(survivingEdge)); graph().removeSplit(this, blockSuccessor(survivingEdge)); } - if (value() instanceof LoadHubNode && ((LoadHubNode) value()).object().stamp() instanceof ObjectStamp) { - ObjectStamp stamp = (ObjectStamp) ((LoadHubNode) value()).object().stamp(); + if (value() instanceof LoadHubNode && ((LoadHubNode) value()).getValue().stamp() instanceof ObjectStamp) { + ObjectStamp stamp = (ObjectStamp) ((LoadHubNode) value()).getValue().stamp(); if (stamp.type() != null) { int validKeys = 0; for (int i = 0; i < keyCount(); i++) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Mon Jun 30 12:02:19 2014 +0200 @@ -68,13 +68,5 @@ Value[] visitInvokeArguments(CallingConvention cc, Collection arguments); - Variable newVariable(Kind kind); - - void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); - - void emitBitCount(Variable result, Value operand); - - void emitBitScanForward(Variable result, Value operand); - void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Jun 30 12:02:19 2014 +0200 @@ -114,25 +114,20 @@ public static Stamp rem(IntegerStamp stamp1, IntegerStamp stamp2) { assert stamp1.getBits() == stamp2.getBits(); - long magnitude; // the maximum absolute value of the result + // zero is always possible + long lowerBound = Math.min(stamp1.lowerBound(), 0); + long upperBound = Math.max(stamp1.upperBound(), 0); + + long magnitude; // the maximum absolute value of the result, derived from stamp2 if (stamp2.lowerBound() == IntegerStamp.defaultMinValue(stamp2.getBits())) { // Math.abs(...) - 1 does not work in this case magnitude = IntegerStamp.defaultMaxValue(stamp2.getBits()); } else { magnitude = Math.max(Math.abs(stamp2.lowerBound()), Math.abs(stamp2.upperBound())) - 1; } - long lowerBound = Math.max(stamp1.lowerBound(), -magnitude); - if (stamp1.upperBound() > magnitude) { - // if the result can wrap around at the upper bound, it can reach any value between 0 - // and magnitude - lowerBound = Math.min(lowerBound, 0); - } - long upperBound = Math.min(stamp1.upperBound(), magnitude); - if (stamp1.lowerBound() < -magnitude) { - // if the result can wrap around at the lower bound, it can reach any value between - // -magnitude and 0 - upperBound = Math.max(upperBound, 0); - } + lowerBound = Math.max(lowerBound, -magnitude); + upperBound = Math.min(upperBound, magnitude); + return StampFactory.forInteger(stamp1.getBits(), lowerBound, upperBound); } @@ -200,7 +195,7 @@ return add(stamp1, (IntegerStamp) StampTool.negate(stamp2)); } - private static Stamp stampForMask(int bits, long downMask, long upMask) { + public static Stamp stampForMask(int bits, long downMask, long upMask) { long lowerBound; long upperBound; if (((upMask >>> (bits - 1)) & 1) == 0) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Jun 30 12:02:19 2014 +0200 @@ -94,13 +94,13 @@ } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not a loop anymore if (tool != null) { - merge.phis().forEach(phi -> phi.usages().forEach(tool::addToWorkList)); + merge.phis().forEach(phi -> tool.addToWorkList(phi.usages())); } graph.reduceDegenerateLoopBegin((LoopBeginNode) merge); } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore if (tool != null) { - merge.phis().forEach(phi -> phi.usages().forEach(tool::addToWorkList)); + merge.phis().forEach(phi -> tool.addToWorkList(phi.usages())); } graph.reduceTrivialMerge(merge); } @@ -181,6 +181,9 @@ } public static void checkRedundantProxy(ProxyNode vpn) { + if (vpn.isDeleted()) { + return; + } BeginNode proxyPoint = vpn.proxyPoint(); if (proxyPoint instanceof LoopExitNode) { LoopExitNode exit = (LoopExitNode) proxyPoint; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -146,6 +146,6 @@ } public ValueNode length() { - return ConstantNode.forInt(length, graph()); + return ConstantNode.forInt(length); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java Mon Jun 30 12:02:19 2014 +0200 @@ -42,11 +42,13 @@ this.option = option; this.declaringClass = declaringClass; this.fieldName = fieldName; + assert !type.isPrimitive() : "must used boxed type instead of " + type; option.setDescriptor(this); } /** - * Gets the type of values stored in the option. + * Gets the type of values stored in the option. This will be the boxed type for a primitive + * option. */ public Class getType() { return type; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -27,8 +27,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; -import com.oracle.graal.graph.Graph.NodeChangedListener; +import com.oracle.graal.graph.Graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -64,6 +63,10 @@ this.customCanonicalizer = customCanonicalizer; } + public boolean getCanonicalizeReads() { + return canonicalizeReads; + } + @Override protected void run(StructuredGraph graph, PhaseContext context) { new Instance(context, canonicalizeReads, customCanonicalizer).run(graph); @@ -150,22 +153,26 @@ } private void processWorkSet(StructuredGraph graph) { - NodeChangedListener nodeChangedListener = new NodeChangedListener() { + NodeEventListener listener = new NodeEventListener() { - @Override - public void nodeChanged(Node node) { + public void nodeAdded(Node node) { + workList.add(node); + } + + public void inputChanged(Node node) { workList.add(node); } - }; - graph.trackInputChange(nodeChangedListener); - graph.trackUsagesDroppedZero(nodeChangedListener); + + public void usagesDroppedToZero(Node node) { + workList.add(node); + } - for (Node n : workList) { - processNode(n); + }; + try (NodeEventScope nes = graph.trackNodeEvents(listener)) { + for (Node n : workList) { + processNode(n); + } } - - graph.stopTrackingInputChange(); - graph.stopTrackingUsagesDroppedZero(); } private void processNode(Node node) { @@ -177,7 +184,6 @@ return; } StructuredGraph graph = (StructuredGraph) node.graph(); - Mark mark = graph.getMark(); if (!GraphUtil.tryKillUnused(node)) { if (!tryCanonicalize(node, nodeClass)) { if (node instanceof ValueNode) { @@ -196,10 +202,6 @@ } } } - - for (Node newNode : graph.getNewNodes(mark)) { - workList.add(newNode); - } } } @@ -227,12 +229,35 @@ return result; } + private static AutoCloseable getCanonicalizeableContractAssertion(Node node) { + boolean needsAssertion = false; + assert (needsAssertion = true) == true; + if (needsAssertion) { + Mark mark = node.graph().getMark(); + return () -> { + assert mark.equals(node.graph().getMark()) : "new node created while canonicalizing " + node.getClass().getSimpleName() + " " + node + ": " + + node.graph().getNewNodes(mark).snapshot(); + }; + } else { + return new AutoCloseable() { + public void close() throws Exception { + // nothing to do + } + }; + } + } + public boolean baseTryCanonicalize(final Node node, NodeClass nodeClass) { if (nodeClass.isCanonicalizable()) { METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); try (Scope s = Debug.scope("CanonicalizeNode", node)) { - Node canonical = node.canonical(tool); - return performReplacement(node, canonical); + Node canonical; + try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) { + canonical = ((Canonicalizable) node).canonical(tool); + } + if (performReplacement(node, canonical)) { + return true; + } } catch (Throwable e) { throw Debug.handle(e); } @@ -246,8 +271,9 @@ } catch (Throwable e) { throw Debug.handle(e); } + return node.isDeleted(); } - return node.isDeleted(); + return false; } // @formatter:off @@ -266,17 +292,23 @@ // -------------------------------------------- // X: must not happen (checked with assertions) // @formatter:on - private boolean performReplacement(final Node node, Node canonical) { - if (canonical == node) { + private boolean performReplacement(final Node node, Node newCanonical) { + if (newCanonical == node) { Debug.log("Canonicalizer: work on %1s", node); return false; } else { + Node canonical = newCanonical; Debug.log("Canonicalizer: replacing %1s with %1s", node, canonical); METRIC_CANONICALIZED_NODES.increment(); StructuredGraph graph = (StructuredGraph) node.graph(); + if (canonical != null && !canonical.isAlive()) { + assert !canonical.isDeleted(); + canonical = graph.addOrUniqueWithInputs(canonical); + } if (node instanceof FloatingNode) { if (canonical == null) { // case 1 + node.replaceAtUsages(null); graph.removeFloating((FloatingNode) node); } else { // case 2 @@ -301,6 +333,7 @@ tool.addToWorkList(fixedWithNext.next()); if (canonical == null) { // case 3 + node.replaceAtUsages(null); graph.removeFixed(fixedWithNext); } else if (canonical instanceof FloatingNode) { // case 4 @@ -376,6 +409,10 @@ workList.add(node); } + public void addToWorkList(Iterable nodes) { + workList.addAll(nodes); + } + @Override public void removeIfUnused(Node node) { GraphUtil.tryKillUnused(node); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,7 @@ @Override protected void run(StructuredGraph graph) { for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.class)) { - graph.replaceFloating(proxy, proxy.getObject()); + graph.replaceFloating(proxy, proxy.getValue()); } assert graph.getNodes(TypeProfileProxyNode.class).count() == 0; } diff -r 51f392557124 -r 5f01f7c48d40 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 Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -373,16 +373,16 @@ if (isTrue && condition instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) condition; - ValueNode object = instanceOf.object(); + ValueNode object = instanceOf.getValue(); state.addNullness(false, object); state.addType(instanceOf.type(), object); } else if (condition instanceof IsNullNode) { IsNullNode nullCheck = (IsNullNode) condition; - state.addNullness(isTrue, nullCheck.object()); + state.addNullness(isTrue, nullCheck.getValue()); } else if (condition instanceof ObjectEqualsNode) { ObjectEqualsNode equals = (ObjectEqualsNode) condition; - ValueNode x = equals.x(); - ValueNode y = equals.y(); + ValueNode x = equals.getX(); + ValueNode y = equals.getY(); if (isTrue) { if (state.isNull(x) && !state.isNull(y)) { metricObjectEqualsRegistered.increment(); @@ -438,8 +438,8 @@ } } if (type != null) { - state.addNullness(false, loadHub.object()); - state.addType(type, loadHub.object()); + state.addNullness(false, loadHub.getValue()); + state.addType(type, loadHub.getValue()); } } } @@ -452,16 +452,16 @@ return null; } IntegerBelowThanNode below = (IntegerBelowThanNode) guard.condition(); - if (below.x().getKind() == Kind.Int && below.x().isConstant() && !below.y().isConstant()) { - Stamp stamp = StampTool.unsignedCompare(below.x().stamp(), below.y().stamp()); + if (below.getX().getKind() == Kind.Int && below.getX().isConstant() && !below.getY().isConstant()) { + Stamp stamp = StampTool.unsignedCompare(below.getX().stamp(), below.getY().stamp()); if (stamp != null) { - return new GuardedStamp(below.y(), stamp, guard); + return new GuardedStamp(below.getY(), stamp, guard); } } - if (below.y().getKind() == Kind.Int && below.y().isConstant() && !below.x().isConstant()) { - Stamp stamp = StampTool.unsignedCompare(below.x().stamp(), below.y().stamp()); + if (below.getY().getKind() == Kind.Int && below.getY().isConstant() && !below.getX().isConstant()) { + Stamp stamp = StampTool.unsignedCompare(below.getX().stamp(), below.getY().stamp()); if (stamp != null) { - return new GuardedStamp(below.x(), stamp, guard); + return new GuardedStamp(below.getX(), stamp, guard); } } } @@ -522,13 +522,13 @@ GuardNode existingGuard = null; if (guard.condition() instanceof IntegerBelowThanNode) { IntegerBelowThanNode below = (IntegerBelowThanNode) guard.condition(); - IntegerStamp xStamp = (IntegerStamp) below.x().stamp(); - IntegerStamp yStamp = (IntegerStamp) below.y().stamp(); - GuardedStamp cstamp = state.valueConstraints.get(below.x()); + IntegerStamp xStamp = (IntegerStamp) below.getX().stamp(); + IntegerStamp yStamp = (IntegerStamp) below.getY().stamp(); + GuardedStamp cstamp = state.valueConstraints.get(below.getX()); if (cstamp != null) { xStamp = (IntegerStamp) cstamp.getStamp(); } else { - cstamp = state.valueConstraints.get(below.y()); + cstamp = state.valueConstraints.get(below.getY()); if (cstamp != null) { yStamp = (IntegerStamp) cstamp.getStamp(); } @@ -552,10 +552,10 @@ } } else if (guard.condition() instanceof IntegerEqualsNode && guard.negated()) { IntegerEqualsNode equals = (IntegerEqualsNode) guard.condition(); - GuardedStamp cstamp = state.valueConstraints.get(equals.y()); - if (cstamp != null && equals.x().isConstant()) { + GuardedStamp cstamp = state.valueConstraints.get(equals.getY()); + if (cstamp != null && equals.getX().isConstant()) { IntegerStamp stamp = (IntegerStamp) cstamp.getStamp(); - if (!stamp.contains(equals.x().asConstant().asLong())) { + if (!stamp.contains(equals.getX().asConstant().asLong())) { // x != n is true if n is outside the range of the stamp existingGuard = cstamp.getGuard(); Debug.log("existing guard %s %1s proves !%1s", existingGuard, existingGuard.condition(), guard.condition()); @@ -620,7 +620,7 @@ } else { if (condition instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) condition; - ValueNode object = instanceOf.object(); + ValueNode object = instanceOf.getValue(); if (state.isNull(object)) { metricInstanceOfRemoved.increment(); return falseValue; @@ -633,7 +633,7 @@ } } else if (condition instanceof IsNullNode) { IsNullNode isNull = (IsNullNode) condition; - ValueNode object = isNull.object(); + ValueNode object = isNull.getValue(); if (state.isNull(object)) { metricNullCheckRemoved.increment(); return trueValue; @@ -643,8 +643,8 @@ } } else if (condition instanceof ObjectEqualsNode) { ObjectEqualsNode equals = (ObjectEqualsNode) condition; - ValueNode x = equals.x(); - ValueNode y = equals.y(); + ValueNode x = equals.getX(); + ValueNode y = equals.getY(); if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) { metricObjectEqualsRemoved.increment(); return falseValue; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -71,11 +71,11 @@ CompareNode compare = (CompareNode) fixedGuard.condition(); List mergePredecessors = merge.cfgPredecessors().snapshot(); - Constant[] xs = IfNode.constantValues(compare.x(), merge, true); + Constant[] xs = IfNode.constantValues(compare.getX(), merge, true); if (xs == null) { continue; } - Constant[] ys = IfNode.constantValues(compare.y(), merge, true); + Constant[] ys = IfNode.constantValues(compare.getY(), merge, true); if (ys == null) { continue; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,7 +33,7 @@ private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved"); @Override - protected void run(StructuredGraph graph) { + public void run(StructuredGraph graph) { NodeFlood flood = graph.createNodeFlood(); flood.add(graph.start()); diff -r 51f392557124 -r 5f01f7c48d40 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 Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -42,7 +42,7 @@ CREATE_FLOATING_READS } - public static class MemoryMapImpl extends MemoryMapNode { + public static class MemoryMapImpl implements MemoryMap { private final Map lastMemorySnapshot; @@ -74,33 +74,13 @@ } } - public boolean isEmpty() { - if (lastMemorySnapshot.size() == 0) { - return true; - } - if (lastMemorySnapshot.size() == 1) { - if (lastMemorySnapshot.get(ANY_LOCATION) instanceof StartNode) { - return true; - } - } - return false; - } - @Override - public Set getLocations() { + public Collection getLocations() { return lastMemorySnapshot.keySet(); } - @Override - public boolean replaceLastLocationAccess(MemoryNode oldNode, MemoryNode newNode) { - boolean replaced = false; - for (Map.Entry entry : lastMemorySnapshot.entrySet()) { - if (entry.getValue() == oldNode) { - entry.setValue(newNode); - replaced = true; - } - } - return replaced; + public Map getMap() { + return lastMemorySnapshot; } } @@ -125,11 +105,11 @@ } } - public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List states) { + public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List states) { MemoryMapImpl newState = new MemoryMapImpl(); Set keys = new HashSet<>(); - for (MemoryMapNode other : states) { + for (MemoryMap other : states) { keys.addAll(other.getLocations()); } assert !keys.contains(FINAL_LOCATION); @@ -138,7 +118,7 @@ int mergedStatesCount = 0; boolean isPhi = false; MemoryNode merged = null; - for (MemoryMapNode state : states) { + for (MemoryMap state : states) { MemoryNode last = state.getLastLocationAccess(key); if (isPhi) { merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last)); @@ -243,7 +223,7 @@ assert MemoryCheckpoint.TypeAssertion.correctType(node) : node; if (execmode == ExecutionMode.ANALYSIS_ONLY && node instanceof ReturnNode) { - ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapImpl(state))); + ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapNode(state.lastMemorySnapshot))); } return state; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -117,7 +117,7 @@ private void processGuard(Node node) { GuardNode guard = (GuardNode) node; if (guard.negated() && guard.condition() instanceof IsNullNode && (guard.getSpeculation() == null || guard.getSpeculation().equals(Constant.NULL_OBJECT))) { - ValueNode obj = ((IsNullNode) guard.condition()).object(); + ValueNode obj = ((IsNullNode) guard.condition()).getValue(); nullGuarded.put(obj, guard); } } @@ -158,7 +158,7 @@ StructuredGraph graph = guard.graph(); BeginNode fastPath = graph.add(new BeginNode()); @SuppressWarnings("deprecation") - DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation())); + DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation(), null)); BeginNode deoptBranch = BeginNode.begin(deopt); BeginNode trueSuccessor; BeginNode falseSuccessor; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.phases.common; -import com.oracle.graal.graph.Graph.Mark; +import com.oracle.graal.graph.Graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.util.*; @@ -47,19 +47,13 @@ @Override protected void run(StructuredGraph graph, C context) { - Mark newNodesMark = graph.getMark(); - - HashSetNodeChangeListener listener = new HashSetNodeChangeListener(); - graph.trackInputChange(listener); - graph.trackUsagesDroppedZero(listener); + HashSetNodeEventListener listener = new HashSetNodeEventListener(); + try (NodeEventScope nes = graph.trackNodeEvents(listener)) { + super.run(graph, context); + } - super.run(graph, context); - - graph.stopTrackingInputChange(); - graph.stopTrackingUsagesDroppedZero(); - - if (graph.getMark() != newNodesMark || !listener.getChangedNodes().isEmpty()) { - canonicalizer.applyIncremental(graph, context, listener.getChangedNodes(), newNodesMark, false); + if (!listener.getNodes().isEmpty()) { + canonicalizer.applyIncremental(graph, context, listener.getNodes(), null, false); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; @@ -43,24 +44,22 @@ @Override protected void run(StructuredGraph graph, PhaseContext context) { ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(context.getMetaAccess()); - HashSetNodeChangeListener listener = new HashSetNodeChangeListener(); + HashSetNodeEventListener listener = new HashSetNodeEventListener.ExceptForAddedNodes(); int count = 0; while (true) { - graph.trackInputChange(listener); - graph.trackUsagesDroppedZero(listener); - eliminate.apply(graph); - graph.stopTrackingInputChange(); - graph.stopTrackingUsagesDroppedZero(); - if (listener.getChangedNodes().isEmpty()) { + try (NodeEventScope nes = graph.trackNodeEvents(listener)) { + eliminate.apply(graph); + } + if (listener.getNodes().isEmpty()) { break; } for (Node node : graph.getNodes()) { if (node instanceof Simplifiable) { - listener.getChangedNodes().add(node); + listener.getNodes().add(node); } } - canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); - listener.getChangedNodes().clear(); + canonicalizer.applyIncremental(graph, context, listener.getNodes()); + listener.getNodes().clear(); if (++count > MAX_ITERATIONS) { throw new BailoutException("Number of iterations in ConditionalEliminationPhase phase exceeds " + MAX_ITERATIONS); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -157,7 +157,7 @@ IsNullNode isNullNode = (IsNullNode) condition; BeginNode nonTrappingContinuation = ifNode.falseSuccessor(); BeginNode trappingContinuation = ifNode.trueSuccessor(); - NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.object())); + NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.getValue())); trappingNullCheck.setStateBefore(deopt.stateBefore()); deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java Mon Jun 30 12:02:19 2014 +0200 @@ -22,18 +22,16 @@ */ package com.oracle.graal.phases.common.cfs; -import com.oracle.graal.api.code.Assumptions; +import java.util.*; + +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.Debug; -import com.oracle.graal.debug.DebugMetric; -import com.oracle.graal.graph.Node; -import com.oracle.graal.graph.spi.CanonicalizerTool; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.compiler.common.type.ObjectStamp; -import com.oracle.graal.phases.graph.SinglePassNodeIterator; -import com.oracle.graal.phases.tiers.PhaseContext; - -import java.util.ArrayList; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.tiers.*; /** *

@@ -140,9 +138,8 @@ * One of the promises of * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} * is that a "maximally reduced" node is returned. That is achieved in part by leveraging - * {@link com.oracle.graal.graph.Node#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)}. - * Doing so, in turn, requires this subclass of - * {@link com.oracle.graal.graph.spi.CanonicalizerTool}. + * {@link Canonicalizable#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)}. Doing so, in + * turn, requires this subclass of {@link com.oracle.graal.graph.spi.CanonicalizerTool}. *

*/ public final class Tool implements CanonicalizerTool { @@ -168,16 +165,6 @@ return context.getConstantReflection(); } - /** - * Postpone - * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} - * until {@link FlowSensitiveReduction#finished()} for the reasons covered there. - */ - @Override - public void removeIfUnused(Node node) { - // GraphUtil.tryKillUnused(node); - } - @Override public boolean canonicalizeReads() { return false; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java Mon Jun 30 12:02:19 2014 +0200 @@ -45,7 +45,7 @@ private static CastCheckExtractor extractCastCheckInfo(LogicNode x, LogicNode y) { if (x instanceof IsNullNode) { IsNullNode isNull = (IsNullNode) x; - ValueNode subject = isNull.object(); + ValueNode subject = isNull.getValue(); if (isInstanceOfCheckOn(y, subject)) { InstanceOfNode iOf = (InstanceOfNode) y; return new CastCheckExtractor(iOf.type(), subject); @@ -82,6 +82,6 @@ return false; } InstanceOfNode io = (InstanceOfNode) cond; - return io.object() == subject; + return io.getValue() == subject; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Mon Jun 30 12:02:19 2014 +0200 @@ -332,11 +332,20 @@ } FlowUtil.inferStampAndCheck(changed); added.add(changed); - ValueNode canon = (ValueNode) changed.canonical(tool); - // might be already in `added`, no problem adding it again. - added.add(canon); - rememberSubstitution(f, canon); - return canon; + + if (changed instanceof Canonicalizable) { + ValueNode canon = (ValueNode) ((Canonicalizable) changed).canonical(tool); + if (canon != null && !canon.isAlive()) { + assert !canon.isDeleted(); + canon = graph.addOrUniqueWithInputs(canon); + } + // might be already in `added`, no problem adding it again. + added.add(canon); + rememberSubstitution(f, canon); + return canon; + } else { + return changed; + } } /** @@ -445,7 +454,7 @@ * */ private LogicNode baseCaseInstanceOfNode(InstanceOfNode instanceOf) { - ValueNode scrutinee = GraphUtil.unproxify(instanceOf.object()); + ValueNode scrutinee = GraphUtil.unproxify(instanceOf.getValue()); if (!FlowUtil.hasLegalObjectStamp(scrutinee)) { return instanceOf; } @@ -470,7 +479,7 @@ * */ private FloatingNode baseCaseIsNullNode(IsNullNode isNu) { - ValueNode object = isNu.object(); + ValueNode object = isNu.getValue(); if (!FlowUtil.hasLegalObjectStamp(object)) { return isNu; } @@ -489,11 +498,11 @@ * otherwise the unmodified argument. */ private LogicNode baseCaseObjectEqualsNode(ObjectEqualsNode equals) { - if (!FlowUtil.hasLegalObjectStamp(equals.x()) || !FlowUtil.hasLegalObjectStamp(equals.y())) { + if (!FlowUtil.hasLegalObjectStamp(equals.getX()) || !FlowUtil.hasLegalObjectStamp(equals.getY())) { return equals; } - ValueNode x = GraphUtil.unproxify(equals.x()); - ValueNode y = GraphUtil.unproxify(equals.y()); + ValueNode x = GraphUtil.unproxify(equals.getX()); + ValueNode y = GraphUtil.unproxify(equals.getY()); if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) { metricObjectEqualsRemoved.increment(); return falseConstant; @@ -629,7 +638,7 @@ } TypeProfileProxyNode profile = (TypeProfileProxyNode) object; ObjectStamp outgoinStamp = (ObjectStamp) profile.stamp(); - ObjectStamp payloadStamp = (ObjectStamp) profile.getObject().stamp(); + ObjectStamp payloadStamp = (ObjectStamp) profile.getValue().stamp(); if (payloadStamp.nonNull() && !outgoinStamp.nonNull()) { profile.setStamp(FlowUtil.asNonNullStamp(outgoinStamp)); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon Jun 30 12:02:19 2014 +0200 @@ -234,7 +234,7 @@ return; } // it's unwarranted to assume loadHub.object() to be non-null - state.trackCC(loadHub.object(), type, begin); + state.trackCC(loadHub.getValue(), type, begin); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon Jun 30 12:02:19 2014 +0200 @@ -359,7 +359,7 @@ return false; } IsNullNode isNull = (IsNullNode) cond; - return isNull.object() == subject; + return isNull.getValue() == subject; } /** diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; @@ -41,42 +42,28 @@ this.canonicalizer = canonicalizer; } - public static class CountingListener extends HashSetNodeChangeListener { - - public int count; - - @Override - public void nodeChanged(Node node) { - super.nodeChanged(node); - } - - } - // private Histogram histogram = new Histogram("FSR-"); @Override protected void run(StructuredGraph graph, PhaseContext context) { FlowSensitiveReductionPhase eliminate = new FlowSensitiveReductionPhase(context.getMetaAccess()); - CountingListener listener = new CountingListener(); + HashSetNodeEventListener listener = new HashSetNodeEventListener.ExceptForAddedNodes(); int count = 1; while (true) { - listener.count = count; - graph.trackInputChange(listener); - graph.trackUsagesDroppedZero(listener); - eliminate.apply(graph, context); - graph.stopTrackingInputChange(); - graph.stopTrackingUsagesDroppedZero(); - if (listener.getChangedNodes().isEmpty()) { + try (NodeEventScope nes = graph.trackNodeEvents(listener)) { + eliminate.apply(graph, context); + } + if (listener.getNodes().isEmpty()) { // histogram.tick(count); break; } for (Node node : graph.getNodes()) { if (node instanceof Simplifiable) { - listener.getChangedNodes().add(node); + listener.getNodes().add(node); } } - canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); - listener.getChangedNodes().clear(); + canonicalizer.applyIncremental(graph, context, listener.getNodes()); + listener.getNodes().clear(); if (++count > MAX_ITERATIONS) { // System.out.println("Bailing out IterativeFlowSensitiveReductionPhase for graph: " // + graph); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java Mon Jun 30 12:02:19 2014 +0200 @@ -647,7 +647,7 @@ } if (condition instanceof LogicNegationNode) { - addFact(!isTrue, ((LogicNegationNode) condition).getInput(), anchor); + addFact(!isTrue, ((LogicNegationNode) condition).getValue(), anchor); } else if (condition instanceof ShortCircuitOrNode) { /* * We can register the conditions being or-ed as long as the anchor is a fixed node, @@ -677,7 +677,7 @@ addFactInstanceOf(isTrue, (InstanceOfNode) condition, anchor); } else if (condition instanceof IsNullNode) { IsNullNode nullCheck = (IsNullNode) condition; - addNullness(isTrue, nullCheck.object(), anchor); + addNullness(isTrue, nullCheck.getValue(), anchor); } else if (condition instanceof ObjectEqualsNode) { addFactObjectEqualsNode(isTrue, (ObjectEqualsNode) condition, anchor); } else { @@ -692,7 +692,7 @@ * */ private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) { - ValueNode object = instanceOf.object(); + ValueNode object = instanceOf.getValue(); if (isTrue) { if (knownNotToPassInstanceOf(object, instanceOf.type())) { impossiblePath(); @@ -710,15 +710,15 @@ } private void addFactObjectEqualsNode(boolean isTrue, ObjectEqualsNode equals, GuardingNode anchor) { - if (isDependencyTainted(equals.x(), anchor)) { + if (isDependencyTainted(equals.getX(), anchor)) { return; } - if (isDependencyTainted(equals.y(), anchor)) { + if (isDependencyTainted(equals.getY(), anchor)) { return; } assert anchor instanceof FixedNode; - ValueNode x = GraphUtil.unproxify(equals.x()); - ValueNode y = GraphUtil.unproxify(equals.y()); + ValueNode x = GraphUtil.unproxify(equals.getX()); + ValueNode y = GraphUtil.unproxify(equals.getY()); if (isTrue) { if (isNull(x) && isNonNull(y)) { impossiblePath(); @@ -730,12 +730,12 @@ } if (isNull(x) || isNull(y)) { metricObjectEqualsRegistered.increment(); - addNullness(true, equals.x(), anchor); - addNullness(true, equals.y(), anchor); + addNullness(true, equals.getX(), anchor); + addNullness(true, equals.getY(), anchor); } else if (isNonNull(x) || isNonNull(y)) { metricObjectEqualsRegistered.increment(); - addNullness(false, equals.x(), anchor); - addNullness(false, equals.y(), anchor); + addNullness(false, equals.getX(), anchor); + addNullness(false, equals.getY(), anchor); } Witness wx = typeInfo(x); Witness wy = typeInfo(y); @@ -748,8 +748,8 @@ if (best != null) { assert !best.isInterface(); // type tightening is enough, nullness already taken care of - trackCC(equals.x(), best, anchor); - trackCC(equals.y(), best, anchor); + trackCC(equals.getX(), best, anchor); + trackCC(equals.getY(), best, anchor); } } else if (wx == null) { typeRefinements.put(x, new Witness(wy)); @@ -759,10 +759,10 @@ } else { if (isNull(x) && !isNonNull(y)) { metricObjectEqualsRegistered.increment(); - addNullness(false, equals.y(), anchor); + addNullness(false, equals.getY(), anchor); } else if (!isNonNull(x) && isNull(y)) { metricObjectEqualsRegistered.increment(); - addNullness(false, equals.x(), anchor); + addNullness(false, equals.getX(), anchor); } } } @@ -911,20 +911,20 @@ private Evidence outcomeIsNullNode(boolean isTrue, IsNullNode isNullNode) { if (isTrue) { // grab an anchor attesting nullness - final GuardingNode replacement = nonTrivialNullAnchor(isNullNode.object()); + final GuardingNode replacement = nonTrivialNullAnchor(isNullNode.getValue()); if (replacement != null) { return new Evidence(replacement); } - if (isNonNull(isNullNode.object())) { + if (isNonNull(isNullNode.getValue())) { return Evidence.COUNTEREXAMPLE; } } else { // grab an anchor attesting non-nullness - final Witness w = typeInfo(isNullNode.object()); + final Witness w = typeInfo(isNullNode.getValue()); if (w != null && w.isNonNull()) { return new Evidence(w.guard()); } - if (isNull(isNullNode.object())) { + if (isNull(isNullNode.getValue())) { return Evidence.COUNTEREXAMPLE; } } @@ -936,9 +936,9 @@ * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)} */ private Evidence outcomeInstanceOfNode(boolean isTrue, InstanceOfNode iOf) { - final Witness w = typeInfo(iOf.object()); + final Witness w = typeInfo(iOf.getValue()); if (isTrue) { - if (isNull(iOf.object())) { + if (isNull(iOf.getValue())) { return Evidence.COUNTEREXAMPLE; } // grab an anchor attesting instanceof @@ -957,7 +957,7 @@ } else { // grab an anchor attesting not-instanceof // (1 of 2) attempt determining nullness - final GuardingNode nullGuard = nonTrivialNullAnchor(iOf.object()); + final GuardingNode nullGuard = nonTrivialNullAnchor(iOf.getValue()); if (nullGuard != null) { return new Evidence(nullGuard); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -29,9 +29,7 @@ import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.policy.GreedyInliningPolicy; import com.oracle.graal.phases.common.inlining.policy.InliningPolicy; -import com.oracle.graal.phases.common.inlining.walker.CallsiteHolder; import com.oracle.graal.phases.common.inlining.walker.InliningData; -import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; import com.oracle.graal.phases.tiers.*; public class InliningPhase extends AbstractInliningPhase { @@ -72,68 +70,11 @@ } /** - *

- * The space of inlining decisions is explored depth-first with the help of a stack realized by - * {@link com.oracle.graal.phases.common.inlining.walker.InliningData}. At any point in time, - * its topmost element consist of: - *

    - *
  • - * one or more {@link CallsiteHolder}s of inlining candidates, all of them corresponding to a - * single callsite (details below). For example, "exact inline" leads to a single candidate.
  • - *
  • - * the callsite (for the targets above) is tracked as a {@link MethodInvocation}. The difference - * between {@link com.oracle.graal.phases.common.inlining.walker.MethodInvocation#totalGraphs()} - * and {@link MethodInvocation#processedGraphs()} indicates the topmost {@link CallsiteHolder}s - * that might be delved-into to explore inlining opportunities.
  • - *
- *

* - *

- * The bottom-most element in the stack consists of: - *

    - *
  • - * a single {@link CallsiteHolder} (the root one, for the method on which inlining was called)
  • - *
  • - * a single {@link MethodInvocation} (the - * {@link com.oracle.graal.phases.common.inlining.walker.MethodInvocation#isRoot} one, ie the - * unknown caller of the root graph)
  • - *
- * - *

+ * This method sets in motion the inlining machinery. * - *

- * The stack grows and shrinks as choices are made among the alternatives below: - *

    - *
  1. - * not worth inlining: pop any remaining graphs not yet delved into, pop the current invocation. - *
  2. - *
  3. - * process next invoke: delve into one of the callsites hosted in the current candidate graph, - * determine whether any inlining should be performed in it
  4. - *
  5. - * try to inline: move past the current inlining candidate (remove it from the topmost element). - * If that was the last one then try to inline the callsite that is (still) in the topmost - * element of {@link com.oracle.graal.phases.common.inlining.walker.InliningData}, and then - * remove such callsite.
  6. - *
- *

- * - *

- * Some facts about the alternatives above: - *

    - *
  • - * the first step amounts to backtracking, the 2nd one to delving, and the 3rd one also involves - * backtracking (however after may-be inlining).
  • - *
  • - * the choice of abandon-and-backtrack or delve-into is depends on - * {@link InliningPolicy#isWorthInlining} and {@link InliningPolicy#continueInlining}.
  • - *
  • - * the 3rd choice is picked when both of the previous ones aren't picked
  • - *
  • - * as part of trying-to-inline, {@link InliningPolicy#isWorthInlining} again sees use, but - * that's another story.
  • - *
- *

+ * @see InliningData + * @see InliningData#moveForward() * */ @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Mon Jun 30 12:02:19 2014 +0200 @@ -223,8 +223,10 @@ * @param inlineGraph the graph that the invoke will be replaced with * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, * false if no such check is required + * @param canonicalizedNodes if non-null then append to this list any nodes which should be + * canonicalized after inlining */ - public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { + public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, List canonicalizedNodes) { final NodeInputList parameters = invoke.callTarget().arguments(); FixedNode invokeNode = invoke.asNode(); StructuredGraph graph = invokeNode.graph(); @@ -289,7 +291,6 @@ stateAtExceptionEdge = obj.stateAfter(); UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); obj.replaceAtUsages(unwindDuplicate.exception()); - unwindDuplicate.clearInputs(); Node n = obj.next(); obj.setNext(null); unwindDuplicate.replaceAndDelete(n); @@ -332,7 +333,6 @@ ReturnNode returnNode = (ReturnNode) duplicates.get(returnNodes.get(0)); Node returnValue = returnNode.result(); invokeNode.replaceAtUsages(returnValue); - returnNode.clearInputs(); returnNode.replaceAndDelete(n); } else { ArrayList returnDuplicates = new ArrayList<>(returnNodes.size()); @@ -341,7 +341,7 @@ } MergeNode merge = graph.add(new MergeNode()); merge.setStateAfter(stateAfter); - ValueNode returnValue = mergeReturns(merge, returnDuplicates); + ValueNode returnValue = mergeReturns(merge, returnDuplicates, canonicalizedNodes); invokeNode.replaceAtUsages(returnValue); merge.setNext(n); } @@ -440,7 +440,7 @@ } } - public static ValueNode mergeReturns(MergeNode merge, List returnNodes) { + public static ValueNode mergeReturns(MergeNode merge, List returnNodes, List canonicalizedNodes) { PhiNode returnValuePhi = null; for (ReturnNode returnNode : returnNodes) { @@ -451,10 +451,12 @@ if (returnNode.result() != null) { if (returnValuePhi == null) { returnValuePhi = merge.graph().addWithoutUnique(new ValuePhiNode(returnNode.result().stamp().unrestricted(), merge)); + if (canonicalizedNodes != null) { + canonicalizedNodes.add(returnValuePhi); + } } returnValuePhi.addInput(returnNode.result()); } - returnNode.clearInputs(); returnNode.replaceAndDelete(endNode); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,10 +28,12 @@ import com.oracle.graal.api.meta.ResolvedJavaMethod; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; +import com.oracle.graal.phases.tiers.HighTierContext; public abstract class AbstractInlineInfo implements InlineInfo { @@ -52,22 +54,22 @@ } protected static Collection inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, Assumptions assumptions, boolean receiverNullCheck) { - Collection parameterUsages = new ArrayList<>(); + List canonicalizeNodes = new ArrayList<>(); if (inlineable instanceof InlineableGraph) { StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph(); - Map duplicateMap = InliningUtil.inline(invoke, calleeGraph, receiverNullCheck); - getInlinedParameterUsages(parameterUsages, calleeGraph, duplicateMap); + Map duplicateMap = InliningUtil.inline(invoke, calleeGraph, receiverNullCheck, canonicalizeNodes); + getInlinedParameterUsages(canonicalizeNodes, calleeGraph, duplicateMap); } else { assert inlineable instanceof InlineableMacroNode; Class macroNodeClass = ((InlineableMacroNode) inlineable).getMacroNodeClass(); FixedWithNextNode macroNode = InliningUtil.inlineMacroNode(invoke, concrete, macroNodeClass); - parameterUsages.add(macroNode); + canonicalizeNodes.add(macroNode); } InliningUtil.InlinedBytecodes.add(concrete.getCodeSize()); assumptions.recordMethodContents(concrete); - return parameterUsages; + return canonicalizeNodes; } public static void getInlinedParameterUsages(Collection parameterUsages, StructuredGraph calleeGraph, Map duplicateMap) { @@ -80,4 +82,22 @@ } } } + + public final void populateInlinableElements(HighTierContext context, Assumptions calleeAssumptions, CanonicalizerPhase canonicalizer) { + for (int i = 0; i < numberOfMethods(); i++) { + Inlineable elem = Inlineable.getInlineableElement(methodAt(i), invoke, context.replaceAssumptions(calleeAssumptions), canonicalizer); + setInlinableElement(i, elem); + } + } + + public final int determineNodeCount() { + int nodes = 0; + for (int i = 0; i < numberOfMethods(); i++) { + Inlineable elem = inlineableElementAt(i); + if (elem != null) { + nodes += elem.getNodeCount(); + } + } + return nodes; + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,9 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; +import com.oracle.graal.phases.tiers.HighTierContext; import com.oracle.graal.phases.util.Providers; /** @@ -82,4 +84,8 @@ void tryToDevirtualizeInvoke(MetaAccessProvider metaAccess, Assumptions assumptions); boolean shouldInline(); + + void populateInlinableElements(HighTierContext context, Assumptions calleeAssumptions, CanonicalizerPhase canonicalizer); + + int determineNodeCount(); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Mon Jun 30 12:02:19 2014 +0200 @@ -222,9 +222,7 @@ ArrayList replacementNodes = new ArrayList<>(); - Collection parameterUsages = new ArrayList<>(); - - // do the actual inlining for every invoke + // prepare the anchors for the invokes for (int i = 0; i < numberOfMethods; i++) { BeginNode node = successors[i]; Invoke invokeForInlining = (Invoke) node.next(); @@ -241,8 +239,7 @@ GuardedValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, node, commonType, receiver, exact); invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver); - parameterUsages.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), assumptions, false)); - + assert !anchoredReceiver.isDeleted() : anchoredReceiver; replacementNodes.add(anchoredReceiver); } if (shouldFallbackToInvoke()) { @@ -274,7 +271,17 @@ TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, phaseContext, canonicalizer); } } - return parameterUsages; + + Collection canonicalizeNodes = new ArrayList<>(); + // do the actual inlining for every invoke + for (int i = 0; i < numberOfMethods; i++) { + Invoke invokeForInlining = (Invoke) successors[i].next(); + canonicalizeNodes.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), assumptions, false)); + } + if (returnValuePhi != null) { + canonicalizeNodes.add(returnValuePhi); + } + return canonicalizeNodes; } private int getTypeCount(int concreteMethodIndex) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,6 +32,8 @@ public interface Inlineable { static Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context, CanonicalizerPhase canonicalizer) { + assert method != null; + assert invoke != null; Class macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method); if (macroNodeClass != null) { return new InlineableMacroNode(macroNodeClass); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Mon Jun 30 12:02:19 2014 +0200 @@ -32,11 +32,26 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.DeadCodeEliminationPhase; +import com.oracle.graal.phases.common.cfs.FlowUtil; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.tiers.HighTierContext; import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer; +/** + *

+ * Represents a feasible concrete target for inlining, whose graph has been copied already and thus + * can be modified without affecting the original (usually cached) version. + *

+ * + *

+ * Instances of this class don't make sense in isolation but as part of an + * {@link com.oracle.graal.phases.common.inlining.info.InlineInfo InlineInfo}. + *

+ * + * @see com.oracle.graal.phases.common.inlining.walker.InliningData#moveForward() + * @see com.oracle.graal.phases.common.inlining.walker.CallsiteHolderExplorable + */ public class InlineableGraph implements Inlineable { private final StructuredGraph graph; @@ -73,6 +88,7 @@ try (Debug.Scope s = Debug.scope("InlineGraph", graph)) { ArrayList parameterUsages = replaceParamsWithMoreInformativeArguments(invoke, context); + parameterUsages = rewireParamsForDuplicateArguments(invoke, parameterUsages); if (parameterUsages != null && OptCanonicalizer.getValue()) { assert !parameterUsages.isEmpty() : "The caller didn't have more information about arguments after all"; canonicalizer.applyIncremental(graph, context, parameterUsages); @@ -89,16 +105,62 @@ } } - private static boolean isArgMoreInformativeThanParam(ValueNode arg, ParameterNode param) { - if (arg.isConstant()) { - return true; - } else { - Stamp joinedStamp = param.stamp().join(arg.stamp()); - if (joinedStamp != null && !joinedStamp.equals(param.stamp())) { - return true; + /** + * This method detects duplicate arguments (therefore corresponding to different + * {@link ParameterNode}s) and updates the graph to make all of their usages refer to the first + * one of them. + * + * @return a (possibly updated) list of nodes for incremental canonicalization. + */ + private ArrayList rewireParamsForDuplicateArguments(Invoke invoke, ArrayList parameterUsages0) { + ArrayList parameterUsages = parameterUsages0; + ArrayList params = new ArrayList<>(); + List originalArgs = invoke.callTarget().arguments(); + List argsInEffect = new ArrayList<>(); + // some param-nodes might have been deleted by replaceParamsWithMoreInformativeArguments() + // that's why we obtain an up-to-date list + for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + if (!FlowUtil.lacksUsages(p)) { + params.add(p); + argsInEffect.add(originalArgs.get(p.index())); } } - return false; + // argsInEffect and params paired by position + assert params.size() == argsInEffect.size(); + int argIdx = 0; + for (ValueNode arg : argsInEffect) { + int firstOccurrrence = argsInEffect.indexOf(arg); + assert firstOccurrrence >= 0; + if (firstOccurrrence < argIdx) { + ParameterNode survivingParam = params.get(firstOccurrrence); + assert survivingParam.isAlive(); + ParameterNode duplicateParam = params.get(argIdx); + assert duplicateParam.isAlive(); + assert survivingParam != duplicateParam; + assert !isArgMoreInformativeThanParam(arg, survivingParam); + parameterUsages = trackParameterUsages(duplicateParam, parameterUsages); + // replaceFloating() deletes the duplicate param, unlike replaceAtUsages() + graph.replaceFloating(duplicateParam, survivingParam); + } + argIdx++; + } + return parameterUsages; + } + + private static boolean isArgMoreInformativeThanParam(ValueNode arg, ParameterNode param) { + return arg.isConstant() || canStampBeImproved(arg, param); + } + + private static boolean canStampBeImproved(ValueNode arg, ParameterNode param) { + return improvedStamp(arg, param) != null; + } + + private static Stamp improvedStamp(ValueNode arg, ParameterNode param) { + Stamp joinedStamp = param.stamp().join(arg.stamp()); + if (joinedStamp == null || joinedStamp.equals(param.stamp())) { + return null; + } + return joinedStamp; } /** @@ -140,9 +202,9 @@ graph.replaceFloating(param, ConstantNode.forConstant(constant, context.getMetaAccess(), graph)); // param-node gone, leaving a gap in the sequence given by param.index() } else { - Stamp joinedStamp = param.stamp().join(arg.stamp()); - if (joinedStamp != null && !joinedStamp.equals(param.stamp())) { - param.setStamp(joinedStamp); + Stamp impro = improvedStamp(arg, param); + if (impro != null) { + param.setStamp(impro); parameterUsages = trackParameterUsages(param, parameterUsages); } else { assert !isArgMoreInformativeThanParam(arg, param); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/AbstractInliningPolicy.java Mon Jun 30 12:02:19 2014 +0200 @@ -100,17 +100,6 @@ return size; } - protected static int determineNodeCount(InlineInfo info) { - int nodes = 0; - for (int i = 0; i < info.numberOfMethods(); i++) { - Inlineable elem = info.inlineableElementAt(i); - if (elem != null) { - nodes += elem.getNodeCount(); - } - } - return nodes; - } - protected static double determineInvokeProbability(ToDoubleFunction probabilities, InlineInfo info) { double invokeProbability = 0; for (int i = 0; i < info.numberOfMethods(); i++) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; import java.util.Map; import java.util.function.ToDoubleFunction; @@ -54,8 +55,12 @@ } @Override - public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, InlineInfo info, int inliningDepth, double probability, double relevance, - boolean fullyProcessed) { + public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { + + final InlineInfo info = invocation.callee(); + final double probability = invocation.probability(); + final double relevance = invocation.relevance(); + if (InlineEverything.getValue()) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); return true; @@ -72,7 +77,7 @@ } double inliningBonus = getInliningBonus(info); - int nodes = determineNodeCount(info); + int nodes = info.determineNodeCount(); int lowLevelGraphSize = previousLowLevelGraphSize(info); if (SmallCompiledLowLevelGraphSize.getValue() > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue() * inliningBonus) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.nodes.FixedNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.spi.Replacements; -import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; import java.util.function.ToDoubleFunction; @@ -41,8 +41,7 @@ return true; } - public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, InlineInfo info, int inliningDepth, double probability, double relevance, - boolean fullyProcessed) { + public boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) { return true; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InliningPolicy.java Mon Jun 30 12:02:19 2014 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.nodes.FixedNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.spi.Replacements; -import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; import java.util.function.ToDoubleFunction; @@ -33,5 +33,5 @@ boolean continueInlining(StructuredGraph graph); - boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, InlineInfo info, int inliningDepth, double probability, double relevance, boolean fullyProcessed); + boolean isWorthInlining(ToDoubleFunction probabilities, Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java Mon Jun 30 12:02:19 2014 +0200 @@ -22,105 +22,31 @@ */ package com.oracle.graal.phases.common.inlining.walker; -import com.oracle.graal.api.meta.MetaUtil; import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.FixedNode; -import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.StructuredGraph; -import com.oracle.graal.phases.graph.FixedNodeProbabilityCache; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.function.ToDoubleFunction; - -import static com.oracle.graal.compiler.common.GraalOptions.CapInheritedRelevance; /** * Information about a graph that will potentially be inlined. This includes tracking the * invocations in graph that will subject to inlining themselves. */ -public class CallsiteHolder { - - private final StructuredGraph graph; - private final LinkedList remainingInvokes; - private final double probability; - private final double relevance; - - private final ToDoubleFunction probabilities; - private final ComputeInliningRelevance computeInliningRelevance; - - public CallsiteHolder(StructuredGraph graph, double probability, double relevance) { - this.graph = graph; - this.probability = probability; - this.relevance = relevance; - if (graph == null) { - remainingInvokes = new LinkedList<>(); - probabilities = null; - computeInliningRelevance = null; - } else { - remainingInvokes = new InliningIterator(graph).apply(); - assert remainingInvokes.size() == count(graph.getInvokes()); - if (remainingInvokes.isEmpty()) { - probabilities = null; - computeInliningRelevance = null; - } else { - probabilities = new FixedNodeProbabilityCache(); - computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); - computeProbabilities(); - } - } - } - - private static int count(Iterable invokes) { - int count = 0; - Iterator iterator = invokes.iterator(); - while (iterator.hasNext()) { - iterator.next(); - count++; - } - return count; - } +public abstract class CallsiteHolder { /** * Gets the method associated with the {@linkplain #graph() graph} represented by this object. */ - public ResolvedJavaMethod method() { - return graph == null ? null : graph.method(); - } + public abstract ResolvedJavaMethod method(); - public boolean hasRemainingInvokes() { - return !remainingInvokes.isEmpty(); - } + /** + * The stack realized by {@link InliningData} grows upon {@link InliningData#moveForward()} + * deciding to explore (depth-first) a callsite of the graph associated to this + * {@link CallsiteHolder}. The list of not-yet-considered callsites is managed by + * {@link CallsiteHolderExplorable}, and this method reports whether any such candidates remain. + */ + public abstract boolean hasRemainingInvokes(); /** * The graph about which this object contains inlining information. */ - public StructuredGraph graph() { - return graph; - } - - public Invoke popInvoke() { - return remainingInvokes.removeFirst(); - } - - public void pushInvoke(Invoke invoke) { - remainingInvokes.push(invoke); - } + public abstract StructuredGraph graph(); - public void computeProbabilities() { - computeInliningRelevance.compute(); - } - - public double invokeProbability(Invoke invoke) { - return probability * probabilities.applyAsDouble(invoke.asNode()); - } - - public double invokeRelevance(Invoke invoke) { - return Math.min(CapInheritedRelevance.getValue(), relevance) * computeInliningRelevance.getRelevance(invoke); - } - - @Override - public String toString() { - return (graph != null ? MetaUtil.format("%H.%n(%p)", method()) : "") + remainingInvokes; - } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderDummy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderDummy.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,61 @@ +/* + * 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.phases.common.inlining.walker; + +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.nodes.StructuredGraph; + +import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; + +/** + * A {@link CallsiteHolder} that stands for an {@link InlineableMacroNode} in the stack realized by + * {@link InliningData}. + */ +public final class CallsiteHolderDummy extends CallsiteHolder { + + public static final CallsiteHolderDummy DUMMY_CALLSITE_HOLDER = new CallsiteHolderDummy(); + + private CallsiteHolderDummy() { + // no instances other than the singleton + } + + @Override + public ResolvedJavaMethod method() { + return null; + } + + @Override + public boolean hasRemainingInvokes() { + return false; + } + + @Override + public StructuredGraph graph() { + return null; + } + + @Override + public String toString() { + return ""; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,214 @@ +/* + * 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.phases.common.inlining.walker; + +import com.oracle.graal.api.meta.MetaUtil; +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.graph.FixedNodeProbabilityCache; + +import java.util.*; +import java.util.function.ToDoubleFunction; + +import static com.oracle.graal.compiler.common.GraalOptions.CapInheritedRelevance; + +/** + *

+ * A {@link CallsiteHolder} whose graph has been copied already and thus can be modified without + * affecting the original (usually cached) version. + *

+ * + *

+ * An instance of this class is derived from an + * {@link com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph InlineableGraph} and + * contains a subset of the information there: just the {@link Invoke} nodes from it. Such nodes are + * candidates for depth-first search of further inlining opportunities (thus the adjective + * "explorable" given to this class) + *

+ * + * @see InliningData#moveForward() + */ +public final class CallsiteHolderExplorable extends CallsiteHolder { + + /** + * Graph in which inlining may be performed at one or more of the callsites containined in + * {@link #remainingInvokes} + */ + private final StructuredGraph graph; + + private final LinkedList remainingInvokes; + private final double probability; + private final double relevance; + + /** + * @see #getFixedParams() + */ + private final Set fixedParams; + + private final ToDoubleFunction probabilities; + private final ComputeInliningRelevance computeInliningRelevance; + + public CallsiteHolderExplorable(StructuredGraph graph, double probability, double relevance, BitSet freshlyInstantiatedArguments) { + assert graph != null; + this.graph = graph; + this.probability = probability; + this.relevance = relevance; + this.fixedParams = fixedParamsAt(freshlyInstantiatedArguments); + remainingInvokes = new InliningIterator(graph).apply(); + if (remainingInvokes.isEmpty()) { + probabilities = null; + computeInliningRelevance = null; + } else { + probabilities = new FixedNodeProbabilityCache(); + computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); + computeProbabilities(); + } + assert repOK(); + } + + /** + * @see #getFixedParams() + */ + @SuppressWarnings("unchecked") + private Set fixedParamsAt(BitSet freshlyInstantiatedArguments) { + if (freshlyInstantiatedArguments == null || freshlyInstantiatedArguments.isEmpty()) { + return Collections.EMPTY_SET; + } + Set result = new HashSet<>(); + for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + if (freshlyInstantiatedArguments.get(p.index())) { + result.add(p); + } + } + return result; + } + + /** + *

+ * Parameters for which the callsite targeting {@link #graph()} provides "fixed" arguments. That + * callsite isn't referenced by this instance. Instead, it belongs to the graph of the caller of + * this {@link CallsiteHolderExplorable} + *

+ * + *

+ * Constant arguments don't contribute to fixed-params: those params have been removed already, + * see {@link com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph}. + *

+ * + *

+ * Instead, fixed-params are those receiving freshly instantiated arguments (possibly + * instantiated several levels up in the call-hierarchy) + *

+ * */ + public Set getFixedParams() { + return fixedParams; + } + + public boolean repOK() { + for (Invoke invoke : remainingInvokes) { + if (!invoke.asNode().isAlive() || !containsInvoke(invoke)) { + assert false; + return false; + } + if (!allArgsNonNull(invoke)) { + assert false; + return false; + } + } + for (ParameterNode fixedParam : fixedParams) { + if (!containsParam(fixedParam)) { + assert false; + return false; + } + } + return true; + } + + @Override + public ResolvedJavaMethod method() { + return graph == null ? null : graph.method(); + } + + @Override + public boolean hasRemainingInvokes() { + return !remainingInvokes.isEmpty(); + } + + @Override + public StructuredGraph graph() { + return graph; + } + + public Invoke popInvoke() { + return remainingInvokes.removeFirst(); + } + + public void pushInvoke(Invoke invoke) { + remainingInvokes.push(invoke); + } + + public static boolean allArgsNonNull(Invoke invoke) { + for (ValueNode arg : invoke.callTarget().arguments()) { + if (arg == null) { + assert false; + return false; + } + } + return true; + } + + public boolean containsInvoke(Invoke invoke) { + for (Invoke i : graph().getInvokes()) { + if (i == invoke) { + return true; + } + } + return false; + } + + public boolean containsParam(ParameterNode param) { + for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + if (p == param) { + return true; + } + } + return false; + } + + public void computeProbabilities() { + computeInliningRelevance.compute(); + } + + public double invokeProbability(Invoke invoke) { + return probability * probabilities.applyAsDouble(invoke.asNode()); + } + + public double invokeRelevance(Invoke invoke) { + return Math.min(CapInheritedRelevance.getValue(), relevance) * computeInliningRelevance.getRelevance(invoke); + } + + @Override + public String toString() { + return (graph != null ? MetaUtil.format("%H.%n(%p)", method()) : "") + remainingInvokes; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Mon Jun 30 12:02:19 2014 +0200 @@ -34,7 +34,10 @@ import com.oracle.graal.graph.Graph; import com.oracle.graal.graph.Node; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.AbstractNewObjectNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; +import com.oracle.graal.nodes.virtual.AllocatedObjectNode; +import com.oracle.graal.nodes.virtual.VirtualObjectNode; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.inlining.InliningUtil; @@ -51,14 +54,37 @@ import java.util.function.ToDoubleFunction; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.phases.common.inlining.walker.CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER; /** - * Holds the data for building the callee graphs recursively: graphs and invocations (each - * invocation can have multiple graphs). + *

+ * The space of inlining decisions is explored depth-first with the help of a stack realized by + * {@link InliningData}. At any point in time, the topmost element of that stack consists of: + *

    + *
  • the callsite under consideration is tracked as a {@link MethodInvocation}.
  • + *
  • + * one or more {@link CallsiteHolder}s, all of them associated to the callsite above. Why more than + * one? Depending on the type-profile for the receiver more than one concrete method may be feasible + * target.
  • + *
+ *

+ * + *

+ * The bottom element in the stack consists of: + *

    + *
  • + * a single {@link MethodInvocation} (the + * {@link com.oracle.graal.phases.common.inlining.walker.MethodInvocation#isRoot root} one, ie the + * unknown caller of the root graph)
  • + *
  • + * a single {@link CallsiteHolder} (the root one, for the method on which inlining was called)
  • + *
+ *

+ * + * @see #moveForward() */ public class InliningData { - private static final CallsiteHolder DUMMY_CALLSITE_HOLDER = new CallsiteHolder(null, 1.0, 1.0); // Metrics private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); private static final DebugMetric metricInliningRuns = Debug.metric("InliningRuns"); @@ -87,8 +113,12 @@ this.maxGraphs = 1; Assumptions rootAssumptions = context.getAssumptions(); - invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0)); - pushGraph(rootGraph, 1.0, 1.0); + invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0, null)); + graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0, null)); + } + + public static boolean isFreshInstantiation(ValueNode arg) { + return (arg instanceof AbstractNewObjectNode) || (arg instanceof AllocatedObjectNode) || (arg instanceof VirtualObjectNode); } private String checkTargetConditionsHelper(ResolvedJavaMethod method) { @@ -336,7 +366,7 @@ return new ExactInlineInfo(invoke, targetMethod); } - private void doInline(CallsiteHolder callerCallsiteHolder, MethodInvocation calleeInvocation, Assumptions callerAssumptions) { + private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation, Assumptions callerAssumptions) { StructuredGraph callerGraph = callerCallsiteHolder.graph(); InlineInfo calleeInfo = calleeInvocation.callee(); try { @@ -376,15 +406,27 @@ } /** + * + * This method attempts: + *
    + *
  1. + * to inline at the callsite given by calleeInvocation, where that callsite belongs + * to the {@link CallsiteHolderExplorable} at the top of the {@link #graphQueue} maintained in + * this class.
  2. + *
  3. + * otherwise, to devirtualize the callsite in question.
  4. + *
+ * * @return true iff inlining was actually performed */ - private boolean tryToInline(CallsiteHolder callerCallsiteHolder, MethodInvocation calleeInvocation, MethodInvocation parentInvocation, int inliningDepth) { + private boolean tryToInline(MethodInvocation calleeInvocation, MethodInvocation parentInvocation, int inliningDepth) { + CallsiteHolderExplorable callerCallsiteHolder = (CallsiteHolderExplorable) currentGraph(); InlineInfo calleeInfo = calleeInvocation.callee(); - assert iterContains(callerCallsiteHolder.graph().getInvokes(), calleeInfo.invoke()); + assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke()); Assumptions callerAssumptions = parentInvocation.assumptions(); metricInliningConsidered.increment(); - if (inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), calleeInfo, inliningDepth, calleeInvocation.probability(), calleeInvocation.relevance(), true)) { + if (inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), calleeInvocation, inliningDepth, true)) { doInline(callerCallsiteHolder, calleeInvocation, callerAssumptions); return true; } @@ -396,62 +438,94 @@ return false; } - private static boolean iterContains(Iterable in, T elem) { - for (T i : in) { - if (i == elem) { - return true; - } - } - return false; - } - /** - * Process the next invoke and enqueue all its graphs for processing. + * This method picks one of the callsites belonging to the current + * {@link CallsiteHolderExplorable}. Provided the callsite qualifies to be analyzed for + * inlining, this method prepares a new stack top in {@link InliningData} for such callsite, + * which comprises: + *
    + *
  • preparing a summary of feasible targets, ie preparing an {@link InlineInfo}
  • + *
  • based on it, preparing the stack top proper which consists of:
  • + *
      + *
    • one {@link MethodInvocation}
    • + *
    • a {@link CallsiteHolder} for each feasible target
    • + *
    + *
+ * + *

+ * The thus prepared "stack top" is needed by {@link #moveForward()} to explore the space of + * inlining decisions (each decision one of: backtracking, delving, inlining). + *

+ * + *

+ * The {@link InlineInfo} used to get things rolling is kept around in the + * {@link MethodInvocation}, it will be needed in case of inlining, see + * {@link InlineInfo#inline(Providers, Assumptions)} + *

*/ private void processNextInvoke() { - CallsiteHolder callsiteHolder = currentGraph(); + CallsiteHolderExplorable callsiteHolder = (CallsiteHolderExplorable) currentGraph(); Invoke invoke = callsiteHolder.popInvoke(); MethodInvocation callerInvocation = currentInvocation(); Assumptions parentAssumptions = callerInvocation.assumptions(); - Assumptions calleeAssumptions = new Assumptions(parentAssumptions.useOptimisticAssumptions()); - InlineInfo info = populateInlineInfo(invoke, parentAssumptions, calleeAssumptions); + InlineInfo info = getInlineInfo(invoke, parentAssumptions); if (info != null) { + Assumptions calleeAssumptions = new Assumptions(parentAssumptions.useOptimisticAssumptions()); + info.populateInlinableElements(context, calleeAssumptions, canonicalizer); double invokeProbability = callsiteHolder.invokeProbability(invoke); double invokeRelevance = callsiteHolder.invokeRelevance(invoke); - MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance); + MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance, freshlyInstantiatedArguments(invoke, callsiteHolder.getFixedParams())); pushInvocationAndGraphs(methodInvocation); } } - private InlineInfo populateInlineInfo(Invoke invoke, Assumptions parentAssumptions, Assumptions calleeAssumptions) { - InlineInfo info = getInlineInfo(invoke, parentAssumptions); - if (info == null) { - return null; + /** + *

+ * A freshly instantiated argument is either: + *

    + *
  • an {@link InliningData#isFreshInstantiation(com.oracle.graal.nodes.ValueNode)}
  • + *
  • a fixed-param, ie a {@link ParameterNode} receiving a freshly instantiated argument
  • + *
+ *

+ * + * @return the positions of freshly instantiated arguments in the argument list of the + * invoke, or null if no such positions exist. + */ + public static BitSet freshlyInstantiatedArguments(Invoke invoke, Set fixedParams) { + assert fixedParams != null; + assert paramsAndInvokeAreInSameGraph(invoke, fixedParams); + BitSet result = null; + int argIdx = 0; + for (ValueNode arg : invoke.callTarget().arguments()) { + assert arg != null; + if (isFreshInstantiation(arg) || fixedParams.contains(arg)) { + if (result == null) { + result = new BitSet(); + } + result.set(argIdx); + } + argIdx++; } - for (int i = 0; i < info.numberOfMethods(); i++) { - Inlineable elem = Inlineable.getInlineableElement(info.methodAt(i), info.invoke(), context.replaceAssumptions(calleeAssumptions), canonicalizer); - info.setInlinableElement(i, elem); + return result; + } + + private static boolean paramsAndInvokeAreInSameGraph(Invoke invoke, Set fixedParams) { + if (fixedParams.isEmpty()) { + return true; } - return info; + for (ParameterNode p : fixedParams) { + if (p.graph() != invoke.asNode().graph()) { + return false; + } + } + return true; } public int graphCount() { return graphQueue.size(); } - private void pushGraph(StructuredGraph graph, double probability, double relevance) { - assert graph != null; - assert !contains(graph); - graphQueue.push(new CallsiteHolder(graph, probability, relevance)); - assert graphQueue.size() <= maxGraphs; - } - - private void pushDummyGraph() { - graphQueue.push(DUMMY_CALLSITE_HOLDER); - assert graphQueue.size() <= maxGraphs; - } - public boolean hasUnprocessedGraphs() { return !graphQueue.isEmpty(); } @@ -498,16 +572,11 @@ InlineInfo info = methodInvocation.callee(); maxGraphs += info.numberOfMethods(); assert graphQueue.size() <= maxGraphs; - double invokeProbability = methodInvocation.probability(); - double invokeRelevance = methodInvocation.relevance(); for (int i = 0; i < info.numberOfMethods(); i++) { - Inlineable elem = info.inlineableElementAt(i); - if (elem instanceof InlineableGraph) { - pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); - } else { - assert elem instanceof InlineableMacroNode; - pushDummyGraph(); - } + CallsiteHolder ch = methodInvocation.buildCallsiteHolderForElement(i); + assert (ch == DUMMY_CALLSITE_HOLDER) || !contains(ch.graph()); + graphQueue.push(ch); + assert graphQueue.size() <= maxGraphs; } } @@ -555,6 +624,7 @@ } private boolean contains(StructuredGraph graph) { + assert graph != null; for (CallsiteHolder info : graphQueue) { if (info.graph() == graph) { return true; @@ -564,14 +634,56 @@ } /** + *

+ * The stack realized by {@link InliningData} grows and shrinks as choices are made among the + * alternatives below: + *

    + *
  1. + * not worth inlining: pop stack top, which comprises: + *
      + *
    • pop any remaining graphs not yet delved into
    • + *
    • pop the current invocation
    • + *
    + *
  2. + *
  3. + * {@link #processNextInvoke() delve} into one of the callsites hosted in the current graph, + * such callsite is explored next by {@link #moveForward()}
  4. + *
  5. + * {@link #tryToInline(MethodInvocation, MethodInvocation, int) try to inline}: move past the + * current graph (remove it from the topmost element). + *
      + *
    • + * If that was the last one then {@link #tryToInline(MethodInvocation, MethodInvocation, int) + * try to inline} the callsite under consideration (ie, the "current invocation").
    • + *
    • + * Whether inlining occurs or not, that callsite is removed from the top of {@link InliningData} + * .
    • + *
    + *
  6. + *
+ *

+ * + *

+ * Some facts about the alternatives above: + *

    + *
  • + * the first step amounts to backtracking, the 2nd one to depth-search, and the 3rd one also + * involves backtracking (however possibly after inlining).
  • + *
  • + * the choice of abandon-and-backtrack or delve-into depends on + * {@link InliningPolicy#isWorthInlining} and {@link InliningPolicy#continueInlining}.
  • + *
  • + * the 3rd choice is picked whenever none of the previous choices are made
  • + *
+ *

+ * * @return true iff inlining was actually performed */ public boolean moveForward() { final MethodInvocation currentInvocation = currentInvocation(); - final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), currentInvocation.callee(), inliningDepth(), - currentInvocation.probability(), currentInvocation.relevance(), false)); + final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(probabilities, context.getReplacements(), currentInvocation, inliningDepth(), false)); if (backtrack) { int remainingGraphs = currentInvocation.totalGraphs() - currentInvocation.processedGraphs(); assert remainingGraphs > 0; @@ -602,7 +714,7 @@ popInvocation(); final MethodInvocation parentInvoke = currentInvocation(); try (Debug.Scope s = Debug.scope("Inlining", inliningContext())) { - return tryToInline(currentGraph(), currentInvocation, parentInvoke, inliningDepth() + 1); + return tryToInline(currentInvocation, parentInvoke, inliningDepth() + 1); } catch (Throwable e) { throw Debug.handle(e); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java Mon Jun 30 12:02:19 2014 +0200 @@ -29,6 +29,7 @@ import java.util.ArrayDeque; import java.util.Deque; +import java.util.Iterator; import java.util.LinkedList; /** @@ -81,6 +82,7 @@ } } + assert invokes.size() == count(start.graph().getInvokes()); return invokes; } @@ -127,4 +129,14 @@ } return true; } + + private static int count(Iterable invokes) { + int count = 0; + Iterator iterator = invokes.iterator(); + while (iterator.hasNext()) { + iterator.next(); + count++; + } + return count; + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,7 +28,23 @@ import com.oracle.graal.nodes.CallTargetNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; +import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; +import java.util.BitSet; + +/** + *

+ * An instance of this class denotes a callsite being analyzed for inlining. + *

+ *

+ * Each element of the {@link InliningData} stack contains one such instance, the accompanying + * {@link CallsiteHolder}s in that element represent feasible targets for the callsite in question. + *

+ * + * @see InliningData#moveForward() + */ public class MethodInvocation { private final InlineInfo callee; @@ -38,11 +54,39 @@ private int processedGraphs; - public MethodInvocation(InlineInfo info, Assumptions assumptions, double probability, double relevance) { + /** + *

+ * The immutable positions of freshly instantiated arguments (ie, positions in + * callee.invoke.callTarget.arguments). + *

+ * + *

+ * A freshly instantiated argument is either: + *

    + *
  • an {@link InliningData#isFreshInstantiation(com.oracle.graal.nodes.ValueNode)}
  • + *
  • a fixed-param of the graph containing the callsite (ie, of callee.graph() + * that contains callee.invoke)
  • + *
+ *

+ * + *

+ * Given those positions, the + * {@link com.oracle.graal.phases.common.inlining.walker.CallsiteHolderExplorable} instantiated + * in {@link #buildCallsiteHolderForElement(int)} can determine which of its parameters + * are fixed. + *

+ */ + private final BitSet freshlyInstantiatedArguments; + + private final int sizeFreshArgs; + + public MethodInvocation(InlineInfo info, Assumptions assumptions, double probability, double relevance, BitSet freshlyInstantiatedArguments) { this.callee = info; this.assumptions = assumptions; this.probability = probability; this.relevance = relevance; + this.freshlyInstantiatedArguments = freshlyInstantiatedArguments; + this.sizeFreshArgs = freshlyInstantiatedArguments == null ? 0 : freshlyInstantiatedArguments.cardinality(); } public void incrementProcessedGraphs() { @@ -79,6 +123,27 @@ return callee == null; } + public BitSet getFreshlyInstantiatedArguments() { + return freshlyInstantiatedArguments; + } + + public int getSizeFreshArgs() { + return sizeFreshArgs; + } + + public CallsiteHolder buildCallsiteHolderForElement(int index) { + Inlineable elem = callee.inlineableElementAt(index); + if (elem instanceof InlineableGraph) { + InlineableGraph ig = (InlineableGraph) elem; + final double invokeProbability = probability * callee.probabilityAt(index); + final double invokeRelevance = relevance * callee.relevanceAt(index); + return new CallsiteHolderExplorable(ig.getGraph(), invokeProbability, invokeRelevance, freshlyInstantiatedArguments); + } else { + assert elem instanceof InlineableMacroNode; + return CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER; + } + } + @Override public String toString() { if (isRoot()) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/util/HashSetNodeChangeListener.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/util/HashSetNodeChangeListener.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common.util; - -import java.util.*; - -import com.oracle.graal.graph.Graph.NodeChangedListener; -import com.oracle.graal.graph.*; - -/** - * A simple {@link NodeChangedListener} implementation that accumulates the changed nodes in a - * {@link HashSet}. - */ -public class HashSetNodeChangeListener implements NodeChangedListener { - - private final Set changedNodes; - - public HashSetNodeChangeListener() { - this.changedNodes = new HashSet<>(); - } - - @Override - public void nodeChanged(Node node) { - changedNodes.add(node); - } - - public Set getChangedNodes() { - return changedNodes; - } -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/util/HashSetNodeEventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/util/HashSetNodeEventListener.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.util; + +import java.util.*; + +import com.oracle.graal.graph.Graph.NodeEventListener; +import com.oracle.graal.graph.*; + +/** + * A simple {@link NodeEventListener} implementation that accumulates event nodes in a + * {@link HashSet}. + */ +public class HashSetNodeEventListener implements NodeEventListener { + + /** + * Accumulates all node events except for {@link NodeEventListener#nodeAdded(Node) node + * additions}. + */ + public static class ExceptForAddedNodes extends HashSetNodeEventListener { + @Override + public void nodeAdded(Node node) { + } + } + + private final Set nodes; + + public HashSetNodeEventListener() { + this.nodes = new HashSet<>(); + } + + public void nodeAdded(Node node) { + nodes.add(node); + } + + public void inputChanged(Node node) { + nodes.add(node); + } + + public void usagesDroppedToZero(Node node) { + nodes.add(node); + } + + /** + * Gets the set of nodes that were communicated to this listener. + */ + public Set getNodes() { + return nodes; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -94,12 +94,15 @@ public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { try (TimerCloseable a = timer.start(); Scope s = Debug.scope(getClass(), this); Closeable c = memUseTracker.start()) { - BasePhase.this.run(graph, context); + this.run(graph, context); executionCount.increment(); inputNodesCount.add(graph.getNodeCount()); if (dumpGraph && Debug.isDumpEnabled()) { Debug.dump(graph, "After phase %s", getName()); } + if (Debug.isVerifyEnabled()) { + Debug.verify(graph, this, "After phase " + getName()); + } assert graph.verify(); } catch (Throwable t) { throw Debug.handle(t); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Mon Jun 30 12:02:19 2014 +0200 @@ -67,8 +67,8 @@ protected boolean verify(StructuredGraph graph, PhaseContext context) { for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) { // bail out if we compare an object of type klass with == or != (except null checks) - if (checkUsage(cn.x(), cn.y(), context.getMetaAccess()) && checkUsage(cn.y(), cn.x(), context.getMetaAccess())) { - throw new VerificationError("Verification of " + klass.getName() + " usage failed: Comparing " + cn.x() + " and " + cn.y() + " in " + graph.method() + + if (checkUsage(cn.getX(), cn.getY(), context.getMetaAccess()) && checkUsage(cn.getY(), cn.getX(), context.getMetaAccess())) { + throw new VerificationError("Verification of " + klass.getName() + " usage failed: Comparing " + cn.getX() + " and " + cn.getY() + " in " + graph.method() + " must use .equals() for object equality, not '==' or '!='"); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -299,6 +299,7 @@ for (Position pos : directInputPositions) { writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); + writePoolObject(nodeClass.getInputType(pos)); } Collection directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); writeShort((char) directSuccessorPositions.size()); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -532,7 +532,7 @@ } private void printInterval(Interval interval) { - out.printf("%s %s ", interval.operand, (isRegister(interval.operand) ? "fixed" : interval.kind().name())); + out.printf("%s %s ", interval.operand, (isRegister(interval.operand) ? "fixed" : interval.kind())); if (isRegister(interval.operand)) { out.printf("\"[%s|%c]\"", interval.operand, interval.operand.getKind().getTypeChar()); } else { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Mon Jun 30 12:02:19 2014 +0200 @@ -34,10 +34,17 @@ public class DebugEnvironment { + @SuppressWarnings("all") + private static boolean assertionsEnabled() { + boolean assertionsEnabled = false; + assert assertionsEnabled = true; + return assertionsEnabled; + } + public static GraalDebugConfig initialize(PrintStream log) { // Ensure Graal runtime is initialized prior to Debug being initialized as the former - // included processing command line options used by the latter. + // may include processing command line options used by the latter. Graal.getRuntime(); if (!Debug.isEnabled()) { @@ -55,7 +62,16 @@ if (DecompileAfterPhase.getValue() != null) { dumpHandlers.add(new DecompilerDebugDumpHandler()); } - GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers); + List verifyHandlers = new ArrayList<>(); + String verifyFilter = Verify.getValue(); + if (verifyFilter == null && assertionsEnabled()) { + verifyFilter = ""; + } + if (verifyFilter != null) { + verifyHandlers.add(new NoDeadCodeVerifyHandler()); + } + GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), verifyFilter, MethodFilter.getValue(), log, + dumpHandlers, verifyHandlers); Debug.setConfig(debugConfig); return debugConfig; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014, 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.printer; + +import static com.oracle.graal.printer.NoDeadCodeVerifyHandler.Options.*; + +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.options.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +/** + * Verifies that graphs have no dead code. + */ +public class NoDeadCodeVerifyHandler implements DebugVerifyHandler { + + // The options below will be removed once all phases clean up their own dead code. + + private static final int OFF = 0; + private static final int INFO = 1; + private static final int VERBOSE = 2; + private static final int FATAL = 3; + + static class Options { + // @formatter:off + @Option(help = "Run level for NoDeadCodeVerifyHandler (0 = off, 1 = info, 2 = verbose, 3 = fatal)") + public static final OptionValue NDCV = new OptionValue<>(0); + // @formatter:on + } + + private static final Map, Boolean> discovered = new ConcurrentHashMap<>(); + + public void verify(Object object, Object... context) { + if (NDCV.getValue() != OFF) { + StructuredGraph graph = extract(StructuredGraph.class, object); + BasePhase phase = extract(BasePhase.class, context); + assert phase != null : "a Phase context is required by " + getClass().getSimpleName(); + if (graph != null) { + List before = graph.getNodes().snapshot(); + new DeadCodeEliminationPhase().run(graph); + List after = graph.getNodes().snapshot(); + assert after.size() <= before.size(); + if (before.size() != after.size()) { + before.removeAll(after); + if (discovered.put(phase.getClass(), Boolean.TRUE) == null) { + String message = extract(String.class, context); + String prefix = message == null ? "" : message + ": "; + String phaseClass = phase.getClass().getName(); + GraalInternalError error = new GraalInternalError("%sfound dead nodes in %s (phase class=%s): %s", prefix, graph, phaseClass, before); + if (NDCV.getValue() == INFO) { + System.out.println(error.getMessage()); + } else if (NDCV.getValue() == VERBOSE) { + error.printStackTrace(System.out); + } else { + assert NDCV.getValue() == FATAL; + throw error; + } + } + } + } + } + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java --- a/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -197,12 +197,12 @@ } @Override - public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { - if (!(platformKind instanceof Kind)) { + public boolean canStoreValue(RegisterCategory category, PlatformKind lirKind) { + if (!(lirKind instanceof Kind)) { return false; } - Kind kind = (Kind) platformKind; + Kind kind = (Kind) lirKind; if (category == REG) { switch (kind) { case Boolean: diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Mon Jun 30 12:02:19 2014 +0200 @@ -181,8 +181,8 @@ StructuredGraph graph = convert.graph(); Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("input", convert.getInput()); - args.add("result", graph.unique(new AMD64FloatConvertNode(convert.stamp(), convert.getOp(), convert.getInput()))); + args.add("input", convert.getValue()); + args.add("result", graph.unique(new AMD64FloatConvertNode(convert.stamp(), convert.getOp(), convert.getValue()))); SnippetTemplate template = template(args); Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getOp(), graph, convert, template, args); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -36,15 +37,13 @@ * of the {@link FloatConvertNode} which, on AMD64 needs a {@link AMD64FloatConvertNode} plus some * fixup code that handles the corner cases that differ between AMD64 and Java. */ -public class AMD64FloatConvertNode extends FloatingNode implements ArithmeticLIRLowerable { +public class AMD64FloatConvertNode extends UnaryNode implements ArithmeticLIRLowerable { private final FloatConvert op; - @Input private ValueNode value; public AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) { - super(stamp); + super(stamp, value); this.op = op; - this.value = value; } public Constant evalConst(Constant... inputs) { @@ -52,7 +51,13 @@ throw GraalInternalError.shouldNotReachHere(); } + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + // nothing to do + return this; + } + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitFloatConvert(op, builder.operand(value))); + builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue()))); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java --- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -123,7 +123,7 @@ @Override public Node canonical(CanonicalizerTool tool) { if (getParameter().isConstant()) { - return ConstantNode.forPrimitive(evalConst(getParameter().asConstant()), graph()); + return ConstantNode.forPrimitive(evalConst(getParameter().asConstant())); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,237 @@ +/* + * 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.graal.replacements.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.inlining.*; +import com.oracle.graal.phases.tiers.*; + +public class BitOpNodesTest extends GraalCompilerTest { + + private static final int INT_CONSTANT_1 = 0x80100010; + private static final int INT_CONSTANT_2 = 0x00011110; + private static final int INT_CONSTANT_3 = 0x00000000; + + private static final long LONG_CONSTANT_1 = 0x8000000000100010L; + private static final long LONG_CONSTANT_2 = 0x0000000000011110L; + private static final long LONG_CONSTANT_3 = 0x0000000000000000L; + + public static long dummyField; + + /* + * Tests for BitCountNode canonicalizations. + */ + + public static int bitCountIntConstantSnippet() { + return Integer.bitCount(INT_CONSTANT_1) + Integer.bitCount(INT_CONSTANT_2) + Integer.bitCount(INT_CONSTANT_3); + } + + @Test + public void testBitCountIntConstant() { + ValueNode result = parseAndInline("bitCountIntConstantSnippet"); + Assert.assertEquals(7, result.asConstant().asInt()); + } + + public static int bitCountLongConstantSnippet() { + return Long.bitCount(LONG_CONSTANT_1) + Long.bitCount(LONG_CONSTANT_2) + Long.bitCount(LONG_CONSTANT_3); + } + + public static int bitCountIntSnippet(int v) { + return Integer.bitCount(v & 0xFFFFFF | 0xFF); + } + + @Test + public void testBitCountInt() { + ValueNode result = parseAndInline("bitCountIntSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 8, 24), result.stamp()); + } + + public static int bitCountIntEmptySnippet(int v) { + return Integer.bitCount(v & 0xFFFFFF); + } + + @Test + public void testBitCountIntEmpty() { + ValueNode result = parseAndInline("bitCountIntEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 0, 24), result.stamp()); + } + + @Test + public void testBitCountLongConstant() { + ValueNode result = parseAndInline("bitCountLongConstantSnippet"); + Assert.assertEquals(7, result.asConstant().asInt()); + } + + public static int bitCountLongSnippet(long v) { + return Long.bitCount(v & 0xFFFFFFFFFFL | 0xFFL); + } + + @Test + public void testBitCountLong() { + ValueNode result = parseAndInline("bitCountLongSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 8, 40), result.stamp()); + } + + public static int bitCountLongEmptySnippet(long v) { + return Long.bitCount(v & 0xFFFFFFFFFFL); + } + + @Test + public void testBitCountLongEmpty() { + ValueNode result = parseAndInline("bitCountLongEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 0, 40), result.stamp()); + } + + /* + * Tests for BitScanForwardNode + */ + + public static int scanForwardIntConstantSnippet() { + return Integer.numberOfTrailingZeros(INT_CONSTANT_1) + Integer.numberOfTrailingZeros(INT_CONSTANT_2) + Integer.numberOfTrailingZeros(INT_CONSTANT_3); + } + + @Test + public void testScanForwardIntConstant() { + ValueNode result = parseAndInline("scanForwardIntConstantSnippet"); + Assert.assertEquals(40, result.asConstant().asInt()); + } + + public static int scanForwardIntSnippet(int v) { + return Integer.numberOfTrailingZeros(v & 0xFFF0 | 0xFF00); + } + + @Test + public void testScanForwardInt() { + ValueNode result = parseAndInline("scanForwardIntSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 4, 8), result.stamp()); + } + + public static int scanForwardLongConstantSnippet() { + return Long.numberOfTrailingZeros(LONG_CONSTANT_1) + Long.numberOfTrailingZeros(LONG_CONSTANT_2) + Long.numberOfTrailingZeros(LONG_CONSTANT_3); + } + + @Test + public void testScanForwardLongConstant() { + ValueNode result = parseAndInline("scanForwardLongConstantSnippet"); + Assert.assertEquals(72, result.asConstant().asInt()); + } + + public static int scanForwardLongSnippet(long v) { + return Long.numberOfTrailingZeros(v & 0xFFFF000000L | 0xFF00000000L); + } + + @Test + public void testScanForwardLong() { + ValueNode result = parseAndInline("scanForwardLongSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 32), result.stamp()); + } + + public static int scanForwardLongEmptySnippet(long v) { + int result = Long.numberOfTrailingZeros(v & 0xFFFF000000L); + dummyField = result; + return result; + } + + @Test + public void testScanForwardLongEmpty() { + ValueNode result = parseAndInline("scanForwardLongEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, -1, 64), result.stamp()); + } + + /* + * Tests for BitScanReverseNode + */ + + public static int scanReverseIntConstantSnippet() { + return Integer.numberOfLeadingZeros(INT_CONSTANT_1) + Integer.numberOfLeadingZeros(INT_CONSTANT_2) + Integer.numberOfLeadingZeros(INT_CONSTANT_3); + } + + @Test + public void testScanReverseIntConstant() { + ValueNode result = parseAndInline("scanReverseIntConstantSnippet"); + Assert.assertEquals(47, result.asConstant().asInt()); + } + + public static int scanReverseIntSnippet(int v) { + return Integer.numberOfLeadingZeros(v & 0xFFF0 | 0xFF0); + } + + @Test + public void testScanReverseInt() { + ValueNode result = parseAndInline("scanReverseIntSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 16, 20), result.stamp()); + } + + public static int scanReverseLongConstantSnippet() { + return Long.numberOfLeadingZeros(LONG_CONSTANT_1) + Long.numberOfLeadingZeros(LONG_CONSTANT_2) + Long.numberOfLeadingZeros(LONG_CONSTANT_3); + } + + @Test + public void testScanReverseLongConstant() { + ValueNode result = parseAndInline("scanReverseLongConstantSnippet"); + Assert.assertEquals(111, result.asConstant().asInt()); + } + + public static int scanReverseLongSnippet(long v) { + int result = Long.numberOfLeadingZeros(v & 0xFFF0); + dummyField = result; + return result; + } + + @Test + public void testScanReverseLong() { + ValueNode result = parseAndInline("scanReverseLongSnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 48, 64), result.stamp()); + } + + public static int scanReverseLongEmptySnippet(long v) { + int result = Long.numberOfLeadingZeros(v & 0xFFFF000000L); + dummyField = result; + return result; + } + + @Test + public void testScanReverseLongEmpty() { + ValueNode result = parseAndInline("scanReverseLongEmptySnippet"); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp()); + } + + private ValueNode parseAndInline(String name) { + StructuredGraph graph = parse(name); + HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + canonicalizer.apply(graph, context); + new InliningPhase(canonicalizer).apply(graph, context); + canonicalizer.apply(graph, context); + Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); + return graph.getNodes(ReturnNode.class).first().result(); + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -50,7 +50,7 @@ protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); if (ion != null) { - InstanceOfNode ionNew = graph.unique(new InstanceOfNode(ion.type(), ion.object(), profile)); + InstanceOfNode ionNew = graph.unique(new InstanceOfNode(ion.type(), ion.getValue(), profile)); graph.replaceFloating(ion, ionNew); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -114,7 +114,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } @@ -138,7 +138,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -125,7 +125,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } @@ -154,7 +154,7 @@ SignExtendNode convert = (SignExtendNode) location.getIndex(); Assert.assertEquals(convert.getInputBits(), 32); Assert.assertEquals(convert.getResultBits(), 64); - Assert.assertEquals(graph.getParameter(1), convert.getInput()); + Assert.assertEquals(graph.getParameter(1), convert.getValue()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Mon Jun 30 12:02:19 2014 +0200 @@ -124,6 +124,7 @@ private void findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) { List constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements()); + List failureReasons = new ArrayList<>(); nextConstructor: for (ExecutableElement constructor : constructors) { int sIdx = 0; @@ -141,13 +142,16 @@ TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); while (sIdx < signature.length) { if (!isTypeCompatible(varargsType, signature[sIdx++])) { + failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, varargsType, signature[sIdx - 1])); continue nextConstructor; } } } else if (sIdx >= signature.length) { // too many arguments in intrinsic method + failureReasons.add(String.format("Too many arguments for %s", constructor)); continue nextConstructor; } else if (!isTypeCompatible(paramType, signature[sIdx++])) { + failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, paramType, signature[sIdx - 1])); continue nextConstructor; } } @@ -158,10 +162,17 @@ } // too many arguments in constructor + failureReasons.add(String.format("Not enough arguments for %s", constructor)); } // not found - env.getMessager().printMessage(Kind.ERROR, "Could not find matching constructor for node intrinsic.", intrinsicMethod, intrinsicAnnotation); + if (failureReasons.isEmpty()) { + env.getMessager().printMessage(Kind.ERROR, "Could not find matching constructor for node intrinsic.", intrinsicMethod, intrinsicAnnotation); + } else { + for (String reason : failureReasons) { + env.getMessager().printMessage(Kind.ERROR, reason, intrinsicMethod, intrinsicAnnotation); + } + } } private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java Mon Jun 30 12:02:19 2014 +0200 @@ -34,6 +34,11 @@ @MethodSubstitution public static Object newInstance(Class componentType, int length) throws NegativeArraySizeException { + // The error cases must be handled here since DynamicNewArrayNode can only deoptimize the + // caller in response to exceptions. + if (componentType == void.class) { + throw new IllegalArgumentException(); + } return DynamicNewArrayNode.newArray(GuardingPiNode.guardingNonNull(componentType), length); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.replacements; +import static com.oracle.graal.api.code.BytecodeFrame.*; + import java.util.*; import com.oracle.graal.api.code.*; @@ -129,15 +131,15 @@ FrameState frameState = stateSplit.stateAfter(); if (frameState != null) { if (stateSplit.hasSideEffect()) { - stateSplit.setStateAfter(createInvalidFrameState(node)); + setStateAfter(node.graph(), stateSplit, INVALID_FRAMESTATE_BCI, false); state = state.addSideEffect(stateSplit); } else if (currentState.invalid) { - stateSplit.setStateAfter(createInvalidFrameState(node)); + setStateAfter(node.graph(), stateSplit, INVALID_FRAMESTATE_BCI, false); } else { stateSplit.setStateAfter(null); - } - if (frameState.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(frameState); + if (frameState.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(frameState); + } } } } @@ -176,18 +178,14 @@ for (Node returnSideEffect : returnSideEffects) { if (!unwindSideEffects.contains(returnSideEffect) && !maskedSideEffects.contains(returnSideEffect)) { StateSplit split = (StateSplit) returnSideEffect; - if (split.stateAfter() != null) { - split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_BCI))); - } + setStateAfter(graph, split, AFTER_BCI, true); } } for (Node unwindSideEffect : unwindSideEffects) { if (!returnSideEffects.contains(unwindSideEffect) && !maskedSideEffects.contains(unwindSideEffect)) { StateSplit split = (StateSplit) unwindSideEffect; - if (split.stateAfter() != null) { - split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_EXCEPTION_BCI))); - } + setStateAfter(graph, split, AFTER_EXCEPTION_BCI, true); } } } @@ -207,15 +205,34 @@ } if (isNowInvalid) { - loop.setStateAfter(createInvalidFrameState(loop)); + setStateAfter(loop.graph(), loop, INVALID_FRAMESTATE_BCI, false); } IterationState endState = IterationState.merge(loop, info.endStates.values(), isNowInvalid); return ReentrantNodeIterator.processLoop(this, loop, endState).exitStates; } - private static FrameState createInvalidFrameState(FixedNode node) { - return node.graph().add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); + /** + * Creates and sets a special frame state for a node. If the existing frame state is + * non-null and has no other usages, it is deleted via + * {@link GraphUtil#killWithUnusedFloatingInputs(Node)}. + * + * @param graph the graph context + * @param node the node whose frame state is updated + * @param bci {@link BytecodeFrame#AFTER_BCI}, {@link BytecodeFrame#AFTER_EXCEPTION_BCI} or + * {@link BytecodeFrame#INVALID_FRAMESTATE_BCI} + * @param replaceOnly only perform the update if the node currently has a non-null frame + * state + */ + private static void setStateAfter(StructuredGraph graph, StateSplit node, int bci, boolean replaceOnly) { + assert bci == AFTER_BCI || bci == AFTER_EXCEPTION_BCI || bci == INVALID_FRAMESTATE_BCI; + FrameState currentStateAfter = node.stateAfter(); + if (currentStateAfter != null || !replaceOnly) { + node.setStateAfter(graph.add(new FrameState(bci))); + if (currentStateAfter != null && currentStateAfter.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(currentStateAfter); + } + } } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -109,7 +109,7 @@ StructuredGraph graph = loadField.graph(); ResolvedJavaField field = loadField.field(); ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object(); - Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind(), true); + Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind()); ConstantLocationNode location = createFieldLocation(graph, field, false); assert location != null : "Field that is loaded must not be eliminated"; @@ -158,7 +158,7 @@ StructuredGraph graph = loadIndexed.graph(); Kind elementKind = loadIndexed.elementKind(); LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false); - Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind, true); + Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind); ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE)); ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); @@ -223,7 +223,7 @@ if (graph.getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { return; } - ValueNode hub = createReadHub(graph, loadHub.object(), loadHub.getGuard()); + ValueNode hub = createReadHub(graph, loadHub.getValue(), loadHub.getGuard()); graph.replaceFloating(loadHub, hub); } @@ -273,7 +273,7 @@ } protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) { - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + boolean compressible = load.accessKind() == Kind.Object; Kind readKind = load.accessKind(); LocationNode location = createLocation(load); Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); @@ -503,6 +503,10 @@ protected abstract LocationIdentity initLocationIdentity(); + public Stamp loadStamp(Stamp stamp, Kind kind) { + return loadStamp(stamp, kind, true); + } + protected Stamp loadStamp(Stamp stamp, Kind kind, @SuppressWarnings("unused") boolean compressible) { switch (kind) { case Boolean: @@ -580,21 +584,21 @@ SignExtendNode extend = (SignExtendNode) offset; if (extend.getResultBits() == 64) { signExtend = true; - offset = extend.getInput(); + offset = extend.getValue(); } } if (offset instanceof IntegerAddNode) { IntegerAddNode integerAddNode = (IntegerAddNode) offset; - if (integerAddNode.y() instanceof ConstantNode) { - displacement = integerAddNode.y().asConstant().asLong(); - offset = integerAddNode.x(); + if (integerAddNode.getY() instanceof ConstantNode) { + displacement = integerAddNode.getY().asConstant().asLong(); + offset = integerAddNode.getX(); } } if (offset instanceof LeftShiftNode) { LeftShiftNode leftShiftNode = (LeftShiftNode) offset; - if (leftShiftNode.y() instanceof ConstantNode) { - long shift = leftShiftNode.y().asConstant().asLong(); + if (leftShiftNode.getY() instanceof ConstantNode) { + long shift = leftShiftNode.getY().asConstant().asLong(); if (shift >= 1 && shift <= 3) { if (shift == 1) { indexScaling = 2; @@ -603,7 +607,7 @@ } else { indexScaling = 8; } - offset = leftShiftNode.x(); + offset = leftShiftNode.getX(); } } } @@ -622,13 +626,15 @@ protected GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { StructuredGraph graph = n.graph(); ValueNode array = n.array(); - ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection()); + ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection()); if (arrayLength == null) { Stamp stamp = StampFactory.positiveInt(); ReadNode readArrayLength = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE)); graph.addBeforeFixed(n, readArrayLength); readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool)); arrayLength = readArrayLength; + } else { + arrayLength = arrayLength.isAlive() ? arrayLength : graph.addOrUniqueWithInputs(arrayLength); } if (arrayLength.isConstant() && n.index().isConstant()) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Jun 30 12:02:19 2014 +0200 @@ -208,7 +208,7 @@ ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); ReplacementsImpl repl = new ReplacementsImpl(providers, snippetReflection, new Assumptions(false), providers.getCodeCache().getTarget()); StructuredGraph calleeGraph = repl.makeGraph(method, null, method, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); - InliningUtil.inline(invoke, calleeGraph, false); + InliningUtil.inline(invoke, calleeGraph, false, null); } protected void pushStructure(Structure structure) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Mon Jun 30 12:02:19 2014 +0200 @@ -141,7 +141,7 @@ assert testValue.isConstant(); return LogicConstantNode.forBoolean(result.asConstant().equals(testValue.asConstant()), result.graph()); } - if (condition == null || condition.y() != testValue) { + if (condition == null || condition.getY() != testValue) { // Re-use previously generated condition if the trueValue for the test is the same condition = createCompareNode(result.graph(), Condition.EQ, result, testValue); } @@ -208,7 +208,7 @@ } @Override - public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; newNode.inferStamp(); @@ -234,19 +234,17 @@ public void replaceUsingInstantiation() { ValueNode newValue = instantiation.asMaterialization(usage.graph(), trueValue, falseValue); usage.replaceAtUsages(newValue); - usage.clearInputs(); assert usage.usages().isEmpty(); GraphUtil.killWithUnusedFloatingInputs(usage); } @Override - public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; newNode.inferStamp(); instantiation.initialize(newNode, trueValue, falseValue); usage.replaceAtUsages(newNode); - usage.clearInputs(); assert usage.usages().isEmpty(); GraphUtil.killWithUnusedFloatingInputs(usage); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -23,6 +23,7 @@ package com.oracle.graal.replacements; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.replacements.nodes.*; @ClassSubstitution(Integer.class) @@ -53,4 +54,14 @@ public static int bitCount(int i) { return BitCountNode.bitCount(i); } + + @MethodSubstitution + public static int divideUnsigned(int dividend, int divisor) { + return UnsignedDivNode.unsignedDivide(dividend, divisor); + } + + @MethodSubstitution + public static int remainderUnsigned(int dividend, int divisor) { + return UnsignedRemNode.unsignedRemainder(dividend, divisor); + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -23,6 +23,7 @@ package com.oracle.graal.replacements; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.replacements.nodes.*; @ClassSubstitution(Long.class) @@ -53,4 +54,14 @@ public static int bitCount(long i) { return BitCountNode.bitCount(i); } + + @MethodSubstitution + public static long divideUnsigned(long dividend, long divisor) { + return UnsignedDivNode.unsignedDivide(dividend, divisor); + } + + @MethodSubstitution + public static long remainderUnsigned(long dividend, long divisor) { + return UnsignedRemNode.unsignedRemainder(dividend, divisor); + } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Jun 30 12:02:19 2014 +0200 @@ -483,7 +483,10 @@ if (!SnippetTemplate.hasConstantParameter(method)) { NodeIntrinsificationVerificationPhase.verify(graph); } + int sideEffectCount = 0; + assert (sideEffectCount = graph.getNodes().filter(e -> e instanceof StateSplit && ((StateSplit) e).hasSideEffect()).count()) >= 0; new ConvertDeoptimizeToGuardPhase().apply(graph); + assert sideEffectCount == graph.getNodes().filter(e -> e instanceof StateSplit && ((StateSplit) e).hasSideEffect()).count() : "deleted side effecting node"; switch (frameStateProcessing) { case Removal: @@ -586,7 +589,7 @@ if (isInlinable(substitutedMethod)) { final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod); Mark mark = graph.getMark(); - InliningUtil.inline(callTarget.invoke(), originalGraph, true); + InliningUtil.inline(callTarget.invoke(), originalGraph, true, null); for (MethodCallTargetNode inlinedCallTarget : graph.getNewNodes(mark).filter(MethodCallTargetNode.class)) { if (doNotInline == null) { doNotInline = new HashSet<>(); @@ -620,7 +623,7 @@ targetGraph = parseGraph(callee, policy, inliningDepth + 1); } Object beforeInlineData = beforeInline(callTarget, targetGraph); - InliningUtil.inline(callTarget.invoke(), targetGraph, true); + InliningUtil.inline(callTarget.invoke(), targetGraph, true, null); Debug.dump(graph, "after inlining %s", callee); afterInline(graph, targetGraph, beforeInlineData); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsUtil.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, 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.replacements; + +import com.oracle.graal.replacements.nodes.*; + +public class ReplacementsUtil { + private ReplacementsUtil() { + // empty + } + + private static final boolean REPLACEMENTS_ASSERTIONS_ENABLED; + + static { + boolean assertionsEnabled = false; + assert (assertionsEnabled = true) != false; + REPLACEMENTS_ASSERTIONS_ENABLED = assertionsEnabled; + } + + /** + * Asserts that condition evaluates to true by the time compilation is finished. This is + * intended to be used within snippets or stubs, and will lead to a compile error if the + * assertion fails. + */ + public static void staticAssert(boolean condition, String message) { + if (REPLACEMENTS_ASSERTIONS_ENABLED) { + AssertionNode.assertion(true, condition, message); + } + } + + /** + * Asserts that condition evaluates to true at runtime. This is intended to be used within + * snippets or stubs, and will lead to a VM error if it fails. + */ + public static void runtimeAssert(boolean condition, String message) { + if (REPLACEMENTS_ASSERTIONS_ENABLED) { + AssertionNode.assertion(false, condition, message); + } + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Jun 30 12:02:19 2014 +0200 @@ -35,6 +35,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; +import java.util.stream.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -364,7 +365,7 @@ } public ValueNode length() { - return ConstantNode.forInt(varargs.length, graph()); + return ConstantNode.forInt(varargs.length); } } @@ -618,6 +619,7 @@ Mark mark = snippetCopy.getMark(); LoopTransformations.fullUnroll(loop, phaseContext, new CanonicalizerPhase(true)); new CanonicalizerPhase(true).applyIncremental(snippetCopy, phaseContext, mark); + loop.deleteUnusedNodes(); } GraphUtil.removeFixedWithUnusedInputs(explodeLoop); exploded = true; @@ -676,38 +678,33 @@ Debug.dump(snippet, "SnippetTemplate after fixing memory anchoring"); - List returnNodes = new ArrayList<>(4); - List memMaps = new ArrayList<>(4); StartNode entryPointNode = snippet.start(); - boolean anchorUsed = false; - for (ReturnNode retNode : snippet.getNodes(ReturnNode.class)) { - MemoryMapNode memMap = retNode.getMemoryMap(); - anchorUsed |= memMap.replaceLastLocationAccess(snippetCopy.start(), memoryAnchor); - memMaps.add(memMap); - retNode.setMemoryMap(null); - returnNodes.add(retNode); - if (memMap.usages().isEmpty()) { - memMap.safeDelete(); - } - } - if (memoryAnchor.usages().isEmpty() && !anchorUsed) { + if (memoryAnchor.usages().isEmpty()) { memoryAnchor.safeDelete(); } else { snippetCopy.addAfterFixed(snippetCopy.start(), memoryAnchor); } - assert snippet.getNodes().filter(MemoryMapNode.class).isEmpty(); + List returnNodes = snippet.getNodes(ReturnNode.class).snapshot(); if (returnNodes.isEmpty()) { this.returnNode = null; this.memoryMap = null; } else if (returnNodes.size() == 1) { this.returnNode = returnNodes.get(0); - this.memoryMap = memMaps.get(0); + this.memoryMap = returnNode.getMemoryMap(); } else { MergeNode merge = snippet.add(new MergeNode()); - ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes); + List memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList()); + ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null); this.returnNode = snippet.add(new ReturnNode(returnValue)); - this.memoryMap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps); + MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps); + this.memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap())); merge.setNext(this.returnNode); + + for (MemoryMapNode mm : memMaps) { + if (mm.isAlive()) { + mm.safeDelete(); + } + } } this.sideEffectNodes = curSideEffectNodes; @@ -797,7 +794,7 @@ private final ArrayList nodes; /** - * map of killing locations to memory checkpoints (nodes). + * Map of killing locations to memory checkpoints (nodes). */ private final MemoryMapNode memoryMap; @@ -896,7 +893,7 @@ /** * Replaces all usages of {@code oldNode} with direct or indirect usages of {@code newNode}. */ - void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap); + void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap); } /** @@ -918,7 +915,7 @@ } @Override - public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) { if (mmap != null) { for (Node usage : oldNode.usages().snapshot()) { LocationIdentity identity = getLocationIdentity(usage); @@ -960,12 +957,12 @@ // no floating reads yet, ignore locations created while lowering return true; } - if (memoryMap == null || ((MemoryMapImpl) memoryMap).isEmpty()) { - // there're no kills in the snippet graph + if (memoryMap == null || memoryMap.isEmpty()) { + // there are no kills in the snippet graph return true; } - Set kills = new HashSet<>(((MemoryMapImpl) memoryMap).getLocations()); + Set kills = new HashSet<>(memoryMap.getLocations()); if (replacee instanceof MemoryCheckpoint.Single) { // check if some node in snippet graph also kills the same location @@ -1009,10 +1006,10 @@ return true; } - private class DuplicateMapper extends MemoryMapNode { + private class DuplicateMapper implements MemoryMap { private final Map duplicates; - @Input private StartNode replaceeStart; + private StartNode replaceeStart; public DuplicateMapper(Map duplicates, StartNode replaceeStart) { this.duplicates = duplicates; @@ -1032,14 +1029,9 @@ } @Override - public Set getLocations() { + public Collection getLocations() { return memoryMap.getLocations(); } - - @Override - public boolean replaceLastLocationAccess(MemoryNode oldNode, MemoryNode newNode) { - throw GraalInternalError.shouldNotReachHere(); - } } /** @@ -1133,7 +1125,7 @@ if (returnNode != null && !(replacee instanceof ControlSinkNode)) { ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode); returnValue = returnDuplicate.result(); - MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start()); + MemoryMap mmap = new DuplicateMapper(duplicates, replaceeGraph.start()); if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) { replacer.replace(replacee, null, mmap); } else { @@ -1147,14 +1139,11 @@ next = fwn.next(); fwn.setNext(null); } - returnDuplicate.clearInputs(); returnDuplicate.replaceAndDelete(next); } } // Remove the replacee from its graph - replacee.clearInputs(); - replacee.replaceAtUsages(null); GraphUtil.killCFG(replacee); Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this); @@ -1241,7 +1230,6 @@ replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start())); if (returnDuplicate.isAlive()) { - returnDuplicate.clearInputs(); returnDuplicate.replaceAndDelete(next); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -26,10 +26,7 @@ import static com.oracle.graal.nodes.calc.ConditionalNode.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.calc.*; /** @@ -101,7 +98,7 @@ */ @MethodSubstitution public static int divide(int a, int b) { - return unsignedDivide(Kind.Int, a, b); + return UnsignedDivNode.unsignedDivide(a, b); } /** @@ -109,7 +106,7 @@ */ @MethodSubstitution public static int remainder(int a, int b) { - return unsignedRemainder(Kind.Int, a, b); + return UnsignedRemNode.unsignedRemainder(a, b); } /** @@ -117,7 +114,7 @@ */ @MethodSubstitution public static long divide(long a, long b) { - return unsignedDivide(Kind.Long, a, b); + return UnsignedDivNode.unsignedDivide(a, b); } /** @@ -125,18 +122,6 @@ */ @MethodSubstitution public static long remainder(long a, long b) { - return unsignedRemainder(Kind.Long, a, b); + return UnsignedRemNode.unsignedRemainder(a, b); } - - @NodeIntrinsic(UnsignedDivNode.class) - private static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b); - - @NodeIntrinsic(UnsignedDivNode.class) - private static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b); - - @NodeIntrinsic(UnsignedRemNode.class) - private static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b); - - @NodeIntrinsic(UnsignedRemNode.class) - private static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -67,7 +66,7 @@ return null; } if (GraphUtil.unproxify(array1) == GraphUtil.unproxify(array2)) { - return ConstantNode.forBoolean(true, graph()); + return ConstantNode.forBoolean(true); } return this; } @@ -130,8 +129,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Variable result = gen.newVariable(Kind.Int); - gen.emitArrayEquals(kind, result, gen.operand(array1), gen.operand(array2), gen.operand(length)); + Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length)); gen.setResult(this, result); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, 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.replacements.nodes; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Assertion nodes will go away as soon as the value evaluates to true. Compile-time assertions will + * fail if this has not happened by the time the node is lowered to LIR, while runtime assertions + * may need to insert a check. + */ +public class AssertionNode extends FixedWithNextNode implements Lowerable, Canonicalizable, LIRLowerable { + + @Input private ValueNode value; + + private final boolean compileTimeAssertion; + private final String message; + + public AssertionNode(boolean compileTimeAssertion, ValueNode value, String message) { + super(StampFactory.forVoid()); + this.value = value; + this.compileTimeAssertion = compileTimeAssertion; + this.message = message; + } + + public ValueNode value() { + return value; + } + + public String message() { + return message; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (value.isConstant() && value.asConstant().asInt() != 0) { + return null; + } + return this; + } + + public void lower(LoweringTool tool) { + if (!compileTimeAssertion) { + tool.getLowerer().lower(this, tool); + } + } + + public void generate(NodeLIRBuilderTool generator) { + assert compileTimeAssertion; + if (value.isConstant() && value.asConstant().asInt() == 0) { + throw new GraalInternalError("failed compile-time assertion: %s", message); + } else { + throw new GraalInternalError("failed compile-time assertion (value %s): %s", value, message); + } + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean value, @ConstantNodeParameter String message) { + assert value : message; + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -24,31 +24,31 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class BitCountNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +public class BitCountNode extends UnaryNode implements LIRLowerable { public BitCountNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); - this.value = value; + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant c = value.asConstant(); - if (c.getKind() == Kind.Int) { - return ConstantNode.forInt(Integer.bitCount(c.asInt()), graph()); - } else if (c.getKind() == Kind.Long) { - return ConstantNode.forInt(Long.bitCount(c.asLong()), graph()); - } + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + assert (valueStamp.downMask() & IntegerStamp.defaultMask(valueStamp.getBits())) == valueStamp.downMask(); + assert (valueStamp.upMask() & IntegerStamp.defaultMask(valueStamp.getBits())) == valueStamp.upMask(); + return updateStamp(StampFactory.forInteger(Kind.Int, bitCount(valueStamp.downMask()), bitCount(valueStamp.upMask()))); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + Constant c = forValue.asConstant(); + return ConstantNode.forInt(forValue.getKind() == Kind.Int ? bitCount(c.asInt()) : bitCount(c.asLong())); } return this; } @@ -65,8 +65,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Variable result = gen.newVariable(Kind.Int); - gen.emitBitCount(result, gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitBitCount(gen.operand(getValue())); gen.setResult(this, result); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,31 +24,46 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class BitScanForwardNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +/** + * Determines the index of the least significant "1" bit. Note that the result is undefined if the + * input is zero. + */ +public class BitScanForwardNode extends UnaryNode implements LIRLowerable { public BitScanForwardNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); - this.value = value; + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant c = value.asConstant(); - if (c.getKind() == Kind.Int) { - return ConstantNode.forInt(Integer.numberOfTrailingZeros(c.asInt()), graph()); - } else if (c.getKind() == Kind.Long) { - return ConstantNode.forInt(Long.numberOfTrailingZeros(c.asLong()), graph()); - } + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + int min; + int max; + long mask = IntegerStamp.defaultMask(valueStamp.getBits()); + int firstAlwaysSetBit = scan(valueStamp.downMask() & mask); + if (firstAlwaysSetBit == -1) { + int lastMaybeSetBit = BitScanReverseNode.scan(valueStamp.upMask() & mask); + min = -1; + max = lastMaybeSetBit; + } else { + int firstMaybeSetBit = scan(valueStamp.upMask() & mask); + min = firstMaybeSetBit; + max = firstAlwaysSetBit; + } + return updateStamp(StampFactory.forInteger(Kind.Int, min, max)); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + Constant c = forValue.asConstant(); + return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong())); } return this; } @@ -72,8 +87,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Variable result = gen.newVariable(Kind.Int); - gen.emitBitScanForward(result, gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitBitScanForward(gen.operand(getValue())); gen.setResult(this, result); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,31 +24,44 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class BitScanReverseNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +/** + * Determines the index of the most significant "1" bit. Note that the result is undefined if the + * input is zero. + */ +public class BitScanReverseNode extends UnaryNode implements LIRLowerable { public BitScanReverseNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); - this.value = value; + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - Constant c = value.asConstant(); - if (c.getKind() == Kind.Int) { - return ConstantNode.forInt(31 - Integer.numberOfLeadingZeros(c.asInt()), graph()); - } else if (c.getKind() == Kind.Long) { - return ConstantNode.forInt(63 - Long.numberOfLeadingZeros(c.asLong()), graph()); - } + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + int min; + int max; + long mask = IntegerStamp.defaultMask(valueStamp.getBits()); + int lastAlwaysSetBit = scan(valueStamp.downMask() & mask); + if (lastAlwaysSetBit == -1) { + min = -1; + } else { + min = lastAlwaysSetBit; + } + int lastMaybeSetBit = scan(valueStamp.upMask() & mask); + max = lastMaybeSetBit; + return updateStamp(StampFactory.forInteger(Kind.Int, min, max)); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + Constant c = forValue.asConstant(); + return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong())); } return this; } @@ -79,8 +92,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Variable result = gen.newVariable(Kind.Int); - gen.getLIRGeneratorTool().emitBitScanReverse(result, gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitBitScanReverse(gen.operand(getValue())); gen.setResult(this, result); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -45,9 +45,14 @@ this.readKind = readKind; } + protected ValueNode getAddress() { + return address; + } + @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, gen.operand(address), null)); + LIRKind kind = gen.getLIRGeneratorTool().target().getLIRKind(readKind); + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(kind, gen.operand(address), null)); } @SuppressWarnings("unchecked") diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -50,7 +50,16 @@ @Override public void generate(NodeLIRBuilderTool gen) { Value v = gen.operand(value); - gen.getLIRGeneratorTool().emitStore(kind, gen.operand(address), v, null); + LIRKind lirKind = gen.getLIRGeneratorTool().target().getLIRKind(kind); + gen.getLIRGeneratorTool().emitStore(lirKind, gen.operand(address), v, null); + } + + protected ValueNode getAddress() { + return address; + } + + protected ValueNode getValue() { + return value; } /* diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -35,18 +35,18 @@ @Input private ValueNode index; - private final ParameterNode[] parameters; + @Input private final NodeInputList parameters; public LoadSnippetVarargParameterNode(ParameterNode[] locals, ValueNode index, Stamp stamp) { super(stamp); this.index = index; - this.parameters = locals; + this.parameters = new NodeInputList<>(this, locals); } @Override public Node canonical(CanonicalizerTool tool) { if (index.isConstant()) { - return parameters[index.asConstant().asInt()]; + return parameters.get(index.asConstant().asInt()); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -142,7 +142,7 @@ ((Lowerable) nonNullReceiver).lower(tool); } } - InliningUtil.inline(invoke, replacementGraph, false); + InliningUtil.inline(invoke, replacementGraph, false, null); Debug.dump(graph(), "After inlining replacement %s", replacementGraph); } else { invoke.lower(tool); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -25,16 +25,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { +public class MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable { - @Input private ValueNode x; private final Operation operation; public enum Operation { @@ -47,24 +45,19 @@ TAN } - public ValueNode x() { - return x; - } - public Operation operation() { return operation; } - public MathIntrinsicNode(ValueNode x, Operation op) { - super(StampFactory.forKind(Kind.Double)); - assert x.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(x.stamp()) == 64; - this.x = x; + public MathIntrinsicNode(ValueNode value, Operation op) { + super(StampFactory.forKind(Kind.Double), value); + assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64; this.operation = op; } @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value input = builder.operand(x()); + Value input = builder.operand(getValue()); Value result; switch (operation()) { case ABS: @@ -100,9 +93,9 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant()), graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forPrimitive(evalConst(forValue.asConstant())); } return this; } @@ -112,7 +105,7 @@ return doCompute(value, op); } - private static double doCompute(double value, Operation op) throws GraalInternalError { + private static double doCompute(double value, Operation op) { switch (op) { case ABS: return Math.abs(value); @@ -128,7 +121,8 @@ return Math.cos(value); case TAN: return Math.tan(value); + default: + throw new GraalInternalError("unknown op %s", op); } - throw new GraalInternalError("unknown op %s", op); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -52,7 +52,7 @@ if (param.isConstant()) { Constant constant = evaluate(param.asConstant(), tool.getMetaAccess()); if (constant != null) { - return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph()); + return ConstantNode.forConstant(constant, tool.getMetaAccess()); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -75,7 +75,8 @@ @Override public void generate(NodeLIRBuilderTool generator) { - Value result = register.asValue(getKind()); + LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp()); + Value result = register.asValue(kind); if (incoming) { generator.getLIRGeneratorTool().emitIncomingValues(new Value[]{result}); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -24,32 +24,39 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; -public class ReverseBytesNode extends FloatingNode implements LIRLowerable, Canonicalizable { - - @Input private ValueNode value; +public class ReverseBytesNode extends UnaryNode implements LIRLowerable { public ReverseBytesNode(ValueNode value) { - super(StampFactory.forKind(value.getKind())); - assert getKind().isNumericInteger(); - this.value = value; + super(StampFactory.forKind(value.getKind()), value); + assert getKind() == Kind.Int || getKind() == Kind.Long; } @Override - public Node canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - long v = value.asConstant().asLong(); - if (getKind().getStackKind() == Kind.Int) { - return ConstantNode.forInt(Integer.reverseBytes((int) v), graph()); - } else if (getKind() == Kind.Long) { - return ConstantNode.forLong(Long.reverseBytes(v), graph()); - } + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + Stamp newStamp; + if (getKind() == Kind.Int) { + long mask = IntegerStamp.defaultMask(Kind.Int.getBitCount()); + newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse((int) valueStamp.downMask()) & mask, reverse((int) valueStamp.upMask()) & mask); + } else if (getKind() == Kind.Long) { + newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse(valueStamp.downMask()), reverse(valueStamp.upMask())); + } else { + return false; + } + return updateStamp(newStamp); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + Constant c = forValue.asConstant(); + return ConstantNode.forIntegerKind(getKind(), getKind() == Kind.Int ? reverse(c.asInt()) : reverse(c.asLong())); } return this; } @@ -66,8 +73,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - Variable result = gen.newVariable(value.getKind()); - gen.getLIRGeneratorTool().emitByteSwap(result, gen.operand(value)); + Value result = gen.getLIRGeneratorTool().emitByteSwap(gen.operand(getValue())); gen.setResult(this, result); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -54,7 +54,7 @@ @Override public void generate(NodeLIRBuilderTool generator) { Value val = generator.operand(value); - generator.getLIRGeneratorTool().emitMove(register.asValue(val.getKind()), val); + generator.getLIRGeneratorTool().emitMove(register.asValue(val.getLIRKind()), val); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java --- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,7 +36,6 @@ public class SPARC extends Architecture { public static final RegisterCategory CPU = new RegisterCategory("CPU"); - public static final RegisterCategory FPU = new RegisterCategory("FPU"); // General purpose registers public static final Register r0 = new Register(0, 0, "g0", CPU); @@ -123,6 +122,8 @@ }; // @formatter:on + public static final RegisterCategory FPU = new RegisterCategory("FPU", cpuRegisters.length); + // Floating point registers public static final Register f0 = new Register(32, 0, "f0", FPU); public static final Register f1 = new Register(33, 1, "f1", FPU); @@ -194,12 +195,12 @@ } @Override - public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { - if (!(platformKind instanceof Kind)) { + public boolean canStoreValue(RegisterCategory category, PlatformKind lirKind) { + if (!(lirKind instanceof Kind)) { return false; } - Kind kind = (Kind) platformKind; + Kind kind = (Kind) lirKind; if (category == CPU) { switch (kind) { case Boolean: diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Jun 30 12:02:19 2014 +0200 @@ -246,9 +246,7 @@ @SlowPath public Iterable getStackTrace() { - if (stackIntrospection == null) { - stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class); - } + initStackIntrospection(); final Iterator frames = stackIntrospection.getStackTrace(anyFrameMethod, anyFrameMethod, 1).iterator(); class FrameIterator implements Iterator { @@ -276,10 +274,15 @@ }; } - public FrameInstance getCurrentFrame() { + private void initStackIntrospection() { if (stackIntrospection == null) { stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class); } + } + + @SlowPath + public FrameInstance getCurrentFrame() { + initStackIntrospection(); Iterator frames = stackIntrospection.getStackTrace(callTargetMethod, callTargetMethod, 0).iterator(); if (frames.hasNext()) { return new HotSpotFrameInstance.CallTargetFrame(frames.next(), true); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -120,6 +120,7 @@ } } } + loopsData.deleteUnusedNodes(); } while (unrolled); } @@ -138,7 +139,7 @@ @Override public int compare(LoopEx o1, LoopEx o2) { - return o2.lirLoop().getDepth() - o1.lirLoop().getDepth(); + return o2.loop().getDepth() - o1.loop().getDepth(); } }); return sortedLoops; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Mon Jun 30 12:02:19 2014 +0200 @@ -34,9 +34,8 @@ return profile.getFrequency() / profile.getDeepNodeCount(); } - public boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft) { + public boolean isAllowed(TruffleInliningProfile profile, int currentNodeCount) { if (profile.isRecursiveCall()) { - // recursive call found profile.setFailedReason(REASON_RECURSION); return false; } @@ -45,7 +44,7 @@ return true; } - if (currentBudgetLeft - profile.getDeepNodeCount() < 0) { + if (currentNodeCount + profile.getDeepNodeCount() > TruffleInliningMaxCallerSize.getValue()) { profile.setFailedReason(REASON_MAXIMUM_TOTAL_NODE_COUNT); return false; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Jun 30 12:02:19 2014 +0200 @@ -121,6 +121,7 @@ @Override public void invalidate() { this.runtime.invalidateInstalledCode(this); + invalidateInlining(); } protected void invalidate(Node oldNode, Node newNode, CharSequence reason) { @@ -133,6 +134,23 @@ cancelInstalledTask(oldNode, newNode, reason); } + public void invalidateInlining() { + if (inliningPerformed) { + inliningPerformed = false; + getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + if (node instanceof OptimizedDirectCallNode) { + OptimizedDirectCallNode callNode = (OptimizedDirectCallNode) node; + if (callNode.isInlined()) { + callNode.resetInlining(); + } + } + return true; + } + }); + } + } + private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { if (this.runtime.cancelInstalledTask(this)) { logOptimizingUnqueued(this, oldNode, newNode, reason); @@ -242,19 +260,19 @@ return; } TruffleInliningHandler handler = new TruffleInliningHandler(new DefaultInliningPolicy()); - TruffleInliningResult result = handler.decideInlining(this, 0); + TruffleInliningDecision result = handler.decideInlining(this, 0); performInlining(result); logInliningDecision(result); } - private static void performInlining(TruffleInliningResult result) { + private static void performInlining(TruffleInliningDecision result) { if (result.getCallTarget().inliningPerformed) { return; } result.getCallTarget().inliningPerformed = true; for (TruffleInliningProfile profile : result) { profile.getCallNode().inline(); - TruffleInliningResult recursiveResult = profile.getRecursiveResult(); + TruffleInliningDecision recursiveResult = profile.getRecursiveResult(); if (recursiveResult != null) { performInlining(recursiveResult); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Mon Jun 30 12:02:19 2014 +0200 @@ -53,7 +53,7 @@ private OptimizedCallTargetLog() { } - public static void logInliningDecision(TruffleInliningResult result) { + public static void logInliningDecision(TruffleInliningDecision result) { if (!TraceTruffleInlining.getValue()) { return; } @@ -63,7 +63,7 @@ logInliningDone(result.getCallTarget()); } - private static void logInliningDecisionRecursive(TruffleInliningResult result, int depth) { + private static void logInliningDecisionRecursive(TruffleInliningDecision result, int depth) { List callNodes = searchCallNodes(result.getCallTarget()); for (OptimizedDirectCallNode callNode : callNodes) { TruffleInliningProfile profile = result.getProfiles().get(callNode); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -72,6 +72,14 @@ } } + public void resetInlining() { + CompilerAsserts.neverPartOfCompilation(); + if (inlined) { + inlined = false; + getCurrentCallTarget().invalidateInlining(); + } + } + @Override public boolean isInlinable() { return true; @@ -219,4 +227,5 @@ public static OptimizedDirectCallNode create(OptimizedCallTarget target) { return new OptimizedDirectCallNode(target); } + } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Jun 30 12:02:19 2014 +0200 @@ -214,7 +214,7 @@ expansionLogger.preExpand(methodCallTargetNode, inlineGraph); } List canonicalizedNodes = methodCallTargetNode.invoke().asNode().usages().snapshot(); - Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false); + Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false, canonicalizedNodes); if (TraceTruffleExpansion.getValue()) { expansionLogger.postExpand(inlined); } @@ -280,6 +280,7 @@ break; } } + loopsData.deleteUnusedNodes(); } while (unrolled); } catch (Throwable e) { throw Debug.handle(e); @@ -297,7 +298,7 @@ @Override public int compare(LoopEx o1, LoopEx o2) { - return o2.lirLoop().getDepth() - o1.lirLoop().getDepth(); + return o2.loop().getDepth() - o1.loop().getDepth(); } }); return sortedLoops; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,7 +49,7 @@ loadFieldNode.field().getAnnotation(CompilerDirectives.CompilationFinal.class) != null) { Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); assert verifyFieldValue(loadFieldNode.field(), constant); - return ConstantNode.forConstant(constant, metaAccess, loadFieldNode.graph()); + return ConstantNode.forConstant(constant, metaAccess); } } } else if (node instanceof LoadIndexedNode) { @@ -59,7 +59,7 @@ Constant constant = constantReflection.readArrayElement(loadIndexedNode.array().asConstant(), index); if (constant != null) { - return ConstantNode.forConstant(constant, metaAccess, loadIndexedNode.graph()); + return ConstantNode.forConstant(constant, metaAccess); } } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Mon Jun 30 12:02:19 2014 +0200 @@ -64,7 +64,12 @@ private final HashMap, StructuredGraph> cache = new HashMap<>(); private final HashMap, Long> lastUsed = new HashMap<>(); private final StructuredGraph markerGraph = new StructuredGraph(); + private final ResolvedJavaType stringBuilderClass; + private final ResolvedJavaType runtimeExceptionClass; + private final ResolvedJavaType assertionErrorClass; + private final ResolvedJavaType controlFlowExceptionClass; + private final ResolvedJavaMethod callBoundaryMethod; private long counter; @@ -73,7 +78,12 @@ this.config = config; this.configForRootGraph = configForRootGraph; this.optimisticOptimizations = optimisticOptimizations; + this.stringBuilderClass = providers.getMetaAccess().lookupJavaType(StringBuilder.class); + this.runtimeExceptionClass = providers.getMetaAccess().lookupJavaType(RuntimeException.class); + this.assertionErrorClass = providers.getMetaAccess().lookupJavaType(AssertionError.class); + this.controlFlowExceptionClass = providers.getMetaAccess().lookupJavaType(ControlFlowException.class); + try { callBoundaryMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("callRoot", Object[].class)); } catch (NoSuchMethodException ex) { @@ -244,15 +254,17 @@ ", must annotate such calls with @CompilerDirectives.SlowPath!")); } Invoke invoke = methodCallTargetNode.invoke(); - InliningUtil.inline(invoke, inlineGraph, true); + InliningUtil.inline(invoke, inlineGraph, true, null); } private boolean tryCutOffRuntimeExceptions(MethodCallTargetNode methodCallTargetNode) { if (methodCallTargetNode.targetMethod().isConstructor()) { - ResolvedJavaType runtimeException = providers.getMetaAccess().lookupJavaType(RuntimeException.class); - ResolvedJavaType controlFlowException = providers.getMetaAccess().lookupJavaType(ControlFlowException.class); + ResolvedJavaType declaringClass = methodCallTargetNode.targetMethod().getDeclaringClass(); ResolvedJavaType exceptionType = Objects.requireNonNull(StampTool.typeOrNull(methodCallTargetNode.receiver().stamp())); - if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass()) && !controlFlowException.isAssignableFrom(exceptionType)) { + + boolean removeAllocation = runtimeExceptionClass.isAssignableFrom(declaringClass) || assertionErrorClass.isAssignableFrom(declaringClass); + boolean isCFGException = controlFlowExceptionClass.isAssignableFrom(exceptionType); + if (removeAllocation && !isCFGException) { DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); FixedNode invokeNode = methodCallTargetNode.invoke().asNode(); invokeNode.replaceAtPredecessor(deoptNode); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Jun 30 12:02:19 2014 +0200 @@ -50,6 +50,7 @@ import com.oracle.graal.truffle.nodes.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; /** * Implementation of the Truffle compiler using Graal. @@ -110,8 +111,11 @@ public void compileMethodImpl(final OptimizedCallTarget compilable) { final StructuredGraph graph; - if (TraceTruffleCompilation.getValue()) { + if (TraceTruffleCompilation.getValue() || TraceTruffleCompilationAST.getValue()) { OptimizedCallTargetLog.logOptimizingStart(compilable); + if (TraceTruffleCompilationAST.getValue()) { + NodeUtil.printCompactTree(OptimizedCallTarget.OUT, compilable.getRootNode()); + } } long timeCompilationStarted = System.nanoTime(); @@ -150,7 +154,7 @@ } private static String formatSourceSection(SourceSection sourceSection) { - return sourceSection != null ? sourceSection.toString() : "n/a"; + return sourceSection != null ? sourceSection.getShortDescription() : "n/a"; } public CompilationResult compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Jun 30 12:02:19 2014 +0200 @@ -87,6 +87,8 @@ public static final OptionValue TraceTruffleCompilationHistogram = new OptionValue<>(false); @Option(help = "Prints out all polymorphic and generic nodes after compilation.") public static final OptionValue TraceTruffleCompilationPolymorphism = new OptionValue<>(false); + @Option(help = "Prints out all polymorphic and generic nodes after compilation.") + public static final OptionValue TraceTruffleCompilationAST = new OptionValue<>(false); @Option(help = "") public static final OptionValue TraceTruffleExpansion = new OptionValue<>(false); @Option(help = "") diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Mon Jun 30 12:02:19 2014 +0200 @@ -50,7 +50,7 @@ int sourceMethodBci = callTarget.invoke().bci(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); ResolvedJavaType targetReceiverType = null; - if (!sourceMethod.isStatic() && callTarget.receiver().isConstant()) { + if (!sourceMethod.isStatic() && callTarget.receiver() != null && callTarget.receiver().isConstant()) { targetReceiverType = providers.getMetaAccess().lookupJavaType(callTarget.arguments().first().asConstant()); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningDecision.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningDecision.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle; + +import java.util.*; + +public final class TruffleInliningDecision implements Iterable { + + private final OptimizedCallTarget callTarget; + private final Map profiles; + private final Set inlined; + private final int nodeCount; + + public TruffleInliningDecision(OptimizedCallTarget callTarget, List profiles, Set inlined, int nodeCount) { + this.callTarget = callTarget; + this.profiles = new HashMap<>(); + for (TruffleInliningProfile profile : profiles) { + this.profiles.put(profile.getCallNode(), profile); + } + this.nodeCount = nodeCount; + this.inlined = inlined; + } + + public Map getProfiles() { + return profiles; + } + + public int getNodeCount() { + return nodeCount; + } + + public OptimizedCallTarget getCallTarget() { + return callTarget; + } + + public boolean isInlined(OptimizedDirectCallNode path) { + return inlined.contains(profiles.get(path)); + } + + public int size() { + return inlined.size(); + } + + public Iterator iterator() { + return Collections.unmodifiableSet(inlined).iterator(); + } + + @Override + public String toString() { + return inlined.toString(); + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,68 +31,62 @@ private static final int MAXIMUM_RECURSIVE_DEPTH = 15; private static final ProfileScoreComparator INLINING_SCORE = new ProfileScoreComparator(); private final TruffleInliningPolicy policy; - private final Map resultCache; + private final Map resultCache; public TruffleInliningHandler(TruffleInliningPolicy policy) { this.policy = policy; this.resultCache = new HashMap<>(); } - public TruffleInliningResult decideInlining(OptimizedCallTarget target, int depth) { + public TruffleInliningDecision decideInlining(OptimizedCallTarget target, int depth) { if (resultCache.containsKey(target)) { return resultCache.get(target); } - resultCache.put(target, null); - TruffleInliningResult result = decideInliningImpl(target, depth); + resultCache.put(target, null); // important for recursion detection + TruffleInliningDecision result = createInliningDecision(target, depth); resultCache.put(target, result); return result; } - private TruffleInliningResult decideInliningImpl(OptimizedCallTarget target, int depth) { - List profiles = lookupProfiles(target, depth); + private TruffleInliningDecision createInliningDecision(OptimizedCallTarget target, int depth) { + List profiles = createProfiles(target, depth); Set inlined = new HashSet<>(); Collections.sort(profiles, INLINING_SCORE); - int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - OptimizedCallUtils.countNonTrivialNodes(target, true); + int deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(target, true); int index = 0; + for (TruffleInliningProfile profile : profiles) { profile.setQueryIndex(index++); - if (policy.isAllowed(profile, budget)) { + if (policy.isAllowed(profile, deepNodeCount)) { inlined.add(profile); - budget -= profile.getDeepNodeCount(); + deepNodeCount += profile.getDeepNodeCount(); } } - int deepNodeCount = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - budget; - return new TruffleInliningResult(target, profiles, inlined, deepNodeCount); + return new TruffleInliningDecision(target, profiles, inlined, deepNodeCount); } - private List lookupProfiles(final OptimizedCallTarget target, int depth) { - final List callNodes = new ArrayList<>(); + private List createProfiles(final OptimizedCallTarget target, final int depth) { + final List profiles = new ArrayList<>(); target.getRootNode().accept(new NodeVisitor() { public boolean visit(Node node) { if (node instanceof OptimizedDirectCallNode) { - callNodes.add((OptimizedDirectCallNode) node); + profiles.add(createProfile(target, (OptimizedDirectCallNode) node, depth)); } return true; } }); - final List profiles = new ArrayList<>(); - for (OptimizedDirectCallNode callNode : callNodes) { - profiles.add(lookupProfile(target, callNode, depth)); - } return profiles; } - public TruffleInliningProfile lookupProfile(OptimizedCallTarget parentTarget, OptimizedDirectCallNode ocn, int depth) { + public TruffleInliningProfile createProfile(OptimizedCallTarget parentTarget, OptimizedDirectCallNode ocn, int depth) { OptimizedCallTarget target = ocn.getCurrentCallTarget(); - int callSites = ocn.getCurrentCallTarget().getKnownCallSiteCount(); int nodeCount = OptimizedCallUtils.countNonTrivialNodes(target, false); double frequency = calculateFrequency(parentTarget, ocn); - boolean forced = ocn.isInliningForced(); int deepNodeCount; - TruffleInliningResult recursiveResult; + TruffleInliningDecision recursiveResult; boolean recursiveCall = false; if (target.inliningPerformed || depth > MAXIMUM_RECURSIVE_DEPTH) { deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(target, true); @@ -107,7 +101,7 @@ } } - TruffleInliningProfile profile = new TruffleInliningProfile(ocn, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveCall, recursiveResult); + TruffleInliningProfile profile = new TruffleInliningProfile(ocn, nodeCount, deepNodeCount, frequency, recursiveCall, recursiveResult); profile.setScore(policy.calculateScore(profile)); return profile; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,7 @@ public interface TruffleInliningPolicy { - boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft); + boolean isAllowed(TruffleInliningProfile profile, int currentNodeCount); double calculateScore(TruffleInliningProfile profile); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Mon Jun 30 12:02:19 2014 +0200 @@ -29,25 +29,20 @@ private final OptimizedDirectCallNode callNode; private final int nodeCount; private final int deepNodeCount; - private final int callSites; private final double frequency; - private final boolean forced; private final boolean recursiveCall; - private final TruffleInliningResult recursiveResult; + private final TruffleInliningDecision recursiveResult; private String failedReason; private int queryIndex = -1; private double score; - public TruffleInliningProfile(OptimizedDirectCallNode callNode, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, boolean recursiveCall, - TruffleInliningResult recursiveResult) { + public TruffleInliningProfile(OptimizedDirectCallNode callNode, int nodeCount, int deepNodeCount, double frequency, boolean recursiveCall, TruffleInliningDecision recursiveResult) { this.callNode = callNode; - this.callSites = callSites; this.nodeCount = nodeCount; this.deepNodeCount = deepNodeCount; this.frequency = frequency; this.recursiveCall = recursiveCall; - this.forced = forced; this.recursiveResult = recursiveResult; } @@ -60,14 +55,14 @@ } public int getCallSites() { - return callSites; + return callNode.getCurrentCallTarget().getKnownCallSiteCount(); } public int getNodeCount() { return nodeCount; } - public TruffleInliningResult getRecursiveResult() { + public TruffleInliningDecision getRecursiveResult() { return recursiveResult; } @@ -96,7 +91,7 @@ } public boolean isForced() { - return forced; + return callNode.isInliningForced(); } public double getFrequency() { @@ -112,7 +107,7 @@ properties.put("nodeCount", String.format("%5d/%5d", deepNodeCount, nodeCount)); properties.put("frequency", frequency); properties.put("score", String.format("%8.4f", getScore())); - properties.put(String.format("index=%3d, force=%s, callSites=%2d", queryIndex, (forced ? "Y" : "N"), callSites), ""); + properties.put(String.format("index=%3d, force=%s, callSites=%2d", queryIndex, (isForced() ? "Y" : "N"), getCallSites()), ""); properties.put("reason", failedReason); return properties; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.truffle; - -import java.util.*; - -public final class TruffleInliningResult implements Iterable { - - private final OptimizedCallTarget callTarget; - private final Map profiles; - private final Set inlined; - private final int nodeCount; - - public TruffleInliningResult(OptimizedCallTarget callTarget, List profiles, Set inlined, int nodeCount) { - this.callTarget = callTarget; - this.profiles = new HashMap<>(); - for (TruffleInliningProfile profile : profiles) { - this.profiles.put(profile.getCallNode(), profile); - } - this.nodeCount = nodeCount; - this.inlined = inlined; - } - - public Map getProfiles() { - return profiles; - } - - public int getNodeCount() { - return nodeCount; - } - - public OptimizedCallTarget getCallTarget() { - return callTarget; - } - - public boolean isInlined(OptimizedDirectCallNode path) { - return inlined.contains(profiles.get(path)); - } - - public int size() { - return inlined.size(); - } - - public Iterator iterator() { - return Collections.unmodifiableSet(inlined).iterator(); - } - - @Override - public String toString() { - return inlined.toString(); - } -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -38,7 +38,7 @@ /** * Creates a new {@link LoadIndexedFinalNode}. - * + * * @param array the instruction producing the array * @param index the instruction producing the index * @param elementKind the element type @@ -52,7 +52,7 @@ if (array().isConstant() && index().isConstant()) { Constant constant = tool.getConstantReflection().readArrayElement(array().asConstant(), index().asConstant().asInt()); if (constant != null) { - return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph()); + return ConstantNode.forConstant(constant, tool.getMetaAccess()); } } return this; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -36,42 +35,42 @@ * Node representing an exact integer addition that will throw an {@link ArithmeticException} in * case the addition would overflow the 32 bit range. */ -public class IntegerAddExactNode extends IntegerAddNode implements Canonicalizable, IntegerExactArithmeticNode { +public class IntegerAddExactNode extends IntegerAddNode implements IntegerExactArithmeticNode { public IntegerAddExactNode(ValueNode x, ValueNode y) { - super(x.stamp().unrestricted(), x, y); + super(x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @Override public boolean inferStamp() { - // TODO Should probably use a specialised version which understands that it can't overflow - return updateStamp(StampTool.add(x().stamp(), y().stamp())); + // TODO Should probably use a specialized version which understands that it can't overflow + return updateStamp(StampTool.add(getX().stamp(), getY().stamp())); } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new IntegerAddExactNode(y(), x())); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && !forY.isConstant()) { + return new IntegerAddExactNode(forY, forX); } - if (x().isConstant()) { - Constant xConst = x().asConstant(); - Constant yConst = y().asConstant(); + if (forX.isConstant()) { + Constant xConst = forX.asConstant(); + Constant yConst = forY.asConstant(); assert xConst.getKind() == yConst.getKind(); try { if (xConst.getKind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.addExact(xConst.asInt(), yConst.asInt()), graph()); + return ConstantNode.forInt(ExactMath.addExact(xConst.asInt(), yConst.asInt())); } else { assert xConst.getKind() == Kind.Long; - return ConstantNode.forLong(ExactMath.addExact(xConst.asLong(), yConst.asLong()), graph()); + return ConstantNode.forLong(ExactMath.addExact(xConst.asLong(), yConst.asLong())); } } catch (ArithmeticException ex) { // The operation will result in an overflow exception, so do not canonicalize. } - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 0) { - return x(); + return forX; } } return this; @@ -79,7 +78,7 @@ @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { - return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt)); + return graph().add(new IntegerAddExactSplitNode(stamp(), getX(), getY(), next, deopt)); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -35,39 +34,39 @@ * Node representing an exact integer multiplication that will throw an {@link ArithmeticException} * in case the addition would overflow the 32 bit range. */ -public class IntegerMulExactNode extends IntegerMulNode implements Canonicalizable, IntegerExactArithmeticNode { +public class IntegerMulExactNode extends IntegerMulNode implements IntegerExactArithmeticNode { public IntegerMulExactNode(ValueNode x, ValueNode y) { - super(x.stamp().unrestricted(), x, y); + super(x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && !y().isConstant()) { - return graph().unique(new IntegerMulExactNode(y(), x())); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && !forY.isConstant()) { + return new IntegerMulExactNode(forY, forX); } - if (x().isConstant()) { - Constant xConst = x().asConstant(); - Constant yConst = y().asConstant(); + if (forX.isConstant()) { + Constant xConst = forX.asConstant(); + Constant yConst = forY.asConstant(); assert xConst.getKind() == yConst.getKind(); try { if (xConst.getKind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.multiplyExact(xConst.asInt(), yConst.asInt()), graph()); + return ConstantNode.forInt(ExactMath.multiplyExact(xConst.asInt(), yConst.asInt())); } else { assert xConst.getKind() == Kind.Long; - return ConstantNode.forLong(ExactMath.multiplyExact(xConst.asLong(), yConst.asLong()), graph()); + return ConstantNode.forLong(ExactMath.multiplyExact(xConst.asLong(), yConst.asLong())); } } catch (ArithmeticException ex) { // The operation will result in an overflow exception, so do not canonicalize. } - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 1) { - return x(); + return forX; } if (c == 0) { - return ConstantNode.forIntegerStamp(stamp(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0); } } return this; @@ -75,7 +74,7 @@ @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { - return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt)); + return graph().add(new IntegerMulExactSplitNode(stamp(), getX(), getY(), next, deopt)); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -22,10 +22,13 @@ */ package com.oracle.graal.truffle.nodes.arithmetic; +import java.util.function.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -56,10 +59,45 @@ } } + /** + * Determines the minimum and maximum result of this node for the given inputs and returns the + * result of the given BiFunction on the minimum and maximum values. + */ + private T processExtremes(ValueNode forX, ValueNode forY, BiFunction op) { + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + + Kind kind = getKind(); + assert kind == Kind.Int || kind == Kind.Long; + long[] xExtremes = {xStamp.lowerBound(), xStamp.upperBound()}; + long[] yExtremes = {yStamp.lowerBound(), yStamp.upperBound()}; + long min = Long.MAX_VALUE; + long max = Long.MIN_VALUE; + for (long a : xExtremes) { + for (long b : yExtremes) { + long result = kind == Kind.Int ? ExactMath.multiplyHigh((int) a, (int) b) : ExactMath.multiplyHigh(a, b); + min = Math.min(min, result); + max = Math.max(max, result); + } + } + return op.apply(min, max); + } + + @Override + public boolean inferStamp() { + return updateStamp(processExtremes(getX(), getY(), (min, max) -> StampFactory.forInteger(getKind(), min, max))); + } + + @SuppressWarnings("cast") + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + return processExtremes(forX, forY, (min, max) -> min == (long) max ? ConstantNode.forIntegerKind(getKind(), min) : this); + } + @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value a = builder.operand(x()); - Value b = builder.operand(y()); + Value a = builder.operand(getX()); + Value b = builder.operand(getY()); builder.setResult(this, gen.emitMulHigh(a, b)); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -24,54 +24,54 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; import com.oracle.truffle.api.*; /** * Node representing an exact integer substraction that will throw an {@link ArithmeticException} in * case the addition would overflow the 32 bit range. */ -public class IntegerSubExactNode extends IntegerSubNode implements Canonicalizable, IntegerExactArithmeticNode { +public class IntegerSubExactNode extends IntegerSubNode implements IntegerExactArithmeticNode { public IntegerSubExactNode(ValueNode x, ValueNode y) { - super(StampTool.sub(x.stamp(), y.stamp()), x, y); + super(x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @Override public boolean inferStamp() { - // TODO Should probably use a specialised version which understands that it can't overflow - return updateStamp(StampTool.sub(x().stamp(), y().stamp())); + // TODO Should probably use a specialized version which understands that it can't overflow + return updateStamp(StampTool.sub(getX().stamp(), getY().stamp())); } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return ConstantNode.forIntegerStamp(stamp(), 0, graph()); + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return ConstantNode.forIntegerStamp(stamp(), 0); } - if (x().isConstant() && y().isConstant()) { - Constant xConst = x().asConstant(); - Constant yConst = y().asConstant(); + if (forX.isConstant() && forY.isConstant()) { + Constant xConst = forX.asConstant(); + Constant yConst = forY.asConstant(); assert xConst.getKind() == yConst.getKind(); try { if (xConst.getKind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.subtractExact(xConst.asInt(), yConst.asInt()), graph()); + return ConstantNode.forInt(ExactMath.subtractExact(xConst.asInt(), yConst.asInt())); } else { assert xConst.getKind() == Kind.Long; - return ConstantNode.forLong(ExactMath.subtractExact(xConst.asLong(), yConst.asLong()), graph()); + return ConstantNode.forLong(ExactMath.subtractExact(xConst.asLong(), yConst.asLong())); } } catch (ArithmeticException ex) { // The operation will result in an overflow exception, so do not canonicalize. } - } else if (y().isConstant()) { - long c = y().asConstant().asLong(); + } else if (forY.isConstant()) { + long c = forY.asConstant().asLong(); if (c == 0) { - return x(); + return forX; } } return this; @@ -79,7 +79,7 @@ @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { - return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt)); + return graph().add(new IntegerSubExactSplitNode(stamp(), getX(), getY(), next, deopt)); } @Override diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -22,10 +22,13 @@ */ package com.oracle.graal.truffle.nodes.arithmetic; +import java.util.function.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -56,10 +59,49 @@ } } + /** + * Determines the minimum and maximum result of this node for the given inputs and returns the + * result of the given BiFunction on the minimum and maximum values. Note that the minima and + * maxima are calculated using signed min/max functions, while the values themselves are + * unsigned. + */ + private T processExtremes(ValueNode forX, ValueNode forY, BiFunction op) { + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + + Kind kind = getKind(); + assert kind == Kind.Int || kind == Kind.Long; + long[] xExtremes = {xStamp.lowerBound(), xStamp.upperBound()}; + long[] yExtremes = {yStamp.lowerBound(), yStamp.upperBound()}; + long min = Long.MAX_VALUE; + long max = Long.MIN_VALUE; + for (long a : xExtremes) { + for (long b : yExtremes) { + long result = kind == Kind.Int ? ExactMath.multiplyHighUnsigned((int) a, (int) b) : ExactMath.multiplyHighUnsigned(a, b); + min = Math.min(min, result); + max = Math.max(max, result); + } + } + return op.apply(min, max); + } + + @SuppressWarnings("cast") + @Override + public boolean inferStamp() { + // if min is negative, then the value can reach into the unsigned range + return updateStamp(processExtremes(getX(), getY(), (min, max) -> (min == (long) max || min >= 0) ? StampFactory.forInteger(getKind(), min, max) : StampFactory.forKind(getKind()))); + } + + @SuppressWarnings("cast") + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + return processExtremes(forX, forY, (min, max) -> min == (long) max ? ConstantNode.forIntegerKind(getKind(), min) : this); + } + @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value a = builder.operand(x()); - Value b = builder.operand(y()); + Value a = builder.operand(getX()); + Value b = builder.operand(getY()); builder.setResult(this, gen.emitUMulHigh(a, b)); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -59,7 +59,7 @@ public Node canonical(CanonicalizerTool tool) { if (object.isConstant() && !object.isNullConstant() && offset.isConstant() && condition.isConstant() && condition.asConstant().asInt() == 1) { Constant constant = tool.getConstantReflection().readUnsafeConstant(accessKind, object.asConstant(), offset.asConstant().asLong()); - return ConstantNode.forConstant(constant, tool.getMetaAccess(), graph()); + return ConstantNode.forConstant(constant, tool.getMetaAccess()); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -62,10 +62,9 @@ } else { locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant()); } - CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph())); + CompareNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true)); Kind returnKind = this.getTargetMethod().getSignature().getReturnKind(); - Node result = graph().add(new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare)); - return result; + return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -61,10 +61,7 @@ locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant()); } - UnsafeStoreNode unsafeStoreNode = graph().add( - new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity)); - unsafeStoreNode.setStateAfter(this.stateAfter()); - return unsafeStoreNode; + return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter()); } return this; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -25,17 +25,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.truffle.nodes.asserts.*; import com.oracle.truffle.api.*; /** * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean, boolean)}. */ -public class UnsafeTypeCastMacroNode extends NeverPartOfCompilationNode implements Canonicalizable { +public class UnsafeTypeCastMacroNode extends NeverPartOfCompilationNode implements Simplifiable { private static final int OBJECT_ARGUMENT_INDEX = 0; private static final int CLASS_ARGUMENT_INDEX = 1; @@ -49,22 +49,25 @@ } @Override - public Node canonical(CanonicalizerTool tool) { + public void simplify(SimplifierTool tool) { ValueNode classArgument = arguments.get(CLASS_ARGUMENT_INDEX); ValueNode nonNullArgument = arguments.get(NONNULL_ARGUMENT_INDEX); if (classArgument.isConstant() && nonNullArgument.isConstant()) { ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX); ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX); ResolvedJavaType lookupJavaType = tool.getConstantReflection().asJavaType(classArgument.asConstant()); + tool.addToWorkList(usages()); if (lookupJavaType == null) { - return objectArgument; + replaceAtUsages(objectArgument); + GraphUtil.removeFixedWithUnusedInputs(this); + } else { + Stamp stamp = StampFactory.declared(lookupJavaType, nonNullArgument.asConstant().asInt() != 0); + ConditionAnchorNode valueAnchorNode = graph().add( + new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph())))); + PiNode piCast = graph().unique(new PiNode(objectArgument, stamp, valueAnchorNode)); + replaceAtUsages(piCast); + graph().replaceFixedWithFixed(this, valueAnchorNode); } - Stamp stamp = StampFactory.declared(lookupJavaType, nonNullArgument.asConstant().asInt() != 0); - ConditionAnchorNode valueAnchorNode = graph().add(new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph())))); - PiNode piCast = graph().unique(new PiNode(objectArgument, stamp, valueAnchorNode)); - this.replaceAtUsages(piCast); - return valueAnchorNode; } - return this; } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -54,7 +54,7 @@ } else { StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod()); if (inlineGraph != null) { - InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, true); + InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, true, null); Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString()); } } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Mon Jun 30 12:02:19 2014 +0200 @@ -33,6 +33,9 @@ @MacroSubstitution(macro = NeverPartOfCompilationNode.class, isStatic = true) public static native void neverPartOfCompilation(); + @MacroSubstitution(macro = NeverPartOfCompilationNode.class, isStatic = true) + public static native void neverPartOfCompilation(String message); + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) public static native boolean compilationConstant(boolean value); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; @@ -90,12 +91,10 @@ } // apply the effects collected during this iteration - HashSetNodeChangeListener listener = new HashSetNodeChangeListener(); - graph.trackInputChange(listener); - graph.trackUsagesDroppedZero(listener); - closure.applyEffects(); - graph.stopTrackingInputChange(); - graph.stopTrackingUsagesDroppedZero(); + HashSetNodeEventListener listener = new HashSetNodeEventListener.ExceptForAddedNodes(); + try (NodeEventScope nes = graph.trackNodeEvents(listener)) { + closure.applyEffects(); + } if (Debug.isDumpEnabled()) { Debug.dump(graph, "after " + getName() + " iteration"); @@ -103,7 +102,7 @@ new DeadCodeEliminationPhase().apply(graph); - Set changedNodes = listener.getChangedNodes(); + Set changedNodes = listener.getNodes(); for (Node node : graph.getNodes()) { if (node instanceof Simplifiable) { changedNodes.add(node); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -71,7 +71,12 @@ assert getKind() != input.getKind(); assert generator.getLIRGeneratorTool().target().getSizeInBytes(getKind()) == generator.getLIRGeneratorTool().target().getSizeInBytes(input.getKind()); - AllocatableValue result = generator.getLIRGeneratorTool().newVariable(getKind()); + LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp()); + if (kind.isValue()) { + kind = kind.makeDerivedReference(); + } + + AllocatableValue result = generator.getLIRGeneratorTool().newVariable(kind); generator.getLIRGeneratorTool().emitMove(result, generator.operand(input)); generator.setResult(this, result); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -134,9 +134,9 @@ * Fold constant field reads, e.g. enum constants. */ protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) { - ConstantNode constant = node.asConstant(metaAccess); + ConstantNode constant = node.asConstant(metaAccess, node.object()); if (constant != null) { - node.replaceAtUsages(constant); + node.replaceAtUsages(graph.unique(constant)); graph.removeFixed(node); } } @@ -199,7 +199,7 @@ ValueNode left = arguments.get(0); ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1)); - ValueNode replacement = graph.addOrUnique(createBinaryNodeInstance(operation.node(), wordKind, left, right)); + ValueNode replacement = graph.addOrUnique(createBinaryNodeInstance(operation.node(), left, right)); if (replacement instanceof FixedWithNextNode) { graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) replacement); } @@ -213,7 +213,7 @@ case NOT: assert arguments.size() == 1; - replace(invoke, graph.unique(new XorNode(StampFactory.forKind(wordKind), arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); + replace(invoke, graph.unique(new XorNode(arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); break; case READ_POINTER: @@ -333,10 +333,10 @@ * called for all Word operations which are annotated with @Operation(node = ...) and * encapsulates the reflective allocation of the node. */ - private static ValueNode createBinaryNodeInstance(Class nodeClass, Kind kind, ValueNode left, ValueNode right) { + private static ValueNode createBinaryNodeInstance(Class nodeClass, ValueNode left, ValueNode right) { try { - Constructor constructor = nodeClass.getConstructor(Stamp.class, ValueNode.class, ValueNode.class); - return constructor.newInstance(StampFactory.forKind(kind), left, right); + Constructor constructor = nodeClass.getConstructor(ValueNode.class, ValueNode.class); + return constructor.newInstance(left, right); } catch (Throwable ex) { throw new GraalInternalError(ex).addContext(nodeClass.getName()); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Mon Jun 30 12:02:19 2014 +0200 @@ -86,8 +86,8 @@ MethodCallTargetNode callTarget = (MethodCallTargetNode) usage; verifyInvoke(node, callTarget); } else if (usage instanceof ObjectEqualsNode) { - verify(!isWord(node) || ((ObjectEqualsNode) usage).x() != node, node, usage, "cannot use word type in comparison"); - verify(!isWord(node) || ((ObjectEqualsNode) usage).y() != node, node, usage, "cannot use word type in comparison"); + verify(!isWord(node) || ((ObjectEqualsNode) usage).getX() != node, node, usage, "cannot use word type in comparison"); + verify(!isWord(node) || ((ObjectEqualsNode) usage).getY() != node, node, usage, "cannot use word type in comparison"); } else if (usage instanceof ArrayLengthNode) { verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value"); } else if (usage instanceof ValuePhiNode) { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/SourceTextTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/SourceTextTest.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.test.utilities; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.source.*; + +public class SourceTextTest { + + private final Source emptySource = Source.fromText("", null); + + private final Source emptyLineSource = Source.fromText("\n", null); + + private final Source shortSource = Source.fromText("01", null); + + private final Source longSource = Source.fromText("01234\n67\n9\n", null); + + @Test + public void emptyTextTest0() { + assertEquals(emptySource.getLineCount(), 0); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyTextTest1() { + emptySource.getLineNumber(0); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyTextTest2() { + emptySource.getColumnNumber(0); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyTextTest3() { + emptySource.getLineNumber(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyTextTest4() { + emptySource.getLineStartOffset(0); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyTextTest5() { + emptySource.getLineStartOffset(1); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyTextTest6() { + emptySource.getLineLength(1); + } + + @Test + public void emptyLineTest0() { + assertEquals(emptyLineSource.getLineCount(), 1); + assertEquals(emptyLineSource.getLineNumber(0), 1); + assertEquals(emptyLineSource.getLineStartOffset(1), 0); + assertEquals(emptyLineSource.getColumnNumber(0), 1); + assertEquals(emptyLineSource.getLineLength(1), 0); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyLineTest1() { + emptyLineSource.getLineNumber(1); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyLineTest2() { + emptyLineSource.getLineStartOffset(2); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyLineTest3() { + emptyLineSource.getColumnNumber(1); + } + + @Test(expected = IllegalArgumentException.class) + public void emptyLineTest4() { + emptyLineSource.getLineLength(2); + } + + @Test + public void shortTextTest0() { + + assertEquals(shortSource.getLineCount(), 1); + + assertEquals(shortSource.getLineNumber(0), 1); + assertEquals(shortSource.getLineStartOffset(1), 0); + assertEquals(shortSource.getColumnNumber(0), 1); + + assertEquals(shortSource.getLineNumber(1), 1); + assertEquals(shortSource.getColumnNumber(1), 2); + + assertEquals(shortSource.getLineLength(1), 2); + } + + @Test(expected = IllegalArgumentException.class) + public void shortTextTest1() { + shortSource.getLineNumber(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void shortTextTest2() { + shortSource.getColumnNumber(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void shortTextTest3() { + shortSource.getLineNumber(2); + } + + @Test(expected = IllegalArgumentException.class) + public void shortTextTest4() { + shortSource.getColumnNumber(2); + } + + @Test(expected = IllegalArgumentException.class) + public void shortTextTest5() { + shortSource.getLineLength(2); + } + + @Test(expected = IllegalArgumentException.class) + public void shortTextTest6() { + shortSource.getLineLength(2); + } + + @Test + public void longTextTest0() { + + assertEquals(longSource.getLineCount(), 3); + + assertEquals(longSource.getLineNumber(0), 1); + assertEquals(longSource.getLineStartOffset(1), 0); + assertEquals(longSource.getColumnNumber(0), 1); + + assertEquals(longSource.getLineNumber(4), 1); + assertEquals(longSource.getColumnNumber(4), 5); + + assertEquals(longSource.getLineNumber(5), 1); // newline + assertEquals(longSource.getColumnNumber(5), 6); // newline + assertEquals(longSource.getLineLength(1), 5); + + assertEquals(longSource.getLineNumber(6), 2); + assertEquals(longSource.getLineStartOffset(2), 6); + assertEquals(longSource.getColumnNumber(6), 1); + + assertEquals(longSource.getLineNumber(7), 2); + assertEquals(longSource.getColumnNumber(7), 2); + + assertEquals(longSource.getLineNumber(8), 2); // newline + assertEquals(longSource.getLineNumber(8), 2); // newline + assertEquals(longSource.getLineLength(2), 2); + + assertEquals(longSource.getLineNumber(9), 3); + assertEquals(longSource.getLineStartOffset(3), 9); + assertEquals(longSource.getColumnNumber(9), 1); + + assertEquals(longSource.getLineNumber(10), 3); // newline + assertEquals(longSource.getColumnNumber(10), 2); // newline + assertEquals(longSource.getLineLength(3), 1); + + } + + @Test(expected = IllegalArgumentException.class) + public void longTextTest1() { + longSource.getLineNumber(11); + } + + @Test(expected = IllegalArgumentException.class) + public void longTextTest2() { + longSource.getColumnNumber(11); + } + + @Test(expected = IllegalArgumentException.class) + public void longTextTest3() { + longSource.getLineStartOffset(4); + } + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/TextMapTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/TextMapTest.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.test.utilities; - -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.truffle.api.source.*; - -public class TextMapTest { - - final TextMap emptyTextMap = new TextMap(""); - - final TextMap emptyLineMap = new TextMap("\n"); - - private final TextMap shortMap = new TextMap("01"); - - private final TextMap longMap = new TextMap("01234\n67\n9\n"); - - @Test - public void emptyTextTest0() { - assertEquals(emptyTextMap.lineCount(), 0); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyTextTest1() { - emptyTextMap.offsetToLine(0); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyTextTest2() { - emptyTextMap.offsetToCol(0); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyTextTest3() { - emptyTextMap.lineStartOffset(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyTextTest4() { - emptyTextMap.lineStartOffset(0); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyTextTest5() { - emptyTextMap.lineStartOffset(1); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyTextTest6() { - emptyTextMap.lineLength(1); - } - - @Test - public void emptyLineTest0() { - assertEquals(emptyLineMap.lineCount(), 1); - assertEquals(emptyLineMap.offsetToLine(0), 1); - assertEquals(emptyLineMap.lineStartOffset(1), 0); - assertEquals(emptyLineMap.offsetToCol(0), 1); - assertEquals(emptyLineMap.lineLength(1), 0); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyLineTest1() { - emptyLineMap.offsetToLine(1); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyLineTest2() { - emptyLineMap.lineStartOffset(2); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyLineTest3() { - emptyLineMap.offsetToCol(1); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyLineTest4() { - emptyLineMap.lineLength(2); - } - - @Test - public void shortTextTest0() { - - assertEquals(shortMap.lineCount(), 1); - - assertEquals(shortMap.offsetToLine(0), 1); - assertEquals(shortMap.lineStartOffset(1), 0); - assertEquals(shortMap.offsetToCol(0), 1); - - assertEquals(shortMap.offsetToLine(1), 1); - assertEquals(shortMap.offsetToCol(1), 2); - - assertEquals(shortMap.lineLength(1), 2); - } - - @Test(expected = IllegalArgumentException.class) - public void shortTextTest1() { - shortMap.offsetToLine(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void shortTextTest2() { - shortMap.offsetToCol(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void shortTextTest3() { - shortMap.offsetToLine(2); - } - - @Test(expected = IllegalArgumentException.class) - public void shortTextTest4() { - shortMap.offsetToCol(2); - } - - @Test(expected = IllegalArgumentException.class) - public void shortTextTest5() { - shortMap.lineStartOffset(2); - } - - @Test(expected = IllegalArgumentException.class) - public void shortTextTest6() { - shortMap.lineLength(2); - } - - @Test - public void longTextTest0() { - - assertEquals(longMap.lineCount(), 3); - - assertEquals(longMap.offsetToLine(0), 1); - assertEquals(longMap.lineStartOffset(1), 0); - assertEquals(longMap.offsetToCol(0), 1); - - assertEquals(longMap.offsetToLine(4), 1); - assertEquals(longMap.offsetToCol(4), 5); - - assertEquals(longMap.offsetToLine(5), 1); // newline - assertEquals(longMap.offsetToCol(5), 6); // newline - assertEquals(longMap.lineLength(1), 5); - - assertEquals(longMap.offsetToLine(6), 2); - assertEquals(longMap.lineStartOffset(2), 6); - assertEquals(longMap.offsetToCol(6), 1); - - assertEquals(longMap.offsetToLine(7), 2); - assertEquals(longMap.offsetToCol(7), 2); - - assertEquals(longMap.offsetToLine(8), 2); // newline - assertEquals(longMap.offsetToLine(8), 2); // newline - assertEquals(longMap.lineLength(2), 2); - - assertEquals(longMap.offsetToLine(9), 3); - assertEquals(longMap.lineStartOffset(3), 9); - assertEquals(longMap.offsetToCol(9), 1); - - assertEquals(longMap.offsetToLine(10), 3); // newline - assertEquals(longMap.offsetToCol(10), 2); // newline - assertEquals(longMap.lineLength(3), 1); - - } - - @Test(expected = IllegalArgumentException.class) - public void longTextTest1() { - longMap.offsetToLine(11); - } - - @Test(expected = IllegalArgumentException.class) - public void longTextTest2() { - longMap.offsetToCol(11); - } - - @Test(expected = IllegalArgumentException.class) - public void longTextTest3() { - longMap.lineStartOffset(4); - } - -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java Mon Jun 30 12:02:19 2014 +0200 @@ -29,7 +29,7 @@ * either executed in the interpreter or in the compiled code. The assertions are checked during * code generation and the Truffle compiler produces for failing assertions a stack trace that * identifies the code position of the assertion in the context of the current compilation. - * + * */ public class CompilerAsserts { @@ -42,9 +42,12 @@ public static void neverPartOfCompilation() { } + public static void neverPartOfCompilation(@SuppressWarnings("unused") String message) { + } + /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -54,7 +57,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -64,7 +67,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -74,7 +77,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -84,7 +87,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -94,7 +97,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -104,7 +107,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -114,7 +117,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ @@ -124,7 +127,7 @@ /** * Assertion that the corresponding value is reduced to a constant during compilation. - * + * * @param value the value that must be constant during compilation * @return the value given as parameter */ diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Mon Jun 30 12:02:19 2014 +0200 @@ -109,6 +109,16 @@ } /** + * Has a {@link Probe} been created that is uniquely associated with a particular source code + * location. + * + * @return a probe uniquely associated with an extent of guest language source code. + */ + public final boolean hasProbe(SourceSection sourceSection) { + return probeManager.hasProbe(sourceSection); + } + + /** * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty * collection if no probes found. */ @@ -120,7 +130,7 @@ * Returns all existing probes with first character on a specified line; empty collection if no * probes found. */ - public final Collection findProbesByLine(SourceLineLocation lineLocation) { + public final Collection findProbesByLine(LineLocation lineLocation) { return probeManager.findProbesByLine(lineLocation); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/NullSourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/NullSourceSection.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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; - -/** - * Marker for a special flavor of {@link SourceSection} that has no content and can be ignored. - */ -public interface NullSourceSection extends SourceSection { - -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2013, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 java.io.*; - -import com.oracle.truffle.api.source.*; - -/** - * Represents a unit (typically a file) of guest language source code. - */ -public interface Source { - - /** - * Returns the name of this resource holding a guest language program. An example would be the - * name of a guest language source code file. - * - * @return the name of the guest language program - */ - String getName(); - - /** - * Returns a short version of the name of the resource holding a guest language program (as - * described in @getName). For example, this could be just the name of the file, rather than a - * full path. - * - * @return the short name of the guest language program - */ - String getShortName(); - - /** - * The normalized, canonical name of the file. - */ - String getPath(); - - /** - * Access to the source contents. - */ - Reader getReader(); - - /** - * Access to the source contents. - */ - InputStream getInputStream(); - - /** - * Return the complete text of the code. - */ - String getCode(); - - /** - * Given a 1-based line number, return the text in the line, not including a possible - * terminating newline. - */ - String getCode(int lineNumber); - - /** - * The number of text lines in the source, including empty lines; characters at the end of the - * source without a terminating newline count as a line. - */ - int getLineCount(); - - /** - * Given a 0-based character offset, return the 1-based number of the line that includes the - * position. - */ - int getLineNumber(int offset); - - /** - * Given a 1-based line number, return the 0-based offset of the first character in the line. - */ - int getLineStartOffset(int lineNumber); - - /** - * The number of characters (not counting a possible terminating newline) in a (1-based) - * numbered line. - */ - int getLineLength(int lineNumber); - - /** - * Creates a representation of a contiguous region of text in the source. Computes the - * {@code (startLine, startColumn)} values by building a {@linkplain TextMap map} of lines in - * the source. - *

- * Checks the position arguments for consistency with the source. - *

- * The resulting representation defines hash/equality around equivalent location, presuming that - * {@link Source} representations are cannonical. - * - * - * @param identifier terse description of the region - * @param charIndex 0-based position of the first character in the section - * @param length the number of characters in the section - * @return newly created object representing the specified region - * @throws IllegalArgumentException if either of the arguments are outside the text of the - * source - * @throws IllegalStateException if the source is one of the "null" instances - */ - SourceSection createSection(String identifier, int charIndex, int length) throws IllegalArgumentException, IllegalStateException; - - /** - * Creates a representation of a contiguous region of text in the source. Computes the - * {@code charIndex} value by building a {@linkplain TextMap map} of lines in the source. - *

- * Checks the position arguments for consistency with the source. - *

- * The resulting representation defines hash/equality around equivalent location, presuming that - * {@link Source} representations are cannonical. - * - * @param identifier terse description of the region - * @param startLine 1-based line number of the first character in the section - * @param startColumn 1-based column number of the first character in the section - * @param length the number of characters in the section - * @return newly created object representing the specified region - * @throws IllegalArgumentException if arguments are outside the text of the source - * @throws IllegalStateException if the source is one of the "null" instances - */ - SourceSection createSection(String identifier, int startLine, int startColumn, int length); - - /** - * Creates a representation of a contiguous region of text in the source. - *

- * This method performs no checks on the validity of the arguments. - *

- * The resulting representation defines hash/equality around equivalent location, presuming that - * {@link Source} representations are cannonical. - * - * @param identifier terse description of the region - * @param startLine 1-based line number of the first character in the section - * @param startColumn 1-based column number of the first character in the section - * @param charIndex the 0-based index of the first character of the section - * @param length the number of characters in the section - * @return newly created object representing the specified region - */ - SourceSection createSection(String identifier, int startLine, int startColumn, int charIndex, int length); - -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2013, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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; - -/** - * Description of contiguous section of text within a {@link Source} of program code. - * - * The starting location of the section can be described using two different coordinates: - *

    - *
  • {@code (startLine, startColumn)}: rows and columns are 1-based, so the first character in a - * source file is at position {@code (1,1)}. {@code Tab} characters are counted as occupying one - * column.
  • - *
  • character index: 0-based offset of the character from the beginning of the source, so - * the first character in a file is at index {@code 0}.
  • - *
- * The {@code Newline} that terminates each line counts as a single character for the purpose of a - * character index and when counting the length of text. The {@code (line,column)} coordinates of a - * {@code Newline} should never appear in a text section. - *

- * If the final character of source is not a {@code Newline}, the final characters of the text are - * still considered to be a line ("unterminated"). - *

- * - * @see Source#createSection(String, int, int, int, int) - * @see Source#createSection(String, int, int, int) - * @see Source#createSection(String, int, int) - */ -public interface SourceSection { - - // TODO support alternate text representations/encodings - - /** - * Representation of the source program that contains this section. - * - * @return the source object - */ - Source getSource(); - - /** - * Returns 1-based line number of the first character in this section (inclusive). - * - * @return the starting line number - */ - int getStartLine(); - - /** - * Returns the 1-based column number of the first character in this section (inclusive). - * - * @return the starting column number - */ - int getStartColumn(); - - /** - * Returns the 0-based index of the first character in this section. - * - * @return the starting character index - */ - int getCharIndex(); - - /** - * Returns the length of this section in characters. - * - * @return the number of characters in the section - */ - int getCharLength(); - - /** - * Returns the index of the text position immediately following the last character in the - * section. - * - * @return the end position of the section - */ - int getCharEndIndex(); - - /** - * Returns terse text describing this source section, typically used for printing the section. - * - * @return the identifier of the section - */ - String getIdentifier(); - - /** - * Returns text described by this section. - * - * @return the code as a String object - */ - String getCode(); - - /** - * Returns a short description of the source section, using just the file name, rather than its - * full path. - * - * @return a short description of the source section - */ - String getShortDescription(); - - /** - * Singleton instance with no content. - */ - SourceSection NULL = new NullSourceSection() { - - @Override - public Source getSource() { - return null; - } - - @Override - public int getStartLine() { - return 0; - } - - @Override - public int getStartColumn() { - return 0; - } - - @Override - public int getCharIndex() { - return 0; - } - - @Override - public int getCharLength() { - return 0; - } - - @Override - public int getCharEndIndex() { - return 0; - } - - @Override - public String getIdentifier() { - return null; - } - - @Override - public String getCode() { - return null; - } - - @Override - public String getShortDescription() { - return "short"; - } - - }; - -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Mon Jun 30 12:02:19 2014 +0200 @@ -72,6 +72,13 @@ */ public static NodeCost TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost")); + /** + * Enables the dumping of Node creations and AST rewrites in JSON format. + *

+ * Can be set with {@code -Dtruffle.TraceASTJSON=true}. + */ + public static final boolean TraceASTJSON = Boolean.getBoolean("truffle.TraceASTJSON"); + private static NodeCost parseNodeInfoKind(String kind) { if (kind == null) { return null; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Mon Jun 30 12:02:19 2014 +0200 @@ -57,6 +57,7 @@ } public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) { + CompilerAsserts.neverPartOfCompilation("interpreter-only. includes hashmap operations."); assert !identifierToSlotMap.containsKey(identifier); FrameSlot slot = new FrameSlot(this, identifier, slots.size(), kind); slots.add(slot); @@ -87,6 +88,7 @@ } public void removeFrameSlot(Object identifier) { + CompilerAsserts.neverPartOfCompilation("interpreter-only. includes hashmap operations."); assert identifierToSlotMap.containsKey(identifier); slots.remove(identifierToSlotMap.get(identifier)); identifierToSlotMap.remove(identifier); @@ -104,7 +106,7 @@ /** * Retrieve the list of all the identifiers associated with this frame descriptor. - * + * * @return the list of all the identifiers in this frame descriptor */ public Set getIdentifiers() { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Mon Jun 30 12:02:19 2014 +0200 @@ -25,6 +25,7 @@ package com.oracle.truffle.api.frame; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; /** * A slot in a frame that can store a value of a given type. @@ -34,7 +35,7 @@ private final FrameDescriptor descriptor; private final Object identifier; private final int index; - @com.oracle.truffle.api.CompilerDirectives.CompilationFinal private FrameSlotKind kind; + @CompilationFinal private FrameSlotKind kind; public FrameSlot(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) { this.descriptor = descriptor; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,7 @@ */ package com.oracle.truffle.api.instrument; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; /** * A collector of {@link ExecutionEvents} at a specific site (node) in a Truffle AST (generated by a diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,10 +24,14 @@ */ package com.oracle.truffle.api.instrument; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; /** * Client for receiving events relate to {@link Probe} management. Does not report AST copying. + *

+ * Disclaimer: experimental interface under development. + * + * @See Instrumentation */ public interface ProbeListener { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SourceCallback.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SourceCallback.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SourceCallback.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,7 @@ */ package com.oracle.truffle.api.instrument; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; /** * Instrumentation callback for guest language source-related events. diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SourceListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SourceListener.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SourceListener.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,7 +24,7 @@ */ package com.oracle.truffle.api.instrument; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; /** * A client of the instrumentation framework that requests event notifications from the language diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Mon Jun 30 12:02:19 2014 +0200 @@ -27,12 +27,12 @@ import java.io.*; import java.util.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; import com.oracle.truffle.api.nodes.NodeUtil.NodeField; import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind; +import com.oracle.truffle.api.source.*; /** * A language-agnostic for printing out various pieces of a Truffle AST. diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,6 +28,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; public class DefaultVisualizer implements Visualizer { diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -31,6 +31,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; /** * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments. diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,7 +26,6 @@ import java.util.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.instrument.impl.InstrumentationNode.ProbeCallback; import com.oracle.truffle.api.instrument.impl.InstrumentationNode.ProbeImpl; @@ -47,7 +46,7 @@ /** * Map: Source line ==> probes associated with source sections starting on the line. */ - private final Map> lineToProbes = new HashMap<>(); + private final Map> lineToProbes = new HashMap<>(); private final List probeListeners = new ArrayList<>(); @@ -104,7 +103,7 @@ // Register new probe by source line, there may be more than one // Create line location for map key - final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine()); + final LineLocation lineLocation = sourceSection.getLineLocation(); Collection probes = lineToProbes.get(lineLocation); if (probes == null) { @@ -120,6 +119,11 @@ return probe; } + public boolean hasProbe(SourceSection sourceSection) { + assert sourceSection != null; + return srcToProbe.get(sourceSection) != null; + } + public Collection findProbesTaggedAs(PhylumTag tag) { final List probes = new ArrayList<>(); for (Probe probe : srcToProbe.values()) { @@ -130,7 +134,7 @@ return probes; } - public Collection findProbesByLine(SourceLineLocation lineLocation) { + public Collection findProbesByLine(LineLocation lineLocation) { final Collection probes = lineToProbes.get(lineLocation); if (probes == null) { return Collections.emptyList(); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,6 +30,8 @@ import java.util.concurrent.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.utilities.*; /** * Abstract base class for all Truffle nodes. @@ -57,12 +59,15 @@ } protected Node() { - CompilerAsserts.neverPartOfCompilation(); + this(null); } protected Node(SourceSection sourceSection) { CompilerAsserts.neverPartOfCompilation(); this.sourceSection = sourceSection; + if (TruffleOptions.TraceASTJSON) { + JSONHelper.dumpNewNode(this); + } } /** @@ -168,6 +173,9 @@ } boolean isInserted = newChild.parent == null; newChild.parent = this; + if (TruffleOptions.TraceASTJSON) { + JSONHelper.dumpNewChild(this, newChild); + } newChild.adoptHelper(); if (isInserted) { newChild.onAdopt(); @@ -272,6 +280,9 @@ this.parent.adoptUnadoptedHelper(newNode); } reportReplace(this, newNode, reason); + if (TruffleOptions.TraceASTJSON) { + JSONHelper.dumpReplaceChild(this, newNode, reason); + } onReplace(newNode, reason); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Jun 30 12:02:19 2014 +0200 @@ -34,6 +34,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.Node.Children; +import com.oracle.truffle.api.source.*; /** * Utility class that manages the special access methods for node instances. diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.source.*; /** * A root node is a node with a method to execute it given only a frame as a parameter. Therefore, a diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java Mon Jun 30 12:02:19 2014 +0200 @@ -29,11 +29,11 @@ import sun.misc.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; import com.oracle.truffle.api.nodes.NodeUtil.NodeField; import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind; +import com.oracle.truffle.api.source.*; /** * Experimental API. May change without notice. @@ -61,12 +61,12 @@ /** * Deserializes the byte stream and returns the deserialized Truffle AST node. - * + * * @param bytes the trimmed byte array containing the serialized data * @param expectedType the expected root node type. Throws an exception if the root node is not * assignable from this type. * @return the deserialized Truffle AST represented by the root Node. - * + * * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not * supported by the constant pool implementation. */ diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java Mon Jun 30 12:02:19 2014 +0200 @@ -29,11 +29,11 @@ import sun.misc.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; import com.oracle.truffle.api.nodes.NodeUtil.NodeField; import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind; +import com.oracle.truffle.api.source.*; /** * Experimental API. May change without notice. @@ -59,10 +59,10 @@ /** * Serializes the node AST and returns the serialized data as byte array. - * + * * @param node the root node that represents the Truffle AST that should be serialized. * @return a trimmed byte array that contains the serialized data. - * + * * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not * supported by the constant pool implementation. */ diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/LineLocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/LineLocation.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.source; + +/** + * A specification for a location in guest language source, expressed as a line number in a specific + * instance of {@link Source}, suitable for hash table keys with equality defined in terms of + * content. + */ +public interface LineLocation { + + public Source getSource(); + + /** + * Gets the 1-based number of a line in the source + */ + public int getLineNumber(); + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/NullSourceSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/NullSourceSection.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.source; + +/** + * A special subtype of {@link SourceSection} that represents unavailable source, e.g. for language + * builtins. + */ +public class NullSourceSection implements SourceSection { + + private final String kind; + private final String name; + private final String asCode; + + /** + * Placeholder for source that is unavailable, e.g. for language builtins. + * + * @param kind the general category, e.g. "JS builtin" + * @param name specific name for this section + */ + public NullSourceSection(String kind, String name) { + this(kind, name, kind); + } + + /** + * Placeholder for source that is unavailable, e.g. for language builtins. + * + * @param kind the general category, e.g. "JS builtin" + * @param name specific name for this section + * @param asCode string to return when {@link #getCode()} is called + */ + public NullSourceSection(String kind, String name, String asCode) { + this.kind = kind; + this.name = name; + this.asCode = asCode; + } + + public final Source getSource() { + return null; + } + + public final int getStartLine() { + throw new UnsupportedOperationException(this.toString()); + } + + public final LineLocation getLineLocation() { + throw new UnsupportedOperationException(this.toString()); + } + + public final int getStartColumn() { + throw new UnsupportedOperationException(this.toString()); + } + + public final int getCharIndex() { + throw new UnsupportedOperationException(this.toString()); + } + + public final int getCharLength() { + throw new UnsupportedOperationException(this.toString()); + } + + public final int getCharEndIndex() { + throw new UnsupportedOperationException(this.toString()); + } + + public final String getIdentifier() { + return name; + } + + public final String getCode() { + return asCode; + } + + public final String getShortDescription() { + return kind + ": " + name; + } + + @Override + public String toString() { + return getShortDescription(); + } + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,975 @@ +/* + * Copyright (c) 2013, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.source; + +import java.io.*; +import java.lang.ref.*; +import java.net.*; +import java.util.*; + +/** + * Representation of a guest language source code unit and its contents. Sources originate in + * several ways: + *

    + *
  • Literal: A named text string. These are not indexed and should be considered + * value objects; equality is defined based on contents.
    + * See {@link Source#fromText(String, String)}
  • + *

    + *

  • File: Each file is represented as a canonical object, indexed by the + * absolute, canonical path name of the file. File contents are read lazily and contents + * optionally cached.
    + * See {@link Source#fromFileName(String)}
    + * See {@link Source#fromFileName(String, boolean)}
  • + *

    + *

  • URL: Each URL source is represented as a canonical object, indexed by the + * URL. Contents are read eagerly and cached.
    + * See {@link Source#fromURL(URL, String)}
  • + *

    + *

  • Reader: Contents are read eagerly and treated as a Literal + * .
    + * See {@link Source#fromReader(Reader, String)}
  • + *

    + *

  • Pseudo File: A literal text string that can be retrieved by name as if it + * were a file, unlike literal sources; useful for testing.
    + * See {@link Source#asPseudoFile(String, String)}
  • + *
+ *

+ * File cache: + *

    + *
  1. File content caching is optional, off by default.
  2. + *
  3. The first access to source file contents will result in the contents being read, and (if + * enabled) cached.
  4. + *
  5. If file contents have been cached, access to contents via {@link Source#getInputStream()} or + * {@link Source#getReader()} will be provided from the cache.
  6. + *
  7. Any access to file contents via the cache will result in a timestamp check and possible cache + * reload.
  8. + *
+ */ +public abstract class Source { + + // TODO (mlvdv) consider canonicalizing and reusing SourceSection instances + // TOOD (mlvdv) connect SourceSections into a spatial tree for fast geometric lookup + + // Files and pseudo files are indexed. + private static final Map> filePathToSource = new HashMap<>(); + + private static boolean fileCacheEnabled = true; + + /** + * Gets the canonical representation of a source file, whose contents will be read lazily and + * then cached. + * + * @param fileName name + * @param reset forces any existing {@link Source} cache to be cleared, forcing a re-read + * @return canonical representation of the file's contents. + * @throws IOException if the file can not be read + */ + public static Source fromFileName(String fileName, boolean reset) throws IOException { + + final WeakReference nameRef = filePathToSource.get(fileName); + Source source = nameRef == null ? null : nameRef.get(); + if (source == null) { + final File file = new File(fileName); + if (!file.canRead()) { + throw new IOException("Can't read file " + fileName); + } + final String path = file.getCanonicalPath(); + final WeakReference pathRef = filePathToSource.get(path); + source = pathRef == null ? null : pathRef.get(); + if (source == null) { + source = new FileSource(file, fileName, path); + filePathToSource.put(path, new WeakReference<>(source)); + } + } + if (reset) { + source.reset(); + } + return source; + } + + /** + * Gets the canonical representation of a source file, whose contents will be read lazily and + * then cached. + * + * @param fileName name + * @return canonical representation of the file's contents. + * @throws IOException if the file can not be read + */ + public static Source fromFileName(String fileName) throws IOException { + return fromFileName(fileName, false); + } + + /** + * Creates a non-canonical source from literal text. + * + * @param code textual source code + * @param description a note about the origin, for error messages and debugging + * @return a newly created, non-indexed source representation + */ + public static Source fromText(String code, String description) { + assert code != null; + return new LiteralSource(description, code); + } + + /** + * Creates a source whose contents will be read immediately from a URL and cached. + * + * @param url + * @param name identifies the origin, possibly useful for debugging + * @return a newly created, non-indexed source representation + * @throws IOException if reading fails + */ + public static Source fromURL(URL url, String name) throws IOException { + return URLSource.get(url, name); + } + + /** + * Creates a source whose contents will be read immediately and cached. + * + * @param reader + * @param description a note about the origin, possibly useful for debugging + * @return a newly created, non-indexed source representation + * @throws IOException if reading fails + */ + public static Source fromReader(Reader reader, String description) throws IOException { + return new LiteralSource(description, read(reader)); + } + + /** + * Creates a source from literal text, but which acts as a file and can be retrieved by name + * (unlike other literal sources); intended for testing. + * + * @param code textual source code + * @param pseudoFileName string to use for indexing/lookup + * @return a newly created, source representation, canonical with respect to its name + */ + public static Source asPseudoFile(String code, String pseudoFileName) { + final Source source = new LiteralSource(pseudoFileName, code); + filePathToSource.put(pseudoFileName, new WeakReference<>(source)); + return source; + } + + /** + * Enables/disables caching of file contents, disabled by default. Caching of sources + * created from literal text or readers is always enabled. + */ + public static void setFileCaching(boolean enabled) { + fileCacheEnabled = enabled; + } + + private static String read(Reader reader) throws IOException { + final StringBuilder builder = new StringBuilder(); + final char[] buffer = new char[1024]; + + while (true) { + final int n = reader.read(buffer); + if (n == -1) { + break; + } + builder.append(buffer, 0, n); + } + + return builder.toString(); + } + + Source() { + } + + private TextMap textMap = null; + + protected abstract void reset(); + + /** + * Returns the name of this resource holding a guest language program. An example would be the + * name of a guest language source code file. + * + * @return the name of the guest language program + */ + public abstract String getName(); + + /** + * Returns a short version of the name of the resource holding a guest language program (as + * described in @getName). For example, this could be just the name of the file, rather than a + * full path. + * + * @return the short name of the guest language program + */ + public abstract String getShortName(); + + /** + * The normalized, canonical name if the source is a file. + */ + public abstract String getPath(); + + /** + * The URL if the source is retrieved via URL. + */ + public abstract URL getURL(); + + /** + * Access to the source contents. + */ + public abstract Reader getReader(); + + /** + * Access to the source contents. + */ + public final InputStream getInputStream() { + return new ByteArrayInputStream(getCode().getBytes()); + } + + /** + * Return the complete text of the code. + */ + public abstract String getCode(); + + /** + * Gets the text (not including a possible terminating newline) in a (1-based) numbered line. + */ + public final String getCode(int lineNumber) { + checkTextMap(); + final int offset = textMap.lineStartOffset(lineNumber); + final int length = textMap.lineLength(lineNumber); + return getCode().substring(offset, offset + length); + } + + /** + * The number of text lines in the source, including empty lines; characters at the end of the + * source without a terminating newline count as a line. + */ + public final int getLineCount() { + return checkTextMap().lineCount(); + } + + /** + * Given a 0-based character offset, return the 1-based number of the line that includes the + * position. + * + * @throws IllegalArgumentException if the offset is outside the text contents + */ + public final int getLineNumber(int offset) throws IllegalArgumentException { + return checkTextMap().offsetToLine(offset); + } + + /** + * Given a 0-based character offset, return the 1-based number of the column at the position. + * + * @throws IllegalArgumentException if the offset is outside the text contents + */ + public final int getColumnNumber(int offset) throws IllegalArgumentException { + return checkTextMap().offsetToCol(offset); + } + + /** + * Given a 1-based line number, return the 0-based offset of the first character in the line. + * + * @throws IllegalArgumentException if there is no such line in the text + */ + public final int getLineStartOffset(int lineNumber) throws IllegalArgumentException { + return checkTextMap().lineStartOffset(lineNumber); + } + + /** + * The number of characters (not counting a possible terminating newline) in a (1-based) + * numbered line. + * + * @throws IllegalArgumentException if there is no such line in the text + */ + public final int getLineLength(int lineNumber) throws IllegalArgumentException { + return checkTextMap().lineLength(lineNumber); + } + + /** + * Creates a representation of a contiguous region of text in the source. + *

+ * This method performs no checks on the validity of the arguments. + *

+ * The resulting representation defines hash/equality around equivalent location, presuming that + * {@link Source} representations are canonical. + * + * @param identifier terse description of the region + * @param startLine 1-based line number of the first character in the section + * @param startColumn 1-based column number of the first character in the section + * @param charIndex the 0-based index of the first character of the section + * @param length the number of characters in the section + * @return newly created object representing the specified region + */ + public final SourceSection createSection(String identifier, int startLine, int startColumn, int charIndex, int length) { + return new DefaultSourceSection(this, identifier, startLine, startColumn, charIndex, length); + } + + /** + * Creates a representation of a contiguous region of text in the source. Computes the + * {@code charIndex} value by building a {@linkplain TextMap map} of lines in the source. + *

+ * Checks the position arguments for consistency with the source. + *

+ * The resulting representation defines hash/equality around equivalent location, presuming that + * {@link Source} representations are canonical. + * + * @param identifier terse description of the region + * @param startLine 1-based line number of the first character in the section + * @param startColumn 1-based column number of the first character in the section + * @param length the number of characters in the section + * @return newly created object representing the specified region + * @throws IllegalArgumentException if arguments are outside the text of the source + * @throws IllegalStateException if the source is one of the "null" instances + */ + public final SourceSection createSection(String identifier, int startLine, int startColumn, int length) { + checkTextMap(); + final int lineStartOffset = textMap.lineStartOffset(startLine); + if (startColumn > textMap.lineLength(startLine)) { + throw new IllegalArgumentException("column out of range"); + } + final int startOffset = lineStartOffset + startColumn - 1; + return new DefaultSourceSection(this, identifier, startLine, startColumn, startOffset, length); + } + + /** + * Creates a representation of a contiguous region of text in the source. Computes the + * {@code (startLine, startColumn)} values by building a {@linkplain TextMap map} of lines in + * the source. + *

+ * Checks the position arguments for consistency with the source. + *

+ * The resulting representation defines hash/equality around equivalent location, presuming that + * {@link Source} representations are canonical. + * + * + * @param identifier terse description of the region + * @param charIndex 0-based position of the first character in the section + * @param length the number of characters in the section + * @return newly created object representing the specified region + * @throws IllegalArgumentException if either of the arguments are outside the text of the + * source + * @throws IllegalStateException if the source is one of the "null" instances + */ + public final SourceSection createSection(String identifier, int charIndex, int length) throws IllegalArgumentException { + final int codeLength = getCode().length(); + if (!(charIndex >= 0 && length >= 0 && charIndex + length <= codeLength)) { + throw new IllegalArgumentException("text positions out of range"); + } + checkTextMap(); + final int startLine = getLineNumber(charIndex); + final int startColumn = charIndex - getLineStartOffset(startLine) + 1; + + return new DefaultSourceSection(this, identifier, startLine, startColumn, charIndex, length); + } + + /** + * Creates a representation of a line of text in the source identified only by line number, from + * which the character information will be computed. + * + * @param identifier terse description of the line + * @param lineNumber 1-based line number of the first character in the section + * @return newly created object representing the specified line + * @throws IllegalArgumentException if the line does not exist the source + * @throws IllegalStateException if the source is one of the "null" instances + */ + public final SourceSection createSection(String identifier, int lineNumber) { + checkTextMap(); + final int charIndex = textMap.lineStartOffset(lineNumber); + final int length = textMap.lineLength(lineNumber); + return createSection(identifier, charIndex, length); + } + + /** + * Creates a representation of a line number in this source, suitable for use as a hash table + * key with equality defined to mean equivalent location. + * + * @param lineNumber a 1-based line number in this source + * @return a representation of a line in this source + */ + public final LineLocation createLineLocation(int lineNumber) { + return new LineLocationImpl(this, lineNumber); + } + + private TextMap checkTextMap() { + if (textMap == null) { + final String code = getCode(); + if (code == null) { + throw new RuntimeException("can't read file " + getName()); + } + textMap = new TextMap(code); + } + return textMap; + } + + private static final class LiteralSource extends Source { + + private final String name; // Name used originally to describe the source + private final String code; + + public LiteralSource(String name, String code) { + this.name = name; + this.code = code; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getShortName() { + return name; + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getPath() { + return name; + } + + @Override + public URL getURL() { + return null; + } + + @Override + public Reader getReader() { + return new StringReader(code); + } + + @Override + protected void reset() { + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + name.hashCode(); + result = prime * result + (code == null ? 0 : code.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof LiteralSource)) { + return false; + } + LiteralSource other = (LiteralSource) obj; + return name.equals(other.name) && code.equals(other.code); + } + + } + + private static final class FileSource extends Source { + + private final File file; + private final String name; // Name used originally to describe the source + private final String path; // Normalized path description of an actual file + + private String code = null; // A cache of the file's contents + private long timeStamp; // timestamp of the cache in the file system + + public FileSource(File file, String name, String path) { + this.file = file; + this.name = name; + this.path = path; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getShortName() { + return file.getName(); + } + + @Override + public String getCode() { + if (fileCacheEnabled) { + if (code == null || timeStamp != file.lastModified()) { + try { + code = read(getReader()); + timeStamp = file.lastModified(); + } catch (IOException e) { + } + } + return code; + } + try { + return read(new FileReader(file)); + } catch (IOException e) { + } + return null; + } + + @Override + public String getPath() { + return path; + } + + @Override + public URL getURL() { + return null; + } + + @Override + public Reader getReader() { + if (code != null && timeStamp == file.lastModified()) { + return new StringReader(code); + } + try { + return new FileReader(file); + } catch (FileNotFoundException e) { + throw new RuntimeException("Can't find file " + path); + } + } + + @Override + protected void reset() { + this.code = null; + } + + } + + private static final class URLSource extends Source { + + private static final Map> urlToSource = new HashMap<>(); + + public static URLSource get(URL url, String name) throws IOException { + WeakReference sourceRef = urlToSource.get(url); + URLSource source = sourceRef == null ? null : sourceRef.get(); + if (source == null) { + source = new URLSource(url, name); + urlToSource.put(url, new WeakReference<>(source)); + } + return source; + } + + private final URL url; + private final String name; + private String code = null; // A cache of the source contents + + public URLSource(URL url, String name) throws IOException { + this.url = url; + this.name = name; + code = read(new InputStreamReader(url.openStream())); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getShortName() { + return name; + } + + @Override + public String getPath() { + return url.getPath(); + } + + @Override + public URL getURL() { + return url; + } + + @Override + public Reader getReader() { + return new StringReader(code); + } + + @Override + public String getCode() { + return code; + } + + @Override + protected void reset() { + } + + } + + private static final class DefaultSourceSection implements SourceSection { + + private final Source source; + private final String identifier; + private final int startLine; + private final int startColumn; + private final int charIndex; + private final int charLength; + + /** + * Creates a new object representing a contiguous text section within the source code of a + * guest language program's text. + *

+ * The starting location of the section is specified using two different coordinate: + *

    + *
  • (row, column): rows and columns are 1-based, so the first character in a + * source file is at position {@code (1,1)}.
  • + *
  • character index: 0-based offset of the character from the beginning of the + * source, so the first character in a file is at index {@code 0}.
  • + *
+ * The newline that terminates each line counts as a single character for the purpose + * of a character index. The (row,column) coordinates of a newline character should never + * appear in a text section. + *

+ * + * @param source object representing the complete source program that contains this section + * @param identifier an identifier used when printing the section + * @param startLine the 1-based number of the start line of the section + * @param startColumn the 1-based number of the start column of the section + * @param charIndex the 0-based index of the first character of the section + * @param charLength the length of the section in number of characters + */ + public DefaultSourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) { + this.source = source; + this.identifier = identifier; + this.startLine = startLine; + this.startColumn = startColumn; + this.charIndex = charIndex; + this.charLength = charLength; + } + + @Override + public final Source getSource() { + return source; + } + + @Override + public final int getStartLine() { + return startLine; + } + + @Override + public final LineLocation getLineLocation() { + return source.createLineLocation(startLine); + } + + @Override + public final int getStartColumn() { + return startColumn; + } + + @Override + public final int getCharIndex() { + return charIndex; + } + + @Override + public final int getCharLength() { + return charLength; + } + + @Override + public final int getCharEndIndex() { + return charIndex + charLength; + } + + @Override + public final String getIdentifier() { + return identifier; + } + + @Override + public final String getCode() { + return getSource().getCode().substring(charIndex, charIndex + charLength); + } + + @Override + public final String getShortDescription() { + return String.format("%s:%d", source.getShortName(), startLine); + } + + @Override + public String toString() { + return getCode(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + charIndex; + result = prime * result + charLength; + result = prime * result + ((identifier == null) ? 0 : identifier.hashCode()); + result = prime * result + ((source == null) ? 0 : source.hashCode()); + result = prime * result + startColumn; + result = prime * result + startLine; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof DefaultSourceSection)) { + return false; + } + DefaultSourceSection other = (DefaultSourceSection) obj; + if (charIndex != other.charIndex) { + return false; + } + if (charLength != other.charLength) { + return false; + } + if (identifier == null) { + if (other.identifier != null) { + return false; + } + } else if (!identifier.equals(other.identifier)) { + return false; + } + if (source == null) { + if (other.source != null) { + return false; + } + } else if (!source.equals(other.source)) { + return false; + } + if (startColumn != other.startColumn) { + return false; + } + if (startLine != other.startLine) { + return false; + } + return true; + } + + } + + private static final class LineLocationImpl implements LineLocation { + private final Source source; + private final int line; + + public LineLocationImpl(Source source, int line) { + assert source != null; + this.source = source; + this.line = line; + } + + @Override + public Source getSource() { + return source; + } + + @Override + public int getLineNumber() { + return line; + } + + @Override + public String toString() { + return "SourceLine [" + source.getName() + ", " + line + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + line; + result = prime * result + source.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof LineLocationImpl)) { + return false; + } + LineLocationImpl other = (LineLocationImpl) obj; + if (line != other.line) { + return false; + } + return source.equals(other.source); + } + + } + + /** + * A utility for converting between coordinate systems in a string of text interspersed with + * newline characters. The coordinate systems are: + *

    + *
  • 0-based character offset from the beginning of the text, where newline characters count + * as a single character and the first character in the text occupies position 0.
  • + *
  • 1-based position in the 2D space of lines and columns, in which the first position in the + * text is at (1,1).
  • + *
+ *

+ * This utility is based on positions occupied by characters, not text stream positions as in a + * text editor. The distinction shows up in editors where you can put the cursor just past the + * last character in a buffer; this is necessary, among other reasons, so that you can put the + * edit cursor in a new (empty) buffer. For the purposes of this utility, however, there are no + * character positions in an empty text string and there are no lines in an empty text string. + *

+ * A newline character designates the end of a line and occupies a column position. + *

+ * If the text ends with a character other than a newline, then the characters following the + * final newline character count as a line, even though not newline-terminated. + *

+ * Limitations: + *

    + *
  • Does not handle multiple character encodings correctly.
  • + *
  • Treats tabs as occupying 1 column.
  • + *
  • Does not handle multiple-character line termination sequences correctly.
  • + *
+ */ + private static final class TextMap { + + // 0-based offsets of newline characters in the text, with sentinel + private final int[] nlOffsets; + + // The number of characters in the text, including newlines (which count as 1). + private final int textLength; + + // Is the final text character a newline? + final boolean finalNL; + + /** + * Constructs map permitting translation between 0-based character offsets and 1-based + * lines/columns. + */ + public TextMap(String text) { + this.textLength = text.length(); + final ArrayList lines = new ArrayList<>(); + lines.add(0); + int offset = 0; + + while (offset < text.length()) { + final int nlIndex = text.indexOf('\n', offset); + if (nlIndex >= 0) { + offset = nlIndex + 1; + lines.add(offset); + } else { + break; + } + } + lines.add(Integer.MAX_VALUE); + + nlOffsets = new int[lines.size()]; + for (int line = 0; line < lines.size(); line++) { + nlOffsets[line] = lines.get(line); + } + + finalNL = textLength > 0 && (textLength == nlOffsets[nlOffsets.length - 2]); + } + + /** + * Converts 0-based character offset to 1-based number of the line containing the character. + * + * @throws IllegalArgumentException if the offset is outside the string. + */ + public int offsetToLine(int offset) throws IllegalArgumentException { + if (offset < 0 || offset >= textLength) { + throw new IllegalArgumentException("offset out of bounds"); + } + int line = 1; + while (offset >= nlOffsets[line]) { + line++; + } + return line; + } + + /** + * Converts 0-based character offset to 1-based number of the column occupied by the + * character. + *

+ * Tabs are not expanded; they occupy 1 column. + * + * @throws IllegalArgumentException if the offset is outside the string. + */ + public int offsetToCol(int offset) throws IllegalArgumentException { + return 1 + offset - nlOffsets[offsetToLine(offset) - 1]; + } + + /** + * The number of lines in the text; if characters appear after the final newline, then they + * also count as a line, even though not newline-terminated. + */ + public int lineCount() { + if (textLength == 0) { + return 0; + } + return finalNL ? nlOffsets.length - 2 : nlOffsets.length - 1; + } + + /** + * Converts 1-based line number to the 0-based offset of the line's first character; this + * would be the offset of a newline if the line is empty. + * + * @throws IllegalArgumentException if there is no such line in the text. + */ + public int lineStartOffset(int line) throws IllegalArgumentException { + if (textLength == 0 || lineOutOfRange(line)) { + throw new IllegalArgumentException("line out of bounds"); + } + return nlOffsets[line - 1]; + } + + /** + * Gets the number of characters in a line, identified by 1-based line number; + * does not include the final newline, if any. + * + * @throws IllegalArgumentException if there is no such line in the text. + */ + public int lineLength(int line) throws IllegalArgumentException { + if (textLength == 0 || lineOutOfRange(line)) { + throw new IllegalArgumentException("line out of bounds"); + } + if (line == nlOffsets.length - 1 && !finalNL) { + return textLength - nlOffsets[line - 1]; + } + return (nlOffsets[line] - nlOffsets[line - 1]) - 1; + + } + + /** + * Is the line number out of range. + */ + private boolean lineOutOfRange(int line) { + return line <= 0 || line >= nlOffsets.length || (line == nlOffsets.length - 1 && finalNL); + } + + } + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceFactory.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceFactory.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,546 +0,0 @@ -/* - * Copyright (c) 2013, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.source; - -import java.io.*; -import java.lang.ref.*; -import java.util.*; - -import com.oracle.truffle.api.*; - -/** - * Provider for canonical representations of source code. Three kinds of sources are supported. - *

    - *
  • File: Each file is represented as a canonical object, indexed by the - * absolute, canonical path name of the file. File contents are read lazily and contents - * optionally cached.
  • - *
  • Literal Source: A named text string, whose contents are supplied concretely - * (possibly via an {@link Reader}), can also be used as a source. These are not indexed and should - * be considered value objects; equality is defined based on contents.
  • - *
  • Fake Files: A named text string used for testing; its contents can be - * retrieved by name, unlike literal sources.
  • - *
- *

- * File cache: - *

    - *
  1. File content caching is optional, off by default.
  2. - *
  3. The first access to source file contents will result in the contents being read, and (if - * enabled) cached.
  4. - *
  5. If file contents have been cached, access to contents via {@link Source#getInputStream()} or - * {@link Source#getReader()} will be provided from the cache.
  6. - *
  7. Any access to file contents via the cache will result in a timestamp check and possible cache - * reload.
  8. - *
- */ -public final class SourceFactory { - - // Only files and fake files are indexed. - private static final Map> pathToSource = new HashMap<>(); - - private static boolean fileCacheEnabled = true; - - private SourceFactory() { - } - - /** - * Gets the canonical representation of a source file, whose contents will be read lazily and - * then cached. - * - * @param fileName name - * @param reset forces any existing {@link Source} cache to be cleared, forcing a re-read - * @return canonical representation of the file's contents. - * @throws RuntimeException if the file can not be read - */ - public static Source fromFile(String fileName, boolean reset) throws RuntimeException { - - // TODO (mlvdv) throw IOException - - SourceImpl source = lookup(fileName); - if (source == null) { - final File file = new File(fileName); - String path = null; - if (file.exists()) { - try { - path = file.getCanonicalPath(); - } catch (IOException e) { - throw new RuntimeException("Can't find file " + fileName); - } - } - source = lookup(path); - if (source == null) { - source = new FileSourceImpl(file, fileName, path); - store(path, source); - } - } - if (reset) { - source.reset(); - } - return source; - } - - /** - * Gets the canonical representation of a source file, whose contents will be read lazily and - * then cached. - * - * @param fileName name - * @return canonical representation of the file's contents. - * @throws RuntimeException if the file can not be read - */ - public static Source fromFile(String fileName) throws RuntimeException { - return fromFile(fileName, false); - } - - /** - * Creates a non-canonical source from literal text. - * - * @param code textual source code - * @param description a note about the origin, for error messages and debugging - * @return a newly created, non-indexed source representation - */ - public static Source fromText(String code, String description) { - assert code != null; - return new LiteralSourceImpl(description, code); - } - - /** - * Creates a source whose contents will be read immediately and cached. - * - * @param reader - * @param description a note about the origin, possibly useful for debugging - * @return a newly created, non-indexed source representation - * @throws IOException if reading fails - */ - public static Source fromReader(Reader reader, String description) throws IOException { - return new LiteralSourceImpl(description, read(reader)); - } - - /** - * Creates a source from literal text, but which acts as a file and can be retrieved by name - * (unlike other literal sources); intended for testing. - * - * @param code textual source code - * @param fakeFileName string to use for indexing/lookup - * @return a newly created, source representation, canonical with respect to its name - */ - public static Source asFakeFile(String code, String fakeFileName) { - final SourceImpl source = new LiteralSourceImpl(fakeFileName, code); - store(fakeFileName, source); - return source; - } - - /** - * Enables/disables caching of file contents, disabled by default. Caching of sources - * created from literal text or readers is always enabled. - */ - public static void setFileCaching(boolean enabled) { - fileCacheEnabled = enabled; - } - - private static SourceImpl lookup(String key) { - WeakReference sourceRef = pathToSource.get(key); - return sourceRef == null ? null : sourceRef.get(); - } - - private static void store(String key, SourceImpl source) { - pathToSource.put(key, new WeakReference<>(source)); - } - - private static String read(Reader reader) throws IOException { - final StringBuilder builder = new StringBuilder(); - final char[] buffer = new char[1024]; - - while (true) { - final int n = reader.read(buffer); - if (n == -1) { - break; - } - builder.append(buffer, 0, n); - } - - return builder.toString(); - } - - private abstract static class SourceImpl implements Source { - // TODO (mlvdv) consider canonicalizing and reusing SourceSection instances - // TOOD (mlvdv) connect SourceSections into a spatial tree for fast geometric lookup - - protected TextMap textMap = null; - - protected abstract void reset(); - - public final InputStream getInputStream() { - return new ByteArrayInputStream(getCode().getBytes()); - } - - /** - * Gets the text (not including a possible terminating newline) in a (1-based) numbered - * line. - */ - public final String getCode(int lineNumber) { - checkTextMap(); - final int offset = textMap.lineStartOffset(lineNumber); - final int length = textMap.lineLength(lineNumber); - return getCode().substring(offset, offset + length); - } - - /** - * The number of text lines in the source. - */ - public final int getLineCount() { - return checkTextMap().lineCount(); - } - - /** - * The 1-based number of the line that includes a 0-based character offset. - */ - public final int getLineNumber(int offset) { - return checkTextMap().offsetToLine(offset); - } - - /** - * The 0-based character offset at the start of a (1-based) numbered line. - */ - public final int getLineStartOffset(int lineNumber) { - return checkTextMap().lineStartOffset(lineNumber); - } - - /** - * The number of characters (not counting a possible terminating newline) in a (1-based) - * numbered line. - */ - public final int getLineLength(int lineNumber) { - return checkTextMap().lineLength(lineNumber); - } - - public final SourceSection createSection(String identifier, int startOffset, int sectionLength) throws IllegalArgumentException { - final int codeLength = getCode().length(); - if (!(startOffset >= 0 && sectionLength >= 0 && startOffset + sectionLength <= codeLength)) { - throw new IllegalArgumentException("text positions out of range"); - } - checkTextMap(); - final int startLine = getLineNumber(startOffset); - final int startColumn = startOffset - getLineStartOffset(startLine) + 1; - - return new SourceSectionImpl(this, identifier, startLine, startColumn, startOffset, sectionLength); - } - - public SourceSection createSection(String identifier, int startLine, int startColumn, int sectionLength) { - checkTextMap(); - final int lineStartOffset = textMap.lineStartOffset(startLine); - if (startColumn > textMap.lineLength(startLine)) { - throw new IllegalArgumentException("column out of range"); - } - final int startOffset = lineStartOffset + startColumn - 1; - return new SourceSectionImpl(this, identifier, startLine, startColumn, startOffset, sectionLength); - } - - public SourceSection createSection(String identifier, int startLine, int startColumn, int charIndex, int length) { - return new SourceSectionImpl(this, identifier, startLine, startColumn, charIndex, length); - } - - private TextMap checkTextMap() { - if (textMap == null) { - final String code = getCode(); - if (code == null) { - throw new RuntimeException("can't read file " + getName()); - } - textMap = new TextMap(code); - } - return textMap; - } - } - - private static class LiteralSourceImpl extends SourceImpl { - - private final String name; // Name used originally to describe the source - private final String code; - - public LiteralSourceImpl(String name, String code) { - this.name = name; - this.code = code; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getShortName() { - return name; - } - - @Override - public String getCode() { - return code; - } - - @Override - public String getPath() { - return name; - } - - @Override - public Reader getReader() { - return new StringReader(code); - } - - @Override - protected void reset() { - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + name.hashCode(); - result = prime * result + (code == null ? 0 : code.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof LiteralSourceImpl)) { - return false; - } - LiteralSourceImpl other = (LiteralSourceImpl) obj; - return name.equals(other.name) && code.equals(other.code); - } - - } - - private static class FileSourceImpl extends SourceImpl { - - private final File file; - private final String name; // Name used originally to describe the source - private final String path; // Normalized path description of an actual file - - private String code = null; // A cache of the file's contents - private long timeStamp; // timestamp of the cache in the file system - - public FileSourceImpl(File file, String name, String path) { - this.file = file; - this.name = name; - this.path = path; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getShortName() { - return file.getName(); - } - - @Override - public String getCode() { - if (fileCacheEnabled) { - if (code == null || timeStamp != file.lastModified()) { - try { - code = read(getReader()); - timeStamp = file.lastModified(); - } catch (IOException e) { - } - } - return code; - } - try { - return read(new FileReader(file)); - } catch (IOException e) { - } - return null; - } - - @Override - public String getPath() { - return path; - } - - @Override - public Reader getReader() { - if (code != null && timeStamp == file.lastModified()) { - return new StringReader(code); - } - try { - return new FileReader(file); - } catch (FileNotFoundException e) { - throw new RuntimeException("Can't find file " + path); - } - } - - @Override - protected void reset() { - this.code = null; - } - - } - - private static class SourceSectionImpl implements SourceSection { - - private final Source source; - private final String identifier; - private final int startLine; - private final int startColumn; - private final int charIndex; - private final int charLength; - - /** - * Creates a new object representing a contiguous text section within the source code of a - * guest language program's text. - *

- * The starting location of the section is specified using two different coordinate: - *

    - *
  • (row, column): rows and columns are 1-based, so the first character in a - * source file is at position {@code (1,1)}.
  • - *
  • character index: 0-based offset of the character from the beginning of the - * source, so the first character in a file is at index {@code 0}.
  • - *
- * The newline that terminates each line counts as a single character for the purpose - * of a character index. The (row,column) coordinates of a newline character should never - * appear in a text section. - *

- * - * @param source object representing the complete source program that contains this section - * @param identifier an identifier used when printing the section - * @param startLine the 1-based number of the start line of the section - * @param startColumn the 1-based number of the start column of the section - * @param charIndex the 0-based index of the first character of the section - * @param charLength the length of the section in number of characters - */ - public SourceSectionImpl(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) { - this.source = source; - this.identifier = identifier; - this.startLine = startLine; - this.startColumn = startColumn; - this.charIndex = charIndex; - this.charLength = charLength; - } - - public final Source getSource() { - return source; - } - - public final int getStartLine() { - return startLine; - } - - public final int getStartColumn() { - return startColumn; - } - - public final int getCharIndex() { - return charIndex; - } - - public final int getCharLength() { - return charLength; - } - - public final int getCharEndIndex() { - return charIndex + charLength; - } - - public final String getIdentifier() { - return identifier; - } - - public final String getCode() { - return getSource().getCode().substring(charIndex, charIndex + charLength); - } - - public final String getShortDescription() { - return String.format("%s:%d", source.getShortName(), startLine); - } - - @Override - public String toString() { - return String.format("%s:%d", source.getName(), startLine); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + charIndex; - result = prime * result + charLength; - result = prime * result + ((identifier == null) ? 0 : identifier.hashCode()); - result = prime * result + ((source == null) ? 0 : source.hashCode()); - result = prime * result + startColumn; - result = prime * result + startLine; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof SourceSectionImpl)) { - return false; - } - SourceSectionImpl other = (SourceSectionImpl) obj; - if (charIndex != other.charIndex) { - return false; - } - if (charLength != other.charLength) { - return false; - } - if (identifier == null) { - if (other.identifier != null) { - return false; - } - } else if (!identifier.equals(other.identifier)) { - return false; - } - if (source == null) { - if (other.source != null) { - return false; - } - } else if (!source.equals(other.source)) { - return false; - } - if (startColumn != other.startColumn) { - return false; - } - if (startLine != other.startLine) { - return false; - } - return true; - } - - } - -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceLineLocation.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceLineLocation.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2013, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.source; - -import com.oracle.truffle.api.*; - -/** - * A specification for a location in guest language source, expressed as a line number in a specific - * instance of {@link Source}, suitable for hash table keys with equality defined in terms of - * content. - */ -public class SourceLineLocation implements Comparable { - - private final Source source; - private final int line; - - public SourceLineLocation(Source source, int line) { - assert source != null; - this.source = source; - this.line = line; - } - - public SourceLineLocation(SourceSection sourceSection) { - this(sourceSection.getSource(), sourceSection.getStartLine()); - } - - public Source getSource() { - return source; - } - - public int getLine() { - return line; - } - - @Override - public String toString() { - return "SourceLine [" + source.getName() + ", " + line + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + line; - result = prime * result + source.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof SourceLineLocation)) { - return false; - } - SourceLineLocation other = (SourceLineLocation) obj; - if (line != other.line) { - return false; - } - return source.equals(other.source); - } - - @Override - public int compareTo(Object o) { - final SourceLineLocation other = (SourceLineLocation) o; - final int nameOrder = source.getName().compareTo(other.source.getName()); - if (nameOrder != 0) { - return nameOrder; - } - return Integer.compare(line, other.line); - } - -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceSection.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.source; + +/** + * Description of contiguous section of text within a {@link Source} of program code; supports + * multiple modes of access to the text and its location. A special {@linkplain NullSourceSection + * null subtype} should be used for code that is not available from source, e.g language builtins. + * + * @see Source#createSection(String, int, int, int, int) + * @see Source#createSection(String, int, int, int) + * @see Source#createSection(String, int, int) + * @see Source#createSection(String, int) + * @see NullSourceSection + */ +public interface SourceSection { + + // TODO support alternate text representations/encodings + + /** + * Representation of the source program that contains this section. + * + * @return the source object + */ + Source getSource(); + + /** + * Returns 1-based line number of the first character in this section (inclusive). + * + * @return the starting line number + */ + int getStartLine(); + + /** + * Gets a representation of the first line of the section, suitable for a hash key. + */ + LineLocation getLineLocation(); + + /** + * Returns the 1-based column number of the first character in this section (inclusive). + * + * @return the starting column number + */ + int getStartColumn(); + + /** + * Returns the 0-based index of the first character in this section. + * + * @return the starting character index + */ + int getCharIndex(); + + /** + * Returns the length of this section in characters. + * + * @return the number of characters in the section + */ + int getCharLength(); + + /** + * Returns the index of the text position immediately following the last character in the + * section. + * + * @return the end position of the section + */ + int getCharEndIndex(); + + /** + * Returns terse text describing this source section, typically used for printing the section. + * + * @return the identifier of the section + */ + String getIdentifier(); + + /** + * Returns text described by this section. + * + * @return the code as a String object + */ + String getCode(); + + /** + * Returns a short description of the source section, using just the file name, rather than its + * full path. + * + * @return a short description of the source section + */ + String getShortDescription(); + +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/TextMap.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/TextMap.java Mon Jun 30 08:50:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.source; - -import java.util.*; - -/** - * A utility for converting between coordinate systems in a string of text interspersed with newline - * characters. The coordinate systems are: - *
    - *
  • 0-based character offset from the beginning of the text, where newline characters count as a - * single character and the first character in the text occupies position 0.
  • - *
  • 1-based position in the 2D space of lines and columns, in which the first position in the - * text is at (1,1).
  • - *
- *

- * This utility is based on positions occupied by characters, not text stream positions as in a text - * editor. The distinction shows up in editors where you can put the cursor just past the last - * character in a buffer; this is necessary, among other reasons, so that you can put the edit - * cursor in a new (empty) buffer. For the purposes of this utility, however, there are no character - * positions in an empty text string and there are no lines in an empty text string. - *

- * A newline character designates the end of a line and occupies a column position. - *

- * If the text ends with a character other than a newline, then the characters following the final - * newline character count as a line, even though not newline-terminated. - *

- * Limitations: - *

    - *
  • Does not handle multiple character encodings correctly.
  • - *
  • Treats tabs as occupying 1 column.
  • - *
  • Does not handle multiple-character line termination sequences correctly.
  • - *
- */ -public final class TextMap { - - // 0-based offsets of newline characters in the text, with sentinel - private final int[] nlOffsets; - - // The number of characters in the text, including newlines (which count as 1). - private final int textLength; - - // Is the final text character a newline? - final boolean finalNL; - - /** - * Constructs map permitting translation between 0-based character offsets and 1-based - * lines/columns. - */ - public TextMap(String text) { - this.textLength = text.length(); - final ArrayList lines = new ArrayList<>(); - lines.add(0); - int offset = 0; - - while (offset < text.length()) { - final int nlIndex = text.indexOf('\n', offset); - if (nlIndex >= 0) { - offset = nlIndex + 1; - lines.add(offset); - } else { - break; - } - } - lines.add(Integer.MAX_VALUE); - - nlOffsets = new int[lines.size()]; - for (int line = 0; line < lines.size(); line++) { - nlOffsets[line] = lines.get(line); - } - - finalNL = textLength > 0 && (textLength == nlOffsets[nlOffsets.length - 2]); - } - - /** - * Converts 0-based character offset to 1-based number of the line containing the character. - * - * @throws IllegalArgumentException if the offset is outside the string. - */ - public int offsetToLine(int offset) throws IllegalArgumentException { - if (offset < 0 || offset >= textLength) { - throw new IllegalArgumentException("offset out of bounds"); - } - int line = 1; - while (offset >= nlOffsets[line]) { - line++; - } - return line; - } - - /** - * Converts 0-based character offset to 1-based number of the column occupied by the character. - *

- * Tabs are not expanded; they occupy 1 column. - * - * @throws IllegalArgumentException if the offset is outside the string. - */ - public int offsetToCol(int offset) throws IllegalArgumentException { - return 1 + offset - nlOffsets[offsetToLine(offset) - 1]; - } - - /** - * The number of lines in the text; if characters appear after the final newline, then they also - * count as a line, even though not newline-terminated. - */ - public int lineCount() { - if (textLength == 0) { - return 0; - } - return finalNL ? nlOffsets.length - 2 : nlOffsets.length - 1; - } - - /** - * Converts 1-based line number to the 0-based offset of the line's first character; this would - * be the offset of a newline if the line is empty. - * - * @throws IllegalArgumentException if there is no such line in the text. - */ - public int lineStartOffset(int line) throws IllegalArgumentException { - if (textLength == 0 || lineOutOfRange(line)) { - throw new IllegalArgumentException("line out of bounds"); - } - return nlOffsets[line - 1]; - } - - /** - * Gets the number of characters in a line, identified by 1-based line number; does not - * include the final newline, if any. - * - * @throws IllegalArgumentException if there is no such line in the text. - */ - public int lineLength(int line) throws IllegalArgumentException { - if (textLength == 0 || lineOutOfRange(line)) { - throw new IllegalArgumentException("line out of bounds"); - } - if (line == nlOffsets.length - 1 && !finalNL) { - return textLength - nlOffsets[line - 1]; - } - return (nlOffsets[line] - nlOffsets[line - 1]) - 1; - - } - - /** - * Is the line number out of range. - */ - private boolean lineOutOfRange(int line) { - return line <= 0 || line >= nlOffsets.length || (line == nlOffsets.length - 1 && finalNL); - } - -} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.utilities; + +import java.util.*; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; + +/** + * Helper function that allows to dump the AST during creation to a JSON format. + */ +public class JSONHelper { + + private static StringBuilder AstJsonDumpBuilder = new StringBuilder(); + + public static void dumpNewChild(Node parentNode, Node childNode) { + if (AstJsonDumpBuilder != null) { + AstJsonDumpBuilder.append("{ \"action\": \"insertNode\", \"parentId\": \"" + getID(parentNode) + "\", \"newId\": \"" + getID(childNode) + "\" },\n"); + } + } + + public static void dumpReplaceChild(Node oldNode, Node newNode, CharSequence reason) { + if (AstJsonDumpBuilder != null) { + AstJsonDumpBuilder.append("{ \"action\": \"replaceNode\", \"oldId\": \"" + getID(oldNode) + "\", \"newId\": \"" + getID(newNode) + "\", \"reason\": " + quote(reason) + " },\n"); + } + } + + public static void dumpNewNode(Node newNode) { + if (AstJsonDumpBuilder != null) { + AstJsonDumpBuilder.append("{ \"action\": \"createNode\", \"newId\": \"" + getID(newNode) + "\", \"type\": \"" + getType(newNode) + "\", \"description\": \"" + newNode.getDescription() + + "\", \"language\": \"" + newNode.getLanguage() + "\"" + getSourceSectionInfo(newNode) + " },\n"); + } + } + + private static String getSourceSectionInfo(Node newNode) { + SourceSection sourceSection = newNode.getSourceSection(); + if (sourceSection != null) { + return ", \"identifier\": \"" + sourceSection.getIdentifier() + "\" "; + } else { + return ""; + } + } + + public static String getResult() { + return AstJsonDumpBuilder.toString(); + } + + private static String getID(Node newChild) { + return String.valueOf(newChild.hashCode()); + } + + private static String getType(Node node) { + return node.getClass().getSimpleName(); + } + + private static String quote(CharSequence value) { + StringBuilder builder = new StringBuilder(value.length() + 2); + builder.append('"'); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + switch (c) { + case '"': + builder.append("\\\""); + break; + case '\\': + builder.append("\\\\"); + break; + case '\b': + builder.append("\\b"); + break; + case '\f': + builder.append("\\f"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + case '\t': + builder.append("\\t"); + break; + default: { + if (c < ' ') { + builder.append("\\u00"); + builder.append(Character.forDigit((c >> 4) & 0xF, 16)); + builder.append(Character.forDigit(c & 0xF, 16)); + } else { + builder.append(c); + } + } + } + } + builder.append('"'); + return builder.toString(); + } + + public static void restart() { + AstJsonDumpBuilder = new StringBuilder(); + } + + public static JsonObjectBuilder object() { + return new JsonObjectBuilder(); + } + + public static JsonArrayBuilder array() { + return new JsonArrayBuilder(); + } + + public static abstract class JsonStringBuilder { + @Override + public final String toString() { + StringBuilder sb = new StringBuilder(); + appendTo(sb); + return sb.toString(); + } + + protected abstract void appendTo(StringBuilder sb); + + protected static void appendValue(StringBuilder sb, Object value) { + if (value instanceof JsonStringBuilder) { + ((JsonStringBuilder) value).appendTo(sb); + } else if (value instanceof Integer || value instanceof Boolean || value == null) { + sb.append(value); + } else { + sb.append(quote(String.valueOf(value))); + } + } + } + + public static final class JsonObjectBuilder extends JsonStringBuilder { + private final Map contents = new LinkedHashMap<>(); + + private JsonObjectBuilder() { + } + + public JsonObjectBuilder add(String key, String value) { + contents.put(key, value); + return this; + } + + public JsonObjectBuilder add(String key, Number value) { + contents.put(key, value); + return this; + } + + public JsonObjectBuilder add(String key, Boolean value) { + contents.put(key, value); + return this; + } + + public JsonObjectBuilder add(String key, JsonStringBuilder value) { + contents.put(key, value); + return this; + } + + @Override + protected void appendTo(StringBuilder sb) { + sb.append("{"); + boolean comma = false; + for (Map.Entry entry : contents.entrySet()) { + if (comma) { + sb.append(", "); + } + sb.append(quote(entry.getKey())); + sb.append(": "); + appendValue(sb, entry.getValue()); + comma = true; + } + sb.append("}"); + } + } + + public static final class JsonArrayBuilder extends JsonStringBuilder { + private final List contents = new ArrayList<>(); + + private JsonArrayBuilder() { + } + + public JsonArrayBuilder add(String value) { + contents.add(value); + return this; + } + + public JsonArrayBuilder add(Number value) { + contents.add(value); + return this; + } + + public JsonArrayBuilder add(Boolean value) { + contents.add(value); + return this; + } + + public JsonArrayBuilder add(JsonStringBuilder value) { + contents.add(value); + return this; + } + + @Override + protected void appendTo(StringBuilder sb) { + sb.append("["); + boolean comma = false; + for (Object value : contents) { + if (comma) { + sb.append(", "); + } + appendValue(sb, value); + comma = true; + } + sb.append("]"); + } + } +} diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,6 +36,7 @@ import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.Node.Children; +import com.oracle.truffle.api.source.*; /** * THIS IS NOT PUBLIC API. diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java --- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Mon Jun 30 12:02:19 2014 +0200 @@ -36,7 +36,6 @@ import org.junit.runners.*; import org.junit.runners.model.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.runtime.*; @@ -156,7 +155,7 @@ PrintStream printer = new PrintStream(out); try { SLContext context = new SLContext(new BufferedReader(new StringReader(repeat(testCase.testInput, REPEATS))), printer); - final Source source = SourceFactory.fromText(readAllLines(testCase.path), testCase.sourceName); + final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName); SLMain.run(context, source, null, REPEATS); String actualOutput = new String(out.toByteArray()); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Mon Jun 30 12:02:19 2014 +0200 @@ -123,9 +123,9 @@ Source source; if (args.length == 0) { - source = SourceFactory.fromReader(new InputStreamReader(System.in), "stdin"); + source = Source.fromReader(new InputStreamReader(System.in), "stdin"); } else { - source = SourceFactory.fromFile(args[0]); + source = Source.fromFileName(args[0]); } int repeats = 1; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Mon Jun 30 12:02:19 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.truffle.sl.builtins; import com.oracle.truffle.api.CompilerDirectives.SlowPath; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; @@ -45,7 +44,7 @@ @SlowPath private static void doDefineFunction(SLContext context, String code) { - Source source = SourceFactory.fromText(code, "[defineFunction]"); + Source source = Source.fromText(code, "[defineFunction]"); /* The same parsing code as for parsing the initial source. */ Parser.parseSL(context, source); } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -41,10 +41,6 @@ @Children private final SLStatementNode[] bodyNodes; public SLBlockNode(SLStatementNode[] bodyNodes) { - /* - * It is a Truffle requirement to call adoptChildren(), which performs all the necessary - * steps to add the new children to the node tree. - */ this.bodyNodes = bodyNodes; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -50,10 +50,6 @@ private final BranchProfile nullTaken = new BranchProfile(); public SLFunctionBodyNode(SLStatementNode bodyNode) { - /* - * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps - * to add the new child to the node tree. - */ this.bodyNode = bodyNode; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -53,10 +53,6 @@ private final BranchProfile elseTaken = new BranchProfile(); public SLIfNode(SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { - /* - * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps - * to add the new child to the node tree. - */ this.conditionNode = conditionNode; this.thenPartNode = thenPartNode; this.elsePartNode = elsePartNode; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Mon Jun 30 12:02:19 2014 +0200 @@ -51,10 +51,6 @@ private final BranchProfile breakTaken = new BranchProfile(); public SLWhileNode(SLExpressionNode conditionNode, SLStatementNode bodyNode) { - /* - * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps - * to add the new child to the node tree. - */ this.conditionNode = conditionNode; this.bodyNode = bodyNode; } diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Mon Jun 30 12:02:19 2014 +0200 @@ -30,7 +30,7 @@ import java.util.*; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.runtime.*; diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Mon Jun 30 12:02:19 2014 +0200 @@ -27,7 +27,7 @@ import java.util.*; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.runtime.*; @@ -52,7 +52,7 @@ public final Scanner scanner; public final Errors errors; private final SLNodeFactory factory; - + public Parser(SLContext context, Source source) { this.scanner = new Scanner(source.getInputStream()); this.factory = new SLNodeFactory(context, source); @@ -133,39 +133,39 @@ void Function() { Expect(4); Expect(1); - factory.startFunction(t); + factory.startFunction(t); Expect(5); if (la.kind == 1) { Get(); - factory.addFormalParameter(t); + factory.addFormalParameter(t); while (la.kind == 6) { Get(); Expect(1); - factory.addFormalParameter(t); + factory.addFormalParameter(t); } } Expect(7); SLStatementNode body = Block(false); - factory.finishFunction(body); + factory.finishFunction(body); } SLStatementNode Block(boolean inLoop) { SLStatementNode result; factory.startBlock(); - List body = new ArrayList<>(); + List body = new ArrayList<>(); Expect(8); while (StartOf(1)) { SLStatementNode s = Statement(inLoop); - body.add(s); + body.add(s); } Expect(9); - result = factory.finishBlock(body); + result = factory.finishBlock(body); return result; } SLStatementNode Statement(boolean inLoop) { SLStatementNode result; - result = null; + result = null; switch (la.kind) { case 13: { result = WhileStatement(); @@ -173,13 +173,13 @@ } case 10: { Get(); - if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } + if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } Expect(11); break; } case 12: { Get(); - if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } + if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } Expect(11); break; } @@ -205,11 +205,11 @@ SLStatementNode result; Expect(13); Expect(5); - Token whileToken = t; + Token whileToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode body = Block(true); - result = factory.createWhile(whileToken, condition, body); + result = factory.createWhile(whileToken, condition, body); return result; } @@ -217,16 +217,16 @@ SLStatementNode result; Expect(14); Expect(5); - Token ifToken = t; + Token ifToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode thenPart = Block(inLoop); - SLStatementNode elsePart = null; + SLStatementNode elsePart = null; if (la.kind == 15) { Get(); elsePart = Block(inLoop); } - result = factory.createIf(ifToken, condition, thenPart, elsePart); + result = factory.createIf(ifToken, condition, thenPart, elsePart); return result; } @@ -234,11 +234,11 @@ SLStatementNode result; Expect(16); Token returnToken = t; - SLExpressionNode value = null; + SLExpressionNode value = null; if (StartOf(2)) { value = Expression(); } - result = factory.createReturn(returnToken, value); + result = factory.createReturn(returnToken, value); Expect(11); return result; } @@ -248,9 +248,9 @@ result = LogicTerm(); while (la.kind == 17) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicTerm(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -260,9 +260,9 @@ result = LogicFactor(); while (la.kind == 18) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicFactor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -297,9 +297,9 @@ break; } } - Token op = t; + Token op = t; SLExpressionNode right = Arithmetic(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -313,9 +313,9 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Term(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -329,47 +329,47 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Factor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } SLExpressionNode Factor() { SLExpressionNode result; - result = null; + result = null; if (la.kind == 1) { Get(); - Token nameToken = t; + Token nameToken = t; if (la.kind == 5) { Get(); List parameters = new ArrayList<>(); - SLExpressionNode parameter; + SLExpressionNode parameter; if (StartOf(2)) { parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); while (la.kind == 6) { Get(); parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); } } - result = factory.createCall(nameToken, parameters); + result = factory.createCall(nameToken, parameters); Expect(7); } else if (la.kind == 29) { Get(); SLExpressionNode value = Expression(); - result = factory.createAssignment(nameToken, value); + result = factory.createAssignment(nameToken, value); } else if (StartOf(4)) { - result = factory.createRead(nameToken); + result = factory.createRead(nameToken); } else SynErr(32); } else if (la.kind == 2) { Get(); - result = factory.createStringLiteral(t); + result = factory.createStringLiteral(t); } else if (la.kind == 3) { Get(); - result = factory.createNumericLiteral(t); + result = factory.createNumericLiteral(t); } else if (la.kind == 5) { Get(); result = Expression(); diff -r 51f392557124 -r 5f01f7c48d40 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Mon Jun 30 08:50:26 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Mon Jun 30 12:02:19 2014 +0200 @@ -25,9 +25,9 @@ import java.math.*; import java.util.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.nodes.call.*; import com.oracle.truffle.sl.nodes.controlflow.*; diff -r 51f392557124 -r 5f01f7c48d40 make/Makefile --- a/make/Makefile Mon Jun 30 08:50:26 2014 +0200 +++ b/make/Makefile Mon Jun 30 12:02:19 2014 +0200 @@ -193,7 +193,7 @@ $(GRAAL_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_DIR=$(GRAAL_DIR) BUILD_FLAVOR=$(@:%graal=%) VM_TARGET=$@ generic_buildgraal $(ALT_OUT) + $(MAKE) BUILD_DIR=$(GRAAL_DIR) BUILD_FLAVOR=$(@:%graal=%) VM_TARGET=$@ INCLUDE_GRAAL=true generic_buildgraal $(ALT_OUT) # Install hotspot script in build directory HOTSPOT_SCRIPT=$(BUILD_DIR)/$(BUILD_FLAVOR)/hotspot diff -r 51f392557124 -r 5f01f7c48d40 mx/mx_graal.py --- a/mx/mx_graal.py Mon Jun 30 08:50:26 2014 +0200 +++ b/mx/mx_graal.py Mon Jun 30 12:02:19 2014 +0200 @@ -168,7 +168,6 @@ rmIfExists(join(_graal_home, 'build')) rmIfExists(join(_graal_home, 'build-nograal')) rmIfExists(_jdksDir()) - rmIfExists(mx.distribution('GRAAL').path) def export(args): """create archives of builds split by vmbuild and vm""" @@ -506,14 +505,23 @@ jreLibDir = join(jdks, e, 'jre', 'lib') if exists(jreLibDir): def install(srcJar, dstDir): - # do a copy and then a move to get atomic updating (on Unix) name = os.path.basename(srcJar) - fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dstDir) - shutil.copyfile(srcJar, tmp) - os.close(fd) dstJar = join(dstDir, name) - shutil.move(tmp, dstJar) - os.chmod(dstJar, JDK_UNIX_PERMISSIONS) + if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true': + # Using symlinks is much faster than copying but may + # cause issues if graal.jar is being updated while + # the VM is running. + if not os.path.islink(dstJar) or not os.path.realpath(dstJar) == srcJar: + if exists(dstJar): + os.remove(dstJar) + os.symlink(srcJar, dstJar) + else: + # do a copy and then a move to get atomic updating (on Unix) + fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dstDir) + shutil.copyfile(srcJar, tmp) + os.close(fd) + shutil.move(tmp, dstJar) + os.chmod(dstJar, JDK_UNIX_PERMISSIONS) install(graalJar, jreLibDir) if graalDist.sourcesPath: @@ -802,13 +810,19 @@ env.pop('LD_LIBRARY_PATH', None) env.pop('CLASSPATH', None) - if mx._opts.verbose: - # Issue an env prefix that can be used to run the make on the command line - envPrefix = ' '.join([key + '=' + env[key] for key in env.iterkeys() if not os.environ.has_key(key) or env[key] != os.environ[key]]) - if len(envPrefix): - mx.log('env ' + envPrefix + ' \\') + # Issue an env prefix that can be used to run the make on the command line + if not mx._opts.verbose: + mx.log('--------------- make command line ----------------------') + + envPrefix = ' '.join([key + '=' + env[key] for key in env.iterkeys() if not os.environ.has_key(key) or env[key] != os.environ[key]]) + if len(envPrefix): + mx.log('env ' + envPrefix + ' \\') runCmd.append(build + buildSuffix) + + if not mx._opts.verbose: + mx.log(' '.join(runCmd)) + mx.log('--------------------------------------------------------') mx.run(runCmd, err=filterXusage, env=env) jvmCfg = _vmCfgInJdk(jdk) @@ -1798,7 +1812,7 @@ path = join(_graal_home, 'lib', 'hcfdis-1.jar') if not exists(path): - mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-1.jar']) + mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-2.jar']) mx.run_java(['-jar', path] + args.files) if args.map is not None: @@ -1854,6 +1868,20 @@ def isGraalEnabled(vm): return vm != 'original' and not vm.endswith('nograal') +def jol(args): + """Java Object Layout""" + jolurl = "http://lafo.ssw.uni-linz.ac.at/truffle/jol/jol-internals.jar" + joljar = "lib/jol-internals.jar" + if not exists(joljar): + mx.download(joljar, [jolurl]) + + candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) + if len(candidates) > 10: + print "Found %d candidates. Please be more precise." % (len(candidates)) + return + + vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates) + def site(args): """create a website containing javadoc and the project dependency graph""" @@ -2080,7 +2108,8 @@ 'vmfg': [vmfg, '[-options] class [args...]'], 'deoptalot' : [deoptalot, '[n]'], 'longtests' : [longtests, ''], - 'sl' : [sl, '[SL args|@VM options]'] + 'sl' : [sl, '[SL args|@VM options]'], + 'jol' : [jol, ''], } mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) diff -r 51f392557124 -r 5f01f7c48d40 mx/projects --- a/mx/projects Mon Jun 30 08:50:26 2014 +0200 +++ b/mx/projects Mon Jun 30 12:02:19 2014 +0200 @@ -5,30 +5,30 @@ jrelibrary@JFR@jar=jfr.jar library@JUNIT@path=lib/junit-4.11.jar -library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar +library@JUNIT@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/junit-4.11.jar,http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar library@JUNIT@sha1=4e031bb61df09069aeb2bffb4019e7a5034a4ee0 library@JUNIT@eclipse.container=org.eclipse.jdt.junit.JUNIT_CONTAINER/4 library@JUNIT@sourcePath=lib/junit-4.11-sources.jar -library@JUNIT@sourceUrls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11-sources.jar +library@JUNIT@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/junit-4.11-sources.jar,http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11-sources.jar library@JUNIT@sourceSha1=28e0ad201304e4a4abf999ca0570b7cffc352c3c library@JUNIT@dependencies=HAMCREST library@HAMCREST@path=lib/hamcrest-core-1.3.jar -library@HAMCREST@urls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar +library@HAMCREST@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/hamcrest-core-1.3.jar,http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar library@HAMCREST@sha1=42a25dc3219429f0e5d060061f71acb49bf010a0 library@HAMCREST@sourcePath=lib/hamcrest-core-1.3-sources.jar -library@HAMCREST@sourceUrls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar +library@HAMCREST@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/hamcrest-core-1.3-sources.jar,http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar library@HAMCREST@sourceSha1=1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar -library@FINDBUGS@path=lib/findbugs-3.0.0-dev-20131204-e3cbbd5.jar -library@FINDBUGS@urls=jar:http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-dev-20131204-e3cbbd5.zip/download!/findbugs-3.0.0-dev-20131204-e3cbbd5/lib/findbugs.jar -library@FINDBUGS@sha1=539fdc73ef5f65a85c94687f6ec77dcd8493f8c1 +library@FINDBUGS@path=lib/findbugs-3.0.0-rc1.jar +library@FINDBUGS@urls=jar:http://lafo.ssw.uni-linz.ac.at/graal-external-deps/findbugs-3.0.0-rc1.zip!/findbugs-3.0.0-rc1/lib/findbugs.jar,jar:http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-rc1.zip/download!/findbugs-3.0.0-rc1/lib/findbugs.jar +library@FINDBUGS@sha1=3a0a592608b41b57a77721b933b7bb78fcf64015 library@DACAPO@path=lib/dacapo-9.12-bach.jar -library@DACAPO@urls=http://softlayer.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar +library@DACAPO@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/dacapo-9.12-bach.jar,http://softlayer.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar library@DACAPO@sha1=2626a9546df09009f6da0df854e6dc1113ef7dd4 library@JACOCOAGENT@path=lib/jacocoagent.jar @@ -40,29 +40,30 @@ library@JACOCOREPORT@sha1=a630436391832d697a12c8f7daef8655d7a1efd2 library@DACAPO_SCALA@path=lib/dacapo-scala-0.1.0-20120216.jar -library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar +library@DACAPO_SCALA@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/dacapo-scala-0.1.0-20120216.jar,http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar library@DACAPO_SCALA@sha1=59b64c974662b5cf9dbd3cf9045d293853dd7a51 library@OKRA@path=lib/okra-1.9.jar -library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9.jar +library@OKRA@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9.jar library@OKRA@sha1=df450b04882e6b5a365299e2cbf1622038ae880e library@OKRA@sourcePath=lib/okra-1.9-src.jar -library@OKRA@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-src.jar +library@OKRA@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9-src.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9-src.jar library@OKRA@sourceSha1=41dcda5197ca4d87bc94e4d7b5a90e7f22667756 library@OKRA_WITH_SIM@path=lib/okra-1.9-with-sim.jar -library@OKRA_WITH_SIM@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim.jar +library@OKRA_WITH_SIM@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9-with-sim.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim.jar library@OKRA_WITH_SIM@sha1=816fa24814cf51c02f9c05477447bb55a152b388 library@OKRA_WITH_SIM@sourcePath=lib/okra-1.9-with-sim-src.jar library@OKRA_WITH_SIM@sourceSha1=1628919457999a8479d9f39845865de527dbd523 -library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim-src.jar +library@OKRA_WITH_SIM@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9-with-sim-src.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim-src.jar library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar -library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-c7e3525a6b90.jar -library@JAVA_ALLOCATION_INSTRUMENTER@sha1=128eb20a4cd3362a4d8b94614e66647808a2e37c +library@JAVA_ALLOCATION_INSTRUMENTER@sourcePath=lib/java-allocation-instrumenter.jar +library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-8f0db117e64e.jar +library@JAVA_ALLOCATION_INSTRUMENTER@sha1=476d9a44cd19d6b55f81571077dfa972a4f8a083 library@VECMATH@path=lib/vecmath-1.3.1.jar -library@VECMATH@urls=http://mirrors.ibiblio.org/pub/mirrors/maven/java3d/jars/vecmath-1.3.1.jar +library@VECMATH@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/vecmath-1.3.1.jar,http://mirrors.ibiblio.org/pub/mirrors/maven/java3d/jars/vecmath-1.3.1.jar library@VECMATH@sha1=a0ae4f51da409fa0c20fa0ca59e6bbc9413ae71d distribution@GRAAL@path=graal.jar diff -r 51f392557124 -r 5f01f7c48d40 mxtool/mx.py --- a/mxtool/mx.py Mon Jun 30 08:50:26 2014 +0200 +++ b/mxtool/mx.py Mon Jun 30 12:02:19 2014 +0200 @@ -102,7 +102,8 @@ existingSource = zf._provenance.get(arcname, None) isOverwrite = False if existingSource and existingSource != source: - log('warning: ' + self.path + ': avoid overwrite of ' + arcname + '\n new: ' + source + '\n old: ' + existingSource) + if arcname[-1] != os.path.sep: + logv('warning: ' + self.path + ': avoid overwrite of ' + arcname + '\n new: ' + source + '\n old: ' + existingSource) isOverwrite = True zf._provenance[arcname] = source return isOverwrite @@ -1978,8 +1979,9 @@ if not self.jdtJar: mainJava = java() if not args.error_prone: - self.logCompilation('javac') - javacCmd = [mainJava.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()] + javac = args.alt_javac if args.alt_javac else mainJava.javac + self.logCompilation('javac' if not args.alt_javac else args.alt_javac) + javacCmd = [javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()] if jdk.debug_port is not None: javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)] javacCmd += processorArgs @@ -2063,10 +2065,11 @@ parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects') parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors') parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings') + parser.add_argument('--alt-javac', dest='alt_javac', help='path to alternative javac executable', metavar='') compilerSelect = parser.add_mutually_exclusive_group() compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='') compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler', default=_defaultEcjPath(), metavar='') - compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not') + compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac whether ecj.jar is found or not') if suppliedParser: parser.add_argument('remainder', nargs=REMAINDER, metavar='...') @@ -2846,6 +2849,7 @@ parser = parser if suppliedParser else ArgumentParser(prog='mx clean') parser.add_argument('--no-native', action='store_false', dest='native', help='do not clean native projects') parser.add_argument('--no-java', action='store_false', dest='java', help='do not clean Java projects') + parser.add_argument('--no-dist', action='store_false', dest='dist', help='do not delete distributions') args = parser.parse_args(args) @@ -2855,6 +2859,10 @@ path = unicode("\\\\?\\" + dirPath) shutil.rmtree(path) + def _rmIfExists(name): + if os.path.isfile(name): + os.unlink(name) + for p in projects_opt_limit_to_suites(): if p.native: if args.native: @@ -2878,6 +2886,12 @@ if config.exists(): os.unlink(config.path) + if args.dist: + for d in _dists.keys(): + log('Removing distribution {0}...'.format(d)) + _rmIfExists(distribution(d).path) + _rmIfExists(distribution(d).sourcesPath) + if suppliedParser: return args @@ -4149,9 +4163,8 @@ projectDirs = [p.dir for p in suite.projects] for dirpath, dirnames, files in os.walk(suite.dir): if dirpath == suite.dir: - # no point in traversing .hg - if '.hg' in dirnames: - dirnames.remove('.hg') + # no point in traversing .hg or lib/ + dirnames[:] = [d for d in dirnames if d not in ['.hg', 'lib']] elif dirpath in projectDirs: # don't traverse subdirs of an existing project in this suite dirnames[:] = [] @@ -4474,7 +4487,7 @@ return kwargs.pop(0) return None -def findclass(args, logToConsole=True): +def findclass(args, logToConsole=True, matcher=lambda string, classname: string in classname): """find all classes matching a given substring""" matches = [] for entry, filename in classpath_walk(includeBootClasspath=True): @@ -4485,7 +4498,7 @@ classname = filename.replace(os.sep, '.') classname = classname[:-len('.class')] for a in args: - if a in classname: + if matcher(a, classname): matches.append(classname) if logToConsole: log(classname) diff -r 51f392557124 -r 5f01f7c48d40 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/cpu/x86/vm/assembler_x86.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -1824,7 +1824,7 @@ void Assembler::movsbl(Register dst, Register src) { // movsxb NOT_LP64(assert(src->has_byte_register(), "must have byte register")); - int encode = prefix_and_encode(dst->encoding(), src->encoding(), true); + int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true); emit_int8(0x0F); emit_int8((unsigned char)0xBE); emit_int8((unsigned char)(0xC0 | encode)); @@ -1917,7 +1917,7 @@ void Assembler::movzbl(Register dst, Register src) { // movzxb NOT_LP64(assert(src->has_byte_register(), "must have byte register")); - int encode = prefix_and_encode(dst->encoding(), src->encoding(), true); + int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true); emit_int8(0x0F); emit_int8((unsigned char)0xB6); emit_int8(0xC0 | encode); @@ -4562,12 +4562,12 @@ return reg_enc; } -int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) { +int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) { if (dst_enc < 8) { if (src_enc >= 8) { prefix(REX_B); src_enc -= 8; - } else if (byteinst && src_enc >= 4) { + } else if ((src_is_byte && src_enc >= 4) || (dst_is_byte && dst_enc >= 4)) { prefix(REX); } } else { diff -r 51f392557124 -r 5f01f7c48d40 src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/cpu/x86/vm/assembler_x86.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -556,7 +556,10 @@ int prefix_and_encode(int reg_enc, bool byteinst = false); int prefixq_and_encode(int reg_enc); - int prefix_and_encode(int dst_enc, int src_enc, bool byteinst = false); + int prefix_and_encode(int dst_enc, int src_enc) { + return prefix_and_encode(dst_enc, false, src_enc, false); + } + int prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte); int prefixq_and_encode(int dst_enc, int src_enc); void prefix(Register reg); diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/gpu_hsail.cpp --- a/src/gpu/hsail/vm/gpu_hsail.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -66,11 +66,11 @@ JNINativeMethod Hsail::HSAIL_methods[] = { {CC"initialize", CC"()Z", FN_PTR(Hsail::initialize)}, {CC"generateKernel", CC"([B" STRING ")J", FN_PTR(Hsail::generate_kernel)}, - {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT"["JLTHREAD"I[I)Z", FN_PTR(Hsail::execute_kernel_void_1d)}, + {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"["JLTHREAD"I[I)Z", FN_PTR(Hsail::execute_kernel_void_1d)}, }; -void * Hsail::_device_context = NULL; -jint Hsail::_notice_safepoints = false; +void* Hsail::_device_context = NULL; +jint Hsail::_notice_safepoints = false; Hsail::okra_create_context_func_t Hsail::_okra_create_context; Hsail::okra_create_kernel_func_t Hsail::_okra_create_kernel; @@ -85,43 +85,6 @@ Hsail::okra_clearargs_func_t Hsail::_okra_clearargs; Hsail::okra_register_heap_func_t Hsail::_okra_register_heap; -struct Stats { - int _dispatches; - int _deopts; - int _overflows; - bool _changeSeen; - -public: - Stats() { - _dispatches = _deopts = _overflows = 0; - _changeSeen = false; - } - - void incDeopts() { - _deopts++; - _changeSeen = true; - } - void incOverflows() { - _overflows++; - _changeSeen = true; - } - - void finishDispatch() { - _dispatches++; - if (_changeSeen) { - // print(); - _changeSeen = false; - } - } - - void print() { - tty->print_cr("Disp=%d, Deopts=%d, Ovflows=%d", _dispatches, _deopts, _overflows); - } - -}; - -static Stats kernelStats; - //static jint in_kernel = 0; void Hsail::notice_safepoints() { @@ -145,7 +108,7 @@ _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity()); } -GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, jobject oops_save, +GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, jobject donor_threads, jint allocBytesPerWorkitem, jobject oop_map_array)) ResourceMark rm; @@ -162,10 +125,10 @@ SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); } -return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, oops_save, donor_threads, allocBytesPerWorkitem, oop_map_array, CHECK_0); +return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, donor_threads, allocBytesPerWorkitem, oop_map_array, CHECK_0); GPU_END -static void showRanges(jboolean *a, int len) { +static void showRanges(jboolean* a, int len) { // show ranges bool lookFor = true; for (int i = 0; i < len; i++) { @@ -182,225 +145,36 @@ } } -// fill and retire old tlab and get a new one -// if we can't get one, no problem someone will eventually do a gc -void Hsail::getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail) { - tlab->clear_before_allocation(); // fill and retire old tlab (will also check for null) - - // get a size for a new tlab that is at least tlabMinHsail. - size_t new_tlab_size = tlab->compute_size(tlabMinHsail); - if (new_tlab_size == 0) return; - - HeapWord* tlab_start = Universe::heap()->allocate_new_tlab(new_tlab_size); - if (tlab_start == NULL) return; - - // ..and clear it if required - if (ZeroTLAB) { - Copy::zero_to_words(tlab_start, new_tlab_size); - } - // and init the tlab pointers - tlab->fill(tlab_start, tlab_start, new_tlab_size); -} - -static void printTlabInfo (ThreadLocalAllocBuffer* tlab) { - HeapWord *start = tlab->start(); - HeapWord *top = tlab->top(); - HeapWord *end = tlab->end(); - // sizes are in bytes - size_t tlabFree = tlab->free() * HeapWordSize; - size_t tlabUsed = tlab->used() * HeapWordSize; - size_t tlabSize = tlabFree + tlabUsed; - double freePct = 100.0 * (double) tlabFree/(double) tlabSize; - tty->print_cr("(%p, %p, %p), siz=%ld, free=%ld (%f%%)", start, top, end, tlabSize, tlabFree, freePct); -} - -class OopSaver : public StackObj { -private: - objArrayOop _oopsSaveArray; - typeArrayOop _oopMapArray; - jobject _oops_save; - jobject _oop_map_array; - int _last_pcoffset; - int _last_idx; - int _saveAreaCounts; - - enum { - SAVEAREACOUNTS_OFST=0, - SPAN_OFST=1, - HEADERSIZE=2 - }; - int mapPcOffsetToIndex(int pcOffset) { - if (pcOffset == _last_pcoffset) { - return _last_idx; - } - int span = _oopMapArray->int_at(SPAN_OFST); - for (int idx = HEADERSIZE; idx < _oopMapArray->length(); idx += span) { - int ofst = _oopMapArray->int_at(idx); - if (ofst == pcOffset) { - _last_pcoffset = pcOffset; - _last_idx = idx + 1; - return _last_idx; - } - } - ShouldNotReachHere(); - return -1; - } - -public: - OopSaver(jobject oops_save, jobject oop_map_array) { - _oops_save = oops_save; - _oop_map_array = oop_map_array; - _last_pcoffset = -1; - _saveAreaCounts = getSaveAreaCounts(oop_map_array); - resolveArrays(); - } - - void resolveArrays() { - _oopsSaveArray = (objArrayOop) JNIHandles::resolve(_oops_save); - _oopMapArray = (typeArrayOop) JNIHandles::resolve(_oop_map_array); - } - - void * getOopForBit(HSAILFrame * hsailFrame, int bit) { - assert(isOop(hsailFrame, bit), ""); - void *oop; - if (bit < hsailFrame->num_d_regs()) { - // d register - oop = (void*) hsailFrame->get_d_reg(bit); - } else { - // stack slot - int stackOffset = (bit - hsailFrame->num_d_regs()) * 8; // 8 bytes per stack slot - oop = (void *) hsailFrame->get_stackslot64(stackOffset); - } - return oop; - } - - void putOopForBit(HSAILFrame * hsailFrame, int bit, void *oop) { - assert(isOop(hsailFrame, bit), ""); - if (bit < hsailFrame->num_d_regs()) { - // d register - hsailFrame->put_d_reg(bit, (jlong) oop); - } else { - // stack slot - int stackOffset = (bit - hsailFrame->num_d_regs()) * 8; // 8 bytes per stack slot - hsailFrame->put_stackslot64(stackOffset, (jlong) oop); - } - } - - void saveOopsFromFrame(HSAILFrame * hsailFrame, int deoptSlot){ - // as used, no need to resolve arrays on each call - int oopsPerDeopt = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots(); - - // handle the dregister and stackSlot based oops - for (int bit = 0; bit < oopsPerDeopt; bit++) { - if (isOop(hsailFrame, bit)) { - void* saved_oop = getOopForBit(hsailFrame, bit); - int saveArrayIndex = deoptSlot * oopsPerDeopt + bit; - _oopsSaveArray->obj_at_put(saveArrayIndex, (oop) saved_oop); - } - } - } - - void restoreOopsToFrame(HSAILFrame * hsailFrame, int deoptSlot, int workitem){ - // need to re-resolve on each restore - resolveArrays(); - int oopsPerDeopt = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots(); - - // handle the dregister and stackSlot based oops - for (int bit = 0; bit < oopsPerDeopt; bit++) { - if (isOop(hsailFrame, bit)) { - // the dregister or stack slot at this bit is an oop, retrieve it from array and put back in frame - int saveArrayIndex = deoptSlot * oopsPerDeopt + bit; - void * newValue = (void *) _oopsSaveArray->obj_at(saveArrayIndex); - void * oldValue = getOopForBit(hsailFrame, bit); - assert((oldValue != 0 ? newValue != 0 : newValue == 0), "bad dregValue retrieved"); - if (newValue != oldValue) { - if (TraceGPUInteraction) { - int numDRegs = hsailFrame->num_d_regs(); - const char *name = (bit < numDRegs ? "$d" : "stk"); - int num = (bit < numDRegs ? bit : bit - numDRegs); - tty->print_cr("oop moved for %s%d, workitem %d, slot %d, old=%p, new=%p", - name, num, workitem, deoptSlot, oldValue, newValue); - } - putOopForBit(hsailFrame, bit, newValue); - } - } - } - } - - bool isOop(HSAILFrame * hsailFrame, int bit){ - // re-resolve on each access - resolveArrays(); - if (bit > hsailFrame->num_d_regs() + hsailFrame->num_stack_slots()) { - return false; - } - int pcOffset = hsailFrame->pc_offset(); - int bits_int_idx = mapPcOffsetToIndex(pcOffset) + (bit / 32); - int bitpos = bit % 32; - int bits = _oopMapArray->int_at(bits_int_idx); - return ((bits & (1 << bitpos)) != 0); - } - - static int getSaveAreaCounts(jobject oopMapArrayObject) { - typeArrayOop oopMapArray = (typeArrayOop) JNIHandles::resolve(oopMapArrayObject); - return oopMapArray->int_at(SAVEAREACOUNTS_OFST); - } - -}; - -jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oops_save, +jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod* nm, jobject donor_threads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS) { ResourceMark rm(THREAD); objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args); - - // TODO: avoid donor thread logic if kernel does not allocate - objArrayOop donorThreadObjects = (objArrayOop) JNIHandles::resolve(donor_threads); - int numDonorThreads = donorThreadObjects->length(); - guarantee(numDonorThreads > 0, "need at least one donor thread"); - JavaThread** donorThreads = NEW_RESOURCE_ARRAY(JavaThread*, numDonorThreads); - for (int i = 0; i < numDonorThreads; i++) { - donorThreads[i] = java_lang_Thread::thread(donorThreadObjects->obj_at(i)); - } - - - // compute tlabMinHsail based on number of workitems, number of donor - // threads, allocBytesPerWorkitem rounded up - size_t tlabMinHsail = (allocBytesPerWorkitem * dimX + (numDonorThreads - 1)) / numDonorThreads; - if (TraceGPUInteraction) { - tty->print_cr("computed tlabMinHsail = %d", tlabMinHsail); - } + assert(THREAD->is_Java_thread(), "must be a JavaThread"); - for (int i = 0; i < numDonorThreads; i++) { - JavaThread* donorThread = donorThreads[i]; - ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); - if (TraceGPUInteraction) { - tty->print("donorThread %d, is %p, tlab at %p -> ", i, donorThread, tlab); - printTlabInfo(tlab); - } - - // note: this used vs. free limit checking should be based on some - // heuristic where we see how much this kernel tends to allocate - if ((tlab->end() == NULL) || (tlab->free() * HeapWordSize < tlabMinHsail)) { - getNewTlabForDonorThread(tlab, tlabMinHsail); - if (TraceGPUInteraction) { - tty->print("donorThread %d, refilled tlab, -> ", i); - printTlabInfo(tlab); - } - } - } - + // We avoid HSAILAllocationInfo logic if kernel does not allocate + // in which case the donor_thread array passed in will be null + HSAILAllocationInfo* allocInfo = (donor_threads == NULL ? NULL : new HSAILAllocationInfo(donor_threads, dimX, allocBytesPerWorkitem)); + // Reset the kernel arguments _okra_clearargs(kernel); + JavaThread* thread = (JavaThread*)THREAD; HSAILDeoptimizationInfo* e; if (UseHSAILDeoptimization) { // get how many bytes per deopt save area are required - int saveAreaCounts = OopSaver::getSaveAreaCounts(oop_map_array); + int saveAreaCounts = HSAILOopMapHelper::get_save_area_counts(oop_map_array); int numSRegs = saveAreaCounts & 0xff; int numDRegs = (saveAreaCounts >> 8) & 0xff; int numStackSlots = (saveAreaCounts >> 16); int bytesPerSaveArea = numSRegs * 4 + (numDRegs + numStackSlots) * 8; - e = new (MAX_DEOPT_SLOTS, bytesPerSaveArea) HSAILDeoptimizationInfo(MAX_DEOPT_SLOTS, bytesPerSaveArea, dimX, donorThreads); + e = new (MAX_DEOPT_SLOTS, bytesPerSaveArea) HSAILDeoptimizationInfo(MAX_DEOPT_SLOTS, bytesPerSaveArea, dimX, allocInfo, oop_map_array); + // copy cur_tlab_infos + if (allocInfo != NULL) { + e->set_cur_tlabInfos(allocInfo->getCurTlabInfos()); + } + // set deopt info in thread so gc oops_do processing can find it + thread->set_gpu_hsail_deopt_info(e); } // This object sets up the kernel arguments @@ -409,12 +183,11 @@ tty->print_cr("[HSAIL] range=%d", dimX); } - // if any object passed was null, throw an exception here - // doing this means the kernel code can avoid null checks on the object parameters. + // If any object passed was null, throw an exception here. Doing this + // means the kernel code can avoid null checks on the object parameters. if (hka.getFirstNullParameterIndex() >= 0) { char buf[64]; sprintf(buf, "Null Kernel Parameter seen, Parameter Index: %d", hka.getFirstNullParameterIndex()); - JavaThread* thread = (JavaThread*)THREAD; thread->set_gpu_exception_bci(0); thread->set_gpu_exception_method(mh()); THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), buf); @@ -431,23 +204,9 @@ //in_kernel = 0; } - // fix up any tlab tops that overflowed - bool anyOverflows = false; - for (int i = 0; i < numDonorThreads; i++) { - JavaThread * donorThread = donorThreads[i]; - ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); - if (tlab->top() > tlab->end()) { - anyOverflows = true; - long overflowAmount = (long) tlab->top() - (long) tlab->pf_top(); - // tlab->set_top is private this ugly hack gets around that - *(long *)((char *)tlab + in_bytes(tlab->top_offset())) = (long) tlab->pf_top(); - if (TraceGPUInteraction) { - tty->print_cr("donorThread %d at %p overflowed by %ld bytes, setting last good top to %p", i, donorThread, overflowAmount, tlab->top()); - } - } - } - if (anyOverflows) { - kernelStats.incOverflows(); + // avoid HSAILAllocationInfo logic if kernel does not allocate + if (allocInfo != NULL) { + allocInfo->postKernelCleanup(); } if (UseHSAILDeoptimization) { @@ -465,45 +224,23 @@ guarantee(deoptcode == 1, msg); } } else { - kernelStats.incDeopts(); - { TraceTime t3("handle deoptimizing workitems", TraceGPUInteraction); if (TraceGPUInteraction) { tty->print_cr("deopt happened."); - HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(0); + HSAILKernelDeoptimization* pdeopt = e->get_deopt_save_state(0); tty->print_cr("first deopter was workitem %d", pdeopt->workitem()); } - // Before handling any deopting workitems, save the pointers from - // the hsail frames in oops_save so they get adjusted by any - // GC. Need to do this before leaving thread_in_vm mode. - OopSaver oopSaver(oops_save, oop_map_array); - // resolve handle only needed once here (not exiting vm mode) - oopSaver.resolveArrays(); - - // since slots are allocated from the beginning, we know how far to look - assert(e->num_deopts() < e->num_slots(), "deopt save state overflow"); - for (int k = 0; k < e->num_deopts(); k++) { - HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(k); - assert (pdeopt->workitem() >= 0, "bad workitem in deopt"); - // this is a workitem that deopted - oopSaver.saveOopsFromFrame(pdeopt->first_frame(), k); - } - // Handle any deopting workitems. int count_deoptimized = 0; for (int k = 0; k < e->num_deopts(); k++) { - HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(k); + HSAILKernelDeoptimization* pdeopt = e->get_deopt_save_state(k); jint workitem = pdeopt->workitem(); if (workitem != -1) { int deoptId = pdeopt->pc_offset(); - HSAILFrame *hsailFrame = pdeopt->first_frame(); - - // update the hsailFrame from the oopsSaveArray - // will re-resolve the handles each time - oopSaver.restoreOopsToFrame(hsailFrame, k, workitem); + HSAILFrame* hsailFrame = pdeopt->first_frame(); JavaValue result(T_VOID); JavaCallArguments javaArgs; @@ -511,7 +248,7 @@ javaArgs.push_int(deoptId); javaArgs.push_long((jlong) hsailFrame); - // override the deoptimization action with Action_none until we decide + // Override the deoptimization action with Action_none until we decide // how to handle the other actions. int myActionReason = Deoptimization::make_trap_request(Deoptimization::trap_request_reason(pdeopt->reason()), Deoptimization::Action_none); javaArgs.push_int(myActionReason); @@ -520,21 +257,24 @@ tty->print_cr("[HSAIL] Deoptimizing to host for workitem=%d (slot=%d) with deoptId=%d, frame=" INTPTR_FORMAT ", actionAndReason=%d", workitem, k, deoptId, hsailFrame, myActionReason); // show the $d registers or stack slots containing references int maxOopBits = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots(); + HSAILOopMapHelper oopMapHelper(oop_map_array); + int pc_offset = hsailFrame->pc_offset(); for (int bit = 0; bit < maxOopBits; bit++) { - if (oopSaver.isOop(hsailFrame, bit)) { + if (oopMapHelper.is_oop(pc_offset, bit)) { if (bit < hsailFrame->num_d_regs()) { // show $d reg oop - tty->print_cr(" oop $d%d = %p", bit, oopSaver.getOopForBit(hsailFrame, bit)); + tty->print_cr(" oop $d%d = %p", bit, hsailFrame->get_oop_for_bit(bit)); } else { // show stack slot oop int stackOffset = (bit - hsailFrame->num_d_regs()) * 8; // 8 bytes per stack slot - tty->print_cr(" oop stk:%d = %p", stackOffset, oopSaver.getOopForBit(hsailFrame, bit)); + tty->print_cr(" oop stk:%d = %p", stackOffset, hsailFrame->get_oop_for_bit(bit)); } } } } JavaCalls::call(&result, mh, &javaArgs, THREAD); count_deoptimized++; + e->set_deopt_work_index(k + 1); } } if (TraceGPUInteraction) { @@ -542,6 +282,9 @@ } } } + // when we are done with the deopts, we don't need to oops_do anything + // in the saved state anymore + thread->set_gpu_hsail_deopt_info(NULL); // Handle any never_ran workitems if there were any { @@ -551,7 +294,7 @@ // turn off verbose trace stuff for javacall arg setup bool savedTraceGPUInteraction = TraceGPUInteraction; TraceGPUInteraction = false; - jboolean *never_ran_array = e->never_ran_array(); + jboolean* never_ran_array = e->never_ran_array(); if (handleNeverRansHere) { for (int k = 0; k < dimX; k++) { if (never_ran_array[k]) { @@ -562,9 +305,10 @@ JavaCallArguments javaArgs; // re-resolve the args_handle here objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args); - // This object sets up the javaCall arguments - // the way argsArray is set up, this should work for instance methods as well - // (the receiver will be the first oop pushed) + + // This object sets up the javaCall arguments. The way + // argsArray is set up, this should work for instance + // methods as well (the receiver will be the first oop pushed) HSAILJavaCallArguments hjca(&javaArgs, k, mh->signature(), resolvedArgsArray, mh->is_static()); if (mh->is_static()) { JavaCalls::call_static(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD); @@ -583,19 +327,19 @@ } delete e; + delete allocInfo; } - kernelStats.finishDispatch(); return success; } -GPU_ENTRY(jlong, Hsail::generate_kernel, (JNIEnv *env, jclass, jbyteArray code_handle, jstring name_handle)) +GPU_ENTRY(jlong, Hsail::generate_kernel, (JNIEnv* env, jclass, jbyteArray code_handle, jstring name_handle)) guarantee(_okra_create_kernel != NULL, "[HSAIL] Okra not linked"); ResourceMark rm; jsize name_len = env->GetStringLength(name_handle); jsize code_len = env->GetArrayLength(code_handle); char* name = NEW_RESOURCE_ARRAY(char, name_len + 1); - unsigned char *code = NEW_RESOURCE_ARRAY(unsigned char, code_len + 1); + unsigned char* code = NEW_RESOURCE_ARRAY(unsigned char, code_len + 1); code[code_len] = 0; name[name_len] = 0; @@ -631,7 +375,7 @@ return false; \ } \ -GPU_ENTRY(jboolean, Hsail::initialize, (JNIEnv *env, jclass)) +GPU_ENTRY(jboolean, Hsail::initialize, (JNIEnv* env, jclass)) if (okra_library_name == NULL) { if (TraceGPUInteraction) { tty->print_cr("Unsupported HSAIL platform"); @@ -641,14 +385,14 @@ // here we know we have a valid okra_library_name to try to load char ebuf[O_BUFLEN]; - char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_"); + char* okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_"); if (okra_lib_name_from_env_var != NULL) { okra_library_name = okra_lib_name_from_env_var; } if (TraceGPUInteraction) { tty->print_cr("[HSAIL] library is %s", okra_library_name); } - void *okra_lib_handle = NULL; + void* okra_lib_handle = NULL; #if defined(LINUX) // Check first if the Okra library is already loaded. // TODO: Figure out how to do this on other OSes. @@ -668,8 +412,8 @@ guarantee(_okra_create_context == NULL, "cannot repeat GPU initialization"); - // at this point we know okra_lib_handle is valid whether we loaded - // here or earlier. In either case, we can lookup the functions + // At this point we know okra_lib_handle is valid whether we loaded + // here or earlier. In either case, we can lookup the functions. LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context); LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel); LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object); @@ -707,3 +451,27 @@ } return true; } + + +void Hsail::HSAILDeoptimizationInfo::oops_do(OopClosure* f) { + int unprocessed_deopts = num_deopts() - deopt_work_index(); + if (TraceGPUInteraction) { + tty->print_cr("HSAILDeoptimizationInfo::oops_do deopt_occurred=%d, total_deopts=%d, unprocessed_deopts=%d, oop_map_array=%p", _deopt_occurred, num_deopts(), unprocessed_deopts, _oop_map_array); + } + if (num_deopts() == 0 || unprocessed_deopts <= 0) { + return; // nothing to do + } + HSAILOopMapHelper oopMapHelper(_oop_map_array); + oopMapHelper.resolve_arrays(); // resolve once before processing + + // go thru the unprocessed deopt frames, finding each oop and applying the closre + for (int k = deopt_work_index(); k < num_deopts(); k++) { + HSAILKernelDeoptimization* pdeopt = get_deopt_save_state(k); + assert (pdeopt->workitem() >= 0, "bad workitem in deopt"); + if (TraceGPUInteraction) { + tty->print_cr(" deopt %d, workitem %d, pc %d", k, pdeopt->workitem(), pdeopt->pc_offset()); + } + HSAILFrame* hsailFrame = pdeopt->first_frame(); + hsailFrame->oops_do(f, &oopMapHelper); + } +} diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/gpu_hsail.hpp --- a/src/gpu/hsail/vm/gpu_hsail.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -22,12 +22,49 @@ * */ -#ifndef GPU_HSAIL_HPP -#define GPU_HSAIL_HPP +#ifndef GPU_HSAIL_VM_GPU_HSAIL_HPP +#define GPU_HSAIL_VM_GPU_HSAIL_HPP +#include "runtime/gpu.hpp" #include "utilities/exceptions.hpp" #include "graal/graalEnv.hpp" +#include "gpu_hsail_OopMapHelper.hpp" #include "gpu_hsail_Frame.hpp" +#include "gpu_hsail_Tlab.hpp" + +struct HSAILKernelStats { + int _dispatches; + int _deopts; + int _overflows; + bool _changeSeen; + +public: + HSAILKernelStats() { + _dispatches = _deopts = _overflows = 0; + _changeSeen = false; + } + + void incDeopts() { + _deopts++; + _changeSeen = true; + } + void incOverflows() { + _overflows++; + _changeSeen = true; + } + + void finishDispatch() { + _dispatches++; + if (_changeSeen) { + // print(); + _changeSeen = false; + } + } + + void print() { + tty->print_cr("Disp=%d, Deopts=%d, Ovflows=%d", _dispatches, _deopts, _overflows); + } +}; class Hsail : public Gpu { @@ -46,9 +83,9 @@ inline jint workitem() { return _workitemid; } inline jint reason() { return _actionAndReason; } inline jint pc_offset() { return first_frame()->pc_offset(); } - inline HSAILFrame *first_frame() { + inline HSAILFrame* first_frame() { // starts after the "header" fields - return (HSAILFrame *) (((jbyte *) this) + sizeof(*this)); + return (HSAILFrame*) (((jbyte*) this) + sizeof(*this)); } }; @@ -56,38 +93,45 @@ // TODO: query the device to get this number #define MAX_DEOPT_SLOTS (8 * 40 * 64) + class HSAILDeoptimizationInfo : public CHeapObj { friend class VMStructs; private: jint* _notice_safepoints; jint _deopt_occurred; jint _deopt_next_index; - JavaThread** _donor_threads; jint _num_slots; jint _deopt_span; + jint _deopt_work_index; // how far we are in processing the deopts + HSAILTlabInfo** _cur_tlab_info; // copy of what was in the HSAILAllocationInfo, to avoid an extra indirection + HSAILAllocationInfo* _alloc_info; char _ignore; + jobject _oop_map_array; // keep a pointer last so save area following it is word aligned - jboolean * _never_ran_array; + jboolean* _never_ran_array; public: + // static HSAILKernelStats kernelStats; HSAILKernelDeoptimization _deopt_save_states[1]; // number and size of these can vary per kernel static inline size_t hdr_size() { return sizeof(HSAILDeoptimizationInfo); } - inline jbyte * save_area_start() { + inline jbyte* save_area_start() { return (jbyte*) (this) + hdr_size(); } - inline HSAILDeoptimizationInfo(int numSlots, int bytesPerSaveArea, int dimX, JavaThread** donorThreads) { + inline HSAILDeoptimizationInfo(int numSlots, int bytesPerSaveArea, int dimX, HSAILAllocationInfo* allocInfo, jobject oop_map_array) { _notice_safepoints = &Hsail::_notice_safepoints; _deopt_occurred = 0; _deopt_next_index = 0; + _deopt_work_index = 0; _num_slots = numSlots; _never_ran_array = NEW_C_HEAP_ARRAY(jboolean, dimX, mtInternal); memset(_never_ran_array, 0, dimX * sizeof(jboolean)); - _donor_threads = donorThreads; + _alloc_info = allocInfo; + _oop_map_array = oop_map_array; _deopt_span = sizeof(HSAILKernelDeoptimization) + sizeof(HSAILFrame) + bytesPerSaveArea; if (TraceGPUInteraction) { tty->print_cr("HSAILDeoptimizationInfo allocated, %d slots of size %d, total size = 0x%lx bytes", _num_slots, _deopt_span, (_num_slots * _deopt_span + sizeof(HSAILDeoptimizationInfo))); @@ -102,21 +146,29 @@ return _deopt_occurred; } inline jint num_deopts() { return _deopt_next_index; } - inline jboolean *never_ran_array() { return _never_ran_array; } + inline jboolean* never_ran_array() { return _never_ran_array; } inline jint num_slots() {return _num_slots;} + inline void set_deopt_work_index(int val) { _deopt_work_index = val; } + inline jint deopt_work_index() { return _deopt_work_index; } - inline HSAILKernelDeoptimization * get_deopt_save_state(int slot) { + inline HSAILKernelDeoptimization* get_deopt_save_state(int slot) { // use _deopt_span to index into _deopt_states - return (HSAILKernelDeoptimization *) (save_area_start() + _deopt_span * slot); + return (HSAILKernelDeoptimization*) (save_area_start() + _deopt_span * slot); } - void * operator new (size_t hdrSize, int numSlots, int bytesPerSaveArea) { + void set_cur_tlabInfos(HSAILTlabInfo** ptlabInfos) { + _cur_tlab_info = ptlabInfos; + } + + void oops_do(OopClosure* f); + + void* operator new (size_t hdrSize, int numSlots, int bytesPerSaveArea) { assert(hdrSize <= hdr_size(), ""); size_t totalSizeBytes = hdr_size() + numSlots * (sizeof(HSAILKernelDeoptimization) + sizeof(HSAILFrame) + bytesPerSaveArea); return NEW_C_HEAP_ARRAY(char, totalSizeBytes, mtInternal); } - void operator delete (void *ptr) { + void operator delete (void* ptr) { FREE_C_HEAP_ARRAY(char, ptr, mtInternal); } }; @@ -126,21 +178,16 @@ static JNINativeMethod HSAIL_methods[]; // static native boolean initialize(); - JNIEXPORT static jboolean initialize(JNIEnv *env, jclass); + JNIEXPORT static jboolean initialize(JNIEnv* env, jclass); // static native long generateKernel(byte[] targetCode, String name); - JNIEXPORT static jlong generate_kernel(JNIEnv *env, jclass, jbyteArray code_handle, jstring name_handle); + JNIEXPORT static jlong generate_kernel(JNIEnv* env, jclass, jbyteArray code_handle, jstring name_handle); // static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args); - JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv *env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject oopsSave, + JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv* env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array); - // static native void getThreadPointers(Object[] donorThreads, long[] threadPointersOut); - JNIEXPORT static void get_thread_pointers(JNIEnv *env, jclass, jobject donor_threads_handle, jobject thread_ptrs_handle); - - static void getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail); - - static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oopsSave, + static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod* nm, jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS); static void register_heap(); @@ -165,7 +212,7 @@ private: typedef void* (*okra_create_context_func_t)(); - typedef void* (*okra_create_kernel_func_t)(void*, unsigned char *, const char *); + typedef void* (*okra_create_kernel_func_t)(void*, unsigned char*, const char*); typedef bool (*okra_push_object_func_t)(void*, void*); typedef bool (*okra_push_boolean_func_t)(void*, jboolean); typedef bool (*okra_push_byte_func_t)(void*, jbyte); @@ -197,4 +244,4 @@ // true if safepoints are activated static jint _notice_safepoints; }; -#endif // GPU_HSAIL_HPP +#endif // GPU_HSAIL_VM_GPU_HSAIL_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/gpu_hsail_Frame.hpp --- a/src/gpu/hsail/vm/gpu_hsail_Frame.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail_Frame.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -22,8 +22,8 @@ * */ -#ifndef GPU_HSAIL_FRAME_HPP -#define GPU_HSAIL_FRAME_HPP +#ifndef GPU_HSAIL_VM_GPU_HSAIL_FRAME_HPP +#define GPU_HSAIL_VM_GPU_HSAIL_FRAME_HPP #include "graal/graalEnv.hpp" #include "code/debugInfo.hpp" @@ -37,37 +37,86 @@ jbyte _num_d_regs; jshort _num_stack_slots; + jbyte* data_start() {return (jbyte*) this + sizeof(*this); } + int sreg_ofst_start() { return 0; } + int dreg_ofst_start() { return sreg_ofst_start() + num_s_regs() * sizeof(jint); } + int stackslot_ofst_start() { return dreg_ofst_start() + num_d_regs() * sizeof(jlong); } + + int sreg_ofst(int idx) { + assert(idx >= 0 && idx < num_s_regs(), "bad sreg index"); + return sreg_ofst_start() + idx * sizeof(jint); + } + + int dreg_ofst(int idx) { + assert(idx >= 0 && idx < num_d_regs(), "bad dreg index"); + return dreg_ofst_start() + idx * sizeof(jlong); + } + + int stackslot_ofst(int stackOffset) { + assert(stackOffset >= 0 && (unsigned int) stackOffset < num_stack_slots() * sizeof(jlong), "bad stackoffset"); + return stackslot_ofst_start() + stackOffset; + } + + // the _ptr versions just return a pointer to the indicated d reg or stackslot64 + // some of these are used for oops_do processing + jint* get_s_reg_ptr(int idx) { + return((jint*) (data_start() + sreg_ofst(idx))); + } + + jlong* get_d_reg_ptr(int idx) { + return((jlong*) (data_start() + dreg_ofst(idx))); + } + + jlong* get_stackslot64_ptr(int stackOffset) { + return((jlong*) (data_start() + stackslot_ofst(stackOffset))); + } + + jint* get_stackslot32_ptr(int stackOffset) { + return((jint*) (data_start() + stackslot_ofst(stackOffset))); + } + + void* get_oop_ptr_for_bit(int bit) { + void* oop_ptr; + if (bit < num_d_regs()) { + // d register + oop_ptr = (void*) get_d_reg_ptr(bit); + } else { + // stack slot + int stackOffset = (bit - num_d_regs()) * 8; // 8 bytes per stack slot + oop_ptr = (void*) get_stackslot64_ptr(stackOffset); + } + return oop_ptr; + } + public: // Accessors jint pc_offset() { return _pc_offset; } jint num_s_regs() {return _num_s_regs; } jint num_d_regs() {return _num_d_regs; } jint num_stack_slots() {return _num_stack_slots; } - jbyte * data_start() {return (jbyte *) this + sizeof(*this); } - jlong get_d_reg(int idx) { - int ofst = num_s_regs() * 4 + idx * 8; - return(*(jlong *) (data_start() + ofst)); - } - jint get_s_reg(int idx) { - int ofst = idx * 4; - return(*(jint *) (data_start() + ofst)); + + jlong get_oop_for_bit(int bit) { + return * (jlong *) get_oop_ptr_for_bit(bit); } - void put_d_reg(int idx, jlong val) { - int ofst = num_s_regs() * 4 + idx * 8; - (*(jlong *) (data_start() + ofst)) = val; - } - jint get_stackslot32(int stackOffset) { - int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset; - return(*(jint *) (data_start() + ofst)); - } - jlong get_stackslot64(int stackOffset) { - int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset; - return(*(jlong *) (data_start() + ofst)); - } - void put_stackslot64(int stackOffset, jlong val) { - int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset; - (*(jlong *) (data_start() + ofst)) = val; + + // do the oops from this frame + void oops_do(OopClosure* f, HSAILOopMapHelper* oopMapHelper) { + int oops_per_deopt = num_d_regs() + num_stack_slots(); + + // handle the dregister and stackSlot based oops + for (int bit = 0; bit < oops_per_deopt; bit++) { + if (oopMapHelper->is_oop(pc_offset(), bit)) { + void* oop_ptr = get_oop_ptr_for_bit(bit); + // the oops we are dealing with here in the hsailFrame are always uncompressed + oop old_oop = oopDesc::load_heap_oop((oop *)oop_ptr); + f->do_oop((oop*) oop_ptr); + if (TraceGPUInteraction) { + oop new_oop = oopDesc::load_heap_oop((oop *)oop_ptr); + tty->print_cr("bit=%d, oop_ptr=%p, old=%p, new=%p", bit, oop_ptr, (void *)old_oop, (void *)new_oop); + } + } + } } }; -#endif // GPU_HSAIL_FRAME_HPP +#endif // GPU_HSAIL_VM_GPU_HSAIL_FRAME_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/gpu_hsail_OopMapHelper.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gpu/hsail/vm/gpu_hsail_OopMapHelper.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef GPU_HSAIL_VM_GPU_HSAIL_OOPMAPHELPER_HPP +#define GPU_HSAIL_VM_GPU_HSAIL_OOPMAPHELPER_HPP + +#include "graal/graalEnv.hpp" +#include "code/debugInfo.hpp" +#include "code/location.hpp" + +// Takes the jobject for the array of ints created by the java side +// and decodes the information based on pc_offset to find oops +class HSAILOopMapHelper : public StackObj { +private: + jobject _oop_map_array_jobject; + typeArrayOop _oop_map_array; + int _last_pcoffset; + int _last_idx; + + enum { + SAVEAREACOUNTS_OFST=0, + SPAN_OFST=1, + HEADERSIZE=2 + }; + int mapPcOffsetToIndex(int pcOffset) { + if (pcOffset == _last_pcoffset) { + return _last_idx; + } + int span = _oop_map_array->int_at(SPAN_OFST); + for (int idx = HEADERSIZE; idx < _oop_map_array->length(); idx += span) { + int ofst = _oop_map_array->int_at(idx); + if (ofst == pcOffset) { + _last_pcoffset = pcOffset; + _last_idx = idx + 1; + return _last_idx; + } + } + ShouldNotReachHere(); + return -1; + } + +public: + HSAILOopMapHelper(jobject oop_map_array_jobject) { + _oop_map_array_jobject = oop_map_array_jobject; + _last_pcoffset = -1; + resolve_arrays(); + } + + void resolve_arrays() { + _oop_map_array = (typeArrayOop) JNIHandles::resolve(_oop_map_array_jobject); + } + + static int get_save_area_counts(jobject oop_map_array_jobject) { + typeArrayOop oop_map_array_resolved = (typeArrayOop) JNIHandles::resolve(oop_map_array_jobject); + return oop_map_array_resolved->int_at(SAVEAREACOUNTS_OFST); + } + + bool is_oop(int pcOffset, int bit){ + int bits_int_idx = mapPcOffsetToIndex(pcOffset) + (bit / 32); + int bitpos = bit % 32; + int bits = _oop_map_array->int_at(bits_int_idx); + return ((bits & (1 << bitpos)) != 0); + } + +}; + +#endif // GPU_HSAIL_VM_GPU_HSAIL_OOPMAPHELPER_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/gpu_hsail_Tlab.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gpu/hsail/vm/gpu_hsail_Tlab.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef GPU_HSAIL_VM_GPU_HSAIL_TLAB_HPP +#define GPU_HSAIL_VM_GPU_HSAIL_TLAB_HPP + +#include "graal/graalEnv.hpp" +#include "code/debugInfo.hpp" +#include "code/location.hpp" +#include "gpu_hsail.hpp" + +class HSAILAllocationInfo; + +class HSAILTlabInfo VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; +public: + // uses only the necessary fields from a full TLAB + HeapWord* _start; + HeapWord* _top; + HeapWord* _end; + HeapWord* _last_good_top; + HeapWord* _original_top; + JavaThread* _donor_thread; // donor thread associated with this tlabInfo + HSAILAllocationInfo* _alloc_info; // same as what is in HSAILDeoptimizationInfo + + // Accessors + HeapWord* start() { return _start; } + HeapWord* top() { return _top; } + HeapWord* end() { return _end; } + HeapWord* last_good_top() { return _last_good_top; } + HeapWord* original_top() { return _original_top; } + void initialize(HeapWord* start, HeapWord* top, HeapWord* end, JavaThread* donorThread, HSAILAllocationInfo* allocInfo) { + _start = start; + _top = _original_top = top; + _end = end; + _donor_thread = donorThread; + _alloc_info = allocInfo; + } +}; + + +class HSAILAllocationInfo : public CHeapObj { + friend class VMStructs; +private: + JavaThread** donorThreads; + jint _num_donor_threads; + size_t _tlab_align_reserve_bytes; // filled in from ThreadLocalAllocBuffer::alignment_reserve_in_bytes() + HSAILTlabInfo** _cur_tlab_infos; // array of current tlab info pointers, one per donor_thread + HSAILTlabInfo* _tlab_infos_pool_start; // pool for new tlab_infos + HSAILTlabInfo* _tlab_infos_pool_next; // where next will be allocated from + HSAILTlabInfo* _tlab_infos_pool_end; // where next will be allocated from + +public: + HSAILAllocationInfo(jobject donor_threads_jobj, int dimX, int allocBytesPerWorkitem) { + // fill in the donorThreads array + objArrayOop donorThreadObjects = (objArrayOop) JNIHandles::resolve(donor_threads_jobj); + _num_donor_threads = donorThreadObjects->length(); + guarantee(_num_donor_threads > 0, "need at least one donor thread"); + donorThreads = NEW_C_HEAP_ARRAY(JavaThread*, _num_donor_threads, mtInternal); + for (int i = 0; i < _num_donor_threads; i++) { + donorThreads[i] = java_lang_Thread::thread(donorThreadObjects->obj_at(i)); + } + + // Compute max_tlab_infos based on amount of free heap space + size_t max_tlab_infos; + { + JavaThread* donorThread = donorThreads[0]; + ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + size_t new_tlab_size = tlab->compute_size(0); + size_t heap_bytes_free = Universe::heap()->unsafe_max_tlab_alloc(donorThread); + if (new_tlab_size != 0) { + max_tlab_infos = MIN2(heap_bytes_free / new_tlab_size, (size_t)(64 * _num_donor_threads)); + } else { + max_tlab_infos = 8 * _num_donor_threads; // an arbitrary multiple + } + if (TraceGPUInteraction) { + tty->print_cr("heapFree = %ld, newTlabSize=%ld, tlabInfos allocated = %ld", heap_bytes_free, new_tlab_size, max_tlab_infos); + } + } + + _cur_tlab_infos = NEW_C_HEAP_ARRAY(HSAILTlabInfo*, _num_donor_threads, mtInternal); + _tlab_infos_pool_start = NEW_C_HEAP_ARRAY(HSAILTlabInfo, max_tlab_infos, mtInternal); + _tlab_infos_pool_next = &_tlab_infos_pool_start[_num_donor_threads]; + _tlab_infos_pool_end = &_tlab_infos_pool_start[max_tlab_infos]; + _tlab_align_reserve_bytes = ThreadLocalAllocBuffer::alignment_reserve_in_bytes(); + + // we will fill the first N tlabInfos from the donor threads + for (int i = 0; i < _num_donor_threads; i++) { + JavaThread* donorThread = donorThreads[i]; + ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + if (TraceGPUInteraction) { + tty->print("donorThread %d, is %p, tlab at %p -> ", i, donorThread, tlab); + printTlabInfoFromThread(tlab); + } + + // Here we try to get a new tlab if current one is null. Note: + // eventually we may want to test if the size is too small based + // on some heuristic where we see how much this kernel tends to + // allocate, but for now we can just let it overflow and let the + // GPU allocate new tlabs. Actually, if we can't prime a tlab + // here, it might make sense to do a gc now rather than to start + // the kernel and have it deoptimize. How to do that? + if (tlab->end() == NULL) { + bool success = getNewTlabForDonorThread(tlab, i); + if (TraceGPUInteraction) { + if (success) { + tty->print("donorThread %d, refilled tlab, -> ", i); + printTlabInfoFromThread(tlab); + } else { + tty->print("donorThread %d, could not refill tlab, left as ", i); + printTlabInfoFromThread(tlab); + } + } + } + + // extract the necessary tlab fields into a TlabInfo record + HSAILTlabInfo* pTlabInfo = &_tlab_infos_pool_start[i]; + _cur_tlab_infos[i] = pTlabInfo; + pTlabInfo->initialize(tlab->start(), tlab->top(), tlab->end(), donorThread, this); + } + } + + ~HSAILAllocationInfo() { + FREE_C_HEAP_ARRAY(HSAILTlabInfo*, _cur_tlab_infos, mtInternal); + FREE_C_HEAP_ARRAY(HSAILTlabInfo, _tlab_infos_pool_start, mtInternal); + FREE_C_HEAP_ARRAY(JavaThread*, donorThreads, mtInternal); + } + + void postKernelCleanup() { + // go thru all the tlabInfos, fix up any tlab tops that overflowed + // complete the tlabs if they overflowed + // update the donor threads tlabs when appropriate + bool anyOverflows = false; + size_t bytesAllocated = 0; + // if there was an overflow in allocating tlabInfos, correct it here + if (_tlab_infos_pool_next > _tlab_infos_pool_end) { + if (TraceGPUInteraction) { + int overflowAmount = _tlab_infos_pool_next - _tlab_infos_pool_end; + tty->print_cr("tlabInfo allocation overflowed by %d units", overflowAmount); + } + _tlab_infos_pool_next = _tlab_infos_pool_end; + } + for (HSAILTlabInfo* tlabInfo = _tlab_infos_pool_start; tlabInfo < _tlab_infos_pool_next; tlabInfo++) { + if (TraceGPUInteraction) { + tty->print_cr("postprocess tlabInfo %p, start=%p, top=%p, end=%p, last_good_top=%p", tlabInfo, + tlabInfo->start(), tlabInfo->top(), tlabInfo->end(), tlabInfo->last_good_top()); + } + JavaThread* donorThread = tlabInfo->_donor_thread; + ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + bool overflowed = false; + // if a tlabInfo has NULL fields, i.e. we could not prime it on entry, + // or we could not get a tlab from the gpu, so ignore tlabInfo here + if (tlabInfo->start() != NULL) { + if (tlabInfo->top() > tlabInfo->end()) { + anyOverflows = true; + overflowed = true; + if (TraceGPUInteraction) { + long overflowAmount = (long) tlabInfo->top() - (long) tlabInfo->last_good_top(); + tty->print_cr("tlabInfo %p (donorThread = %p) overflowed by %ld bytes, setting last good top to %p", tlabInfo, donorThread, overflowAmount, tlabInfo->last_good_top()); + } + tlabInfo->_top = tlabInfo->last_good_top(); + } + + // fill the donor thread tlab with the tlabInfo information + // we do this even if it will get overwritten by a later tlabinfo + // because it helps with tlab statistics for that donor thread + tlab->fill(tlabInfo->start(), tlabInfo->top(), (tlabInfo->end() - tlabInfo->start()) + tlab->alignment_reserve()); + + // if there was an overflow, make it parsable with retire = true + if (overflowed) { + tlab->make_parsable(true); + } + + size_t delta = (long)(tlabInfo->top()) - (long)(tlabInfo->original_top()); + if (TraceGPUInteraction) { + tty->print_cr("%ld bytes were allocated by tlabInfo %p (start %p, top %p, end %p", delta, tlabInfo, + tlabInfo->start(), tlabInfo->top(), tlabInfo->end()); + } + bytesAllocated += delta; + } + } + if (TraceGPUInteraction) { + tty->print_cr("%ld total bytes were allocated in this kernel", bytesAllocated); + } + if (anyOverflows) { + // Hsail::kernelStats.incOverflows(); + } + } + + HSAILTlabInfo** getCurTlabInfos() { + return _cur_tlab_infos; + } + +private: + // fill and retire old tlab and get a new one + // if we can't get one, no problem someone will eventually do a gc + bool getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, int idx) { + + tlab->clear_before_allocation(); // fill and retire old tlab (will also check for null) + + // get a size for a new tlab that is based on the desired_size + size_t new_tlab_size = tlab->compute_size(0); + if (new_tlab_size == 0) return false; + + HeapWord* tlab_start = Universe::heap()->allocate_new_tlab(new_tlab_size); + if (tlab_start == NULL) return false; + + // ..and clear it if required + if (ZeroTLAB) { + Copy::zero_to_words(tlab_start, new_tlab_size); + } + // and init the tlab pointers + tlab->fill(tlab_start, tlab_start, new_tlab_size); + return true; + } + + void printTlabInfoFromThread (ThreadLocalAllocBuffer* tlab) { + HeapWord* start = tlab->start(); + HeapWord* top = tlab->top(); + HeapWord* end = tlab->end(); + // sizes are in bytes + size_t tlabFree = tlab->free() * HeapWordSize; + size_t tlabUsed = tlab->used() * HeapWordSize; + size_t tlabSize = tlabFree + tlabUsed; + double freePct = 100.0 * (double) tlabFree/(double) tlabSize; + tty->print_cr("(%p, %p, %p), siz=%ld, free=%ld (%f%%)", start, top, end, tlabSize, tlabFree, freePct); + } + +}; + +#endif // GPU_HSAIL_VM_GPU_HSAIL_TLAB_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/hsailArgumentsBase.cpp --- a/src/gpu/hsail/vm/hsailArgumentsBase.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/hsailArgumentsBase.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -38,6 +38,29 @@ return arg; } +void HSAILArgumentsBase::collectArgs() { + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, sig:%s args length=%d", argsBuilderName(), _signature->as_C_string(), _length); + } + if (!_is_static) { + // First object in args should be 'this' + oop arg = _args->obj_at(_index++); + assert(arg->is_instance() && (!arg->is_array()), "First arg should be 'this'"); + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s, instance method, this " PTR_FORMAT ", is a %s", argsBuilderName(), (address) arg, arg->klass()->external_name()); + } + pushObject(arg); + } else { + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s, static method", argsBuilderName()); + } + } + // Iterate over the entire signature + iterate(); + + pushTrailingArgs(); +} + void HSAILArgumentsBase::do_bool() { // Get the boxed value oop arg = _args->obj_at(_index++); diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/hsailArgumentsBase.hpp --- a/src/gpu/hsail/vm/hsailArgumentsBase.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/hsailArgumentsBase.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -22,19 +22,16 @@ * */ -#ifndef BASE_ARGUMENTS_HSAIL_HPP -#define BASE_ARGUMENTS_HSAIL_HPP +#ifndef GPU_HSAIL_VM_HSAIL_ARGUMENTS_BASE_HPP +#define GPU_HSAIL_VM_HSAIL_ARGUMENTS_BASE_HPP #include "runtime/signature.hpp" -/*** - * Base class which iterates thru a signature and pulls from a - * objArrayOop of boxed values. Used as base for HSAILKernelArguments - * and HSAILJavaCallArguments The derived classes specify how to push - * args onto their data structure - ***/ - +// Base class which iterates thru a signature and pulls from a +// objArrayOop of boxed values. Used as base for HSAILKernelArguments +// and HSAILJavaCallArguments The derived classes specify how to push +// args onto their data structure class HSAILArgumentsBase : public SignatureIterator { public: @@ -49,7 +46,7 @@ // number of parameters in the signature int _parameter_count; - Symbol * _signature; + Symbol* _signature; bool _is_static; // records first null parameter seen @@ -58,8 +55,8 @@ // Get next java argument oop next_arg(BasicType expectedType); - virtual char *argsBuilderName() = 0; - virtual void pushObject(void * obj) = 0; + virtual char* argsBuilderName() = 0; + virtual void pushObject(void* obj) = 0; virtual void pushBool(jboolean z) = 0; virtual void pushByte(jbyte b) = 0; virtual void pushDouble(jdouble d) = 0; @@ -67,13 +64,9 @@ virtual void pushInt(jint i) = 0; virtual void pushLong(jlong j) = 0; virtual void handleFinalIntParameter() = 0; - virtual void handleFinalObjParameter(void *obj) = 0; + virtual void handleFinalObjParameter(void* obj) = 0; virtual void pushTrailingArgs() = 0; - void recordNullObjectParameter() { - if (_first_null_parameter_index == -1) _first_null_parameter_index = _parameter_index; - } - public: HSAILArgumentsBase(Symbol* signature, objArrayOop args, bool is_static) : SignatureIterator(signature) { this->_return_type = T_ILLEGAL; @@ -89,32 +82,29 @@ } + void recordNullObjectParameter() { + if (_first_null_parameter_index == -1) { + _first_null_parameter_index = _parameter_index; + } + } + + bool is_static() { + return _is_static; + } + + int length() { + return _length; + } + + objArrayOop args() { + return _args; + } + int getFirstNullParameterIndex() { return _first_null_parameter_index; } - void collectArgs() { - if (TraceGPUInteraction) { - tty->print_cr("[HSAIL] %s::collectArgs, sig:%s args length=%d", argsBuilderName(), _signature->as_C_string(), _length); - } - if (!_is_static) { - // First object in args should be 'this' - oop arg = _args->obj_at(_index++); - assert(arg->is_instance() && (! arg->is_array()), "First arg should be 'this'"); - if (TraceGPUInteraction) { - tty->print_cr("[HSAIL] %s, instance method, this " PTR_FORMAT ", is a %s", argsBuilderName(), (address) arg, arg->klass()->external_name()); - } - pushObject(arg); - } else { - if (TraceGPUInteraction) { - tty->print_cr("[HSAIL] %s, static method", argsBuilderName()); - } - } - // Iterate over the entire signature - iterate(); - - pushTrailingArgs(); - } + virtual void collectArgs(); void do_bool(); void do_byte(); @@ -143,4 +133,4 @@ }; -#endif // BASE_ARGUMENTS_HSAIL_HPP +#endif // GPU_HSAIL_VM_HSAIL_ARGUMENTS_BASE_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/hsailJavaCallArguments.hpp --- a/src/gpu/hsail/vm/hsailJavaCallArguments.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/hsailJavaCallArguments.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -22,8 +22,8 @@ * */ -#ifndef JAVACALL_ARGUMENTS_HSAIL_HPP -#define JAVACALL_ARGUMENTS_HSAIL_HPP +#ifndef GPU_HSAIL_VM_HSAIL_JAVACALL_ARGUMENTS_HPP +#define GPU_HSAIL_VM_HSAIL_JAVACALL_ARGUMENTS_HPP #include "hsailArgumentsBase.hpp" #include "runtime/javaCalls.hpp" @@ -33,17 +33,17 @@ public: private: - // JavaCall Args to push into - JavaCallArguments *_javaArgs; + // JavaCall args to push into + JavaCallArguments* _javaArgs; int _workitemid; public: - HSAILJavaCallArguments(JavaCallArguments *javaArgs, int workitemid, Symbol* signature, objArrayOop args, bool is_static) : HSAILArgumentsBase(signature, args, is_static) { + HSAILJavaCallArguments(JavaCallArguments* javaArgs, int workitemid, Symbol* signature, objArrayOop args, bool is_static) : HSAILArgumentsBase(signature, args, is_static) { _javaArgs = javaArgs; _workitemid = workitemid; collectArgs(); } - virtual char *argsBuilderName() {return (char *)"HSAILJavaCallArguments";} - virtual void pushObject(void *obj) { _javaArgs->push_oop((oop) obj); } + virtual char* argsBuilderName() {return (char*)"HSAILJavaCallArguments";} + virtual void pushObject(void* obj) { _javaArgs->push_oop((oop) obj); } virtual void pushBool(jboolean z) { pushInt(z); } virtual void pushByte(jbyte b) { pushInt(b); } virtual void pushDouble(jdouble d) { _javaArgs->push_double(d); } @@ -64,7 +64,7 @@ // stream source array (already checked in the base class) so for // a javacall we need to extract the correct obj from it based on // the workitemid - virtual void handleFinalObjParameter(void *arg) { + virtual void handleFinalObjParameter(void* arg) { objArrayOop objArrayArg = (objArrayOop) arg; oop extractedObj = objArrayArg->obj_at(_workitemid); if (TraceGPUInteraction) { @@ -77,5 +77,5 @@ }; -#endif // JAVACALL_ARGUMENTS_HSAIL_HPP +#endif // GPU_HSAIL_VM_HSAIL_JAVACALL_ARGUMENTS_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/hsailKernelArguments.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gpu/hsail/vm/hsailKernelArguments.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, 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. + * + */ +#include "precompiled.hpp" +#include "hsailKernelArguments.hpp" + +void HSAILKernelArguments::collectArgs() { + int index = 0; + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, args length=%d", argsBuilderName(), length()); + } + + // Manually iterate over the actual args array without looking at method signature + while (index < length()) { + oop arg = args()->obj_at(index++); + jvalue jValue; + if (arg == NULL) { + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs object, _index=%d, value = " PTR_FORMAT " is a %s", argsBuilderName(), index, (void*) arg, "null"); + } + recordNullObjectParameter(); + pushObject(arg); + } else { + java_lang_boxing_object::get_value(arg, &jValue); + BasicType basic_type = java_lang_boxing_object::basic_type(arg); + if (basic_type == T_ILLEGAL && (!(arg->is_array()))) { + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs object, _index=%d, value = " PTR_FORMAT " is a %s", argsBuilderName(), index, (void*) arg, arg == NULL ? "null" : arg->klass()->external_name()); + } + pushObject(arg); + } else if (arg->is_array()) { + if (TraceGPUInteraction) { + int array_length = ((objArrayOop) arg)->length(); + tty->print_cr("[HSAIL] %s::collectArgs array, length=%d, _index=%d, value = " PTR_FORMAT, argsBuilderName(), array_length, index, (void*) arg); + } + pushObject(arg); + } else { + switch (basic_type) { + case T_INT: + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, T_INT _index=%d, value = %d", argsBuilderName(), index, jValue.i); + } + pushInt(jValue.i); + break; + case T_LONG: + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, T_LONG _index=%d, value = %d", argsBuilderName(), index, jValue.j); + } + pushLong(jValue.j); + break; + case T_FLOAT: + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, T_FLOAT _index=%d, value = %d", argsBuilderName(), index, jValue.f); + } + pushFloat(jValue.f); + break; + case T_DOUBLE: + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, T_DOUBLE _index=%d, value = %d", argsBuilderName(), index, jValue.d); + } + pushDouble(jValue.d); + break; + case T_BYTE: + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, T_BYTE _index=%d, value = %d", argsBuilderName(), index, jValue.b); + } + pushByte(jValue.b); + break; + case T_BOOLEAN: + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] %s::collectArgs, T_BOOLEAN _index=%d, value = %d", argsBuilderName(), index, jValue.z); + } + pushBool(jValue.z); + break; + } + } + } + } + + pushTrailingArgs(); +} + diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/hsailKernelArguments.hpp --- a/src/gpu/hsail/vm/hsailKernelArguments.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/hsailKernelArguments.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -22,8 +22,8 @@ * */ -#ifndef KERNEL_ARGUMENTS_HSAIL_HPP -#define KERNEL_ARGUMENTS_HSAIL_HPP +#ifndef GPU_HSAIL_VM_HSAIL_KERNEL_ARGUMENTS_HPP +#define GPU_HSAIL_VM_HSAIL_KERNEL_ARGUMENTS_HPP #include "gpu_hsail.hpp" #include "runtime/signature.hpp" @@ -37,7 +37,7 @@ private: // Kernel to push into address _kernel; - void * _exceptionHolder; + void* _exceptionHolder; public: HSAILKernelArguments(address kernel, Symbol* signature, objArrayOop args, bool is_static, void* exceptionHolder) : HSAILArgumentsBase(signature, args, is_static) { @@ -45,8 +45,8 @@ _exceptionHolder = exceptionHolder; collectArgs(); } - virtual char *argsBuilderName() {return (char *)"HSAILKernelArguments";} - virtual void pushObject(void *obj) { + virtual char* argsBuilderName() {return (char*)"HSAILKernelArguments";} + virtual void pushObject(void* obj) { bool pushed = Hsail::_okra_push_object(_kernel, obj); assert(pushed == true, "arg push failed"); } @@ -91,16 +91,17 @@ // For kernel arguments we don't pass the final int parameter // since we use the HSAIL workitemid instruction in place of that int value virtual void handleFinalIntParameter() { - if (TraceGPUInteraction) { - tty->print_cr("[HSAIL] HSAILKernelArguments, not pushing trailing int"); - } + ShouldNotReachHere(); } - // for kernel arguments, final obj parameter should be an object + // For kernel arguments, final obj parameter should be an object // stream source array (already checked in the base class) so here we just pass it - virtual void handleFinalObjParameter(void *arg) { - pushObject(arg); + virtual void handleFinalObjParameter(void* arg) { + ShouldNotReachHere(); } + + virtual void collectArgs(); + }; -#endif // KERNEL_ARGUMENTS_HSAIL_HPP +#endif // GPU_HSAIL_VM_HSAIL_KERNEL_ARGUMENTS_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/gpu/hsail/vm/vmStructs_hsail.hpp --- a/src/gpu/hsail/vm/vmStructs_hsail.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -41,16 +41,32 @@ nonstatic_field(Hsail::HSAILKernelDeoptimization, _workitemid, jint) \ nonstatic_field(Hsail::HSAILKernelDeoptimization, _actionAndReason, jint) \ \ - nonstatic_field(Hsail::HSAILDeoptimizationInfo, _notice_safepoints, jint*) \ + nonstatic_field(Hsail::HSAILDeoptimizationInfo, _notice_safepoints, jint*) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_occurred, jint) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_next_index, jint) \ - nonstatic_field(Hsail::HSAILDeoptimizationInfo, _donor_threads, JavaThread**) \ - nonstatic_field(Hsail::HSAILDeoptimizationInfo, _never_ran_array, jboolean *) \ + nonstatic_field(Hsail::HSAILDeoptimizationInfo, _cur_tlab_info, HSAILTlabInfo**) \ + nonstatic_field(Hsail::HSAILDeoptimizationInfo, _alloc_info, HSAILAllocationInfo*) \ + nonstatic_field(Hsail::HSAILDeoptimizationInfo, _never_ran_array, jboolean*) \ + \ + nonstatic_field(HSAILAllocationInfo, _tlab_infos_pool_start, HSAILTlabInfo*) \ + nonstatic_field(HSAILAllocationInfo, _tlab_infos_pool_next, HSAILTlabInfo*) \ + nonstatic_field(HSAILAllocationInfo, _tlab_infos_pool_end, HSAILTlabInfo*) \ + nonstatic_field(HSAILAllocationInfo, _tlab_align_reserve_bytes, size_t) \ + \ + nonstatic_field(HSAILTlabInfo, _start, HeapWord*) \ + nonstatic_field(HSAILTlabInfo, _top, HeapWord*) \ + nonstatic_field(HSAILTlabInfo, _end, HeapWord*) \ + nonstatic_field(HSAILTlabInfo, _last_good_top, HeapWord*) \ + nonstatic_field(HSAILTlabInfo, _original_top, HeapWord*) \ + nonstatic_field(HSAILTlabInfo, _donor_thread, JavaThread*) \ + nonstatic_field(HSAILTlabInfo, _alloc_info, HSAILAllocationInfo*) \ -#define VM_TYPES_GPU_HSAIL(declare_type, declare_toplevel_type) \ +#define VM_TYPES_GPU_HSAIL(declare_type, declare_toplevel_type) \ declare_toplevel_type(HSAILFrame) \ declare_toplevel_type(HSAILFrame*) \ declare_toplevel_type(Hsail::HSAILKernelDeoptimization) \ + declare_toplevel_type(HSAILAllocationInfo) \ + declare_toplevel_type(HSAILTlabInfo) \ declare_toplevel_type(Hsail::HSAILDeoptimizationInfo) #endif // GPU_HSAIL_VM_VMSTRUCTS_HSAIL_HPP diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java Mon Jun 30 12:02:19 2014 +0200 @@ -68,29 +68,31 @@ private final int from; private final int to; private final String label; + private final String type; private State state; public InputEdge(char toIndex, int from, int to) { - this((char) 0, toIndex, from, to, null); + this((char) 0, toIndex, from, to, null, null); } public InputEdge(char fromIndex, char toIndex, int from, int to) { - this(fromIndex, toIndex, from, to, null); + this(fromIndex, toIndex, from, to, null, null); } - public InputEdge(char fromIndex, char toIndex, int from, int to, String label) { + public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type) { this.toIndex = toIndex; this.fromIndex = fromIndex; this.from = from; this.to = to; this.state = State.SAME; this.label = label; + this.type = type; } static WeakHashMap> immutableCache = new WeakHashMap<>(); - public static synchronized InputEdge createImmutable(char fromIndex, char toIndex, int from, int to, String label) { - InputEdge edge = new InputEdge(fromIndex, toIndex, from, to, label, State.IMMUTABLE); + public static synchronized InputEdge createImmutable(char fromIndex, char toIndex, int from, int to, String label, String type) { + InputEdge edge = new InputEdge(fromIndex, toIndex, from, to, label, type, State.IMMUTABLE); WeakReference result = immutableCache.get(edge); if (result != null) { InputEdge edge2 = result.get(); @@ -102,13 +104,14 @@ return edge; } - public InputEdge(char fromIndex, char toIndex, int from, int to, String label, State state) { + public InputEdge(char fromIndex, char toIndex, int from, int to, String label, String type, State state) { this.toIndex = toIndex; this.fromIndex = fromIndex; this.from = from; this.to = to; this.state = state; this.label = label; + this.type = type; } public State getState() { @@ -145,6 +148,10 @@ public String getLabel() { return label; } + + public String getType() { + return type; + } @Override public boolean equals(Object o) { diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -215,12 +215,20 @@ } } + private static class TypedPort extends Port { + public final EnumValue type; + private TypedPort(boolean isList, String name, EnumValue type) { + super(isList, name); + this.type = type; + } + } + private static class NodeClass { public final String className; public final String nameTemplate; - public final List inputs; + public final List inputs; public final List sux; - private NodeClass(String className, String nameTemplate, List inputs, List sux) { + private NodeClass(String className, String nameTemplate, List inputs, List sux) { this.className = className; this.nameTemplate = nameTemplate; this.inputs = inputs; @@ -464,11 +472,12 @@ String className = readString(); String nameTemplate = readString(); int inputCount = readShort(); - List inputs = new ArrayList<>(inputCount); + List inputs = new ArrayList<>(inputCount); for (int i = 0; i < inputCount; i++) { boolean isList = readByte() != 0; String name = readPoolObject(String.class); - inputs.add(new Port(isList, name)); + EnumValue inputType = readPoolObject(EnumValue.class); + inputs.add(new TypedPort(isList, name, inputType)); } int suxCount = readShort(); List sux = new ArrayList<>(suxCount); @@ -726,20 +735,20 @@ } int edgesStart = edges.size(); int portNum = 0; - for (Port p : nodeClass.inputs) { + for (TypedPort p : nodeClass.inputs) { if (p.isList) { int size = readShort(); for (int j = 0; j < size; j++) { int in = readInt(); if (in >= 0) { - edges.add(new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", true)); + edges.add(new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", p.type.toString(Length.S), true)); portNum++; } } } else { int in = readInt(); if (in >= 0) { - edges.add(new Edge(in, id, (char) (preds + portNum), p.name, true)); + edges.add(new Edge(in, id, (char) (preds + portNum), p.name, p.type.toString(Length.S), true)); portNum++; } } @@ -752,14 +761,14 @@ for (int j = 0; j < size; j++) { int sux = readInt(); if (sux >= 0) { - edges.add(new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", false)); + edges.add(new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", "Successor", false)); portNum++; } } } else { int sux = readInt(); if (sux >= 0) { - edges.add(new Edge(id, sux, (char) portNum, p.name, false)); + edges.add(new Edge(id, sux, (char) portNum, p.name, "Successor", false)); portNum++; } } @@ -780,7 +789,7 @@ for (Edge e : edges) { char fromIndex = e.input ? 1 : e.num; char toIndex = e.input ? e.num : 0; - graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label)); + graph.addEdge(InputEdge.createImmutable(fromIndex, toIndex, e.from, e.to, e.label, e.type)); } } @@ -845,14 +854,16 @@ final int to; final char num; final String label; + final String type; final boolean input; public Edge(int from, int to) { - this(from, to, (char) 0, null, false); + this(from, to, (char) 0, null, null, false); } - public Edge(int from, int to, char num, String label, boolean input) { + public Edge(int from, int to, char num, String label, String type, boolean input) { this.from = from; this.to = to; this.label = label != null ? label.intern() : label; + this.type = type != null ? type.intern() : type; this.num = num; this.input = input; } diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Mon Jun 30 12:02:19 2014 +0200 @@ -410,7 +410,7 @@ throw new SAXException(e); } - InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label); + InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label, ""); return start(conn); } diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java --- a/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Mon Jun 30 12:02:19 2014 +0200 @@ -211,7 +211,7 @@ if (nodeFrom == null || nodeTo == null) { System.out.println("Unexpected edge : " + from + " -> " + to); } else { - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType()); if (!newEdges.contains(newEdge)) { markAsDeleted(newEdge); newEdges.add(newEdge); @@ -231,7 +231,7 @@ if (nodeFrom == null || nodeTo == null) { System.out.println("Unexpected edge : " + from + " -> " + to); } else { - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId(), e.getLabel(), e.getType()); if (!newEdges.contains(newEdge)) { markAsNew(newEdge); newEdges.add(newEdge); diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java --- a/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java Mon Jun 30 12:02:19 2014 +0200 @@ -97,7 +97,7 @@ for (InputSlot s : f.getInputSlots()) { for (Connection c : s.getConnections()) { - Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel()); + Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel(), c.getType()); newConn.setColor(c.getColor()); newConn.setStyle(c.getStyle()); } @@ -154,7 +154,7 @@ } } for (Connection c : nextSlot.getConnections()) { - Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel()); + Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel(), c.getType()); newConn.setColor(c.getColor()); newConn.setStyle(c.getStyle()); } diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Mon Jun 30 12:02:19 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, 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 @@ -31,6 +31,7 @@ import com.sun.hotspot.igv.graph.Figure; import com.sun.hotspot.igv.graph.InputSlot; import java.awt.Color; +import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; @@ -41,9 +42,8 @@ */ public class GraalEdgeColorFilter extends AbstractFilter { - private Color successorColor = Color.BLUE; - private Color usageColor = Color.RED; - private Color memoryColor = Color.GREEN; + private HashMap usageColor = new HashMap<>(); + private Color otherUsageColor = Color.BLACK; public GraalEdgeColorFilter() { } @@ -56,66 +56,43 @@ @Override public void apply(Diagram d) { List
figures = d.getFigures(); - Pattern ndf = Pattern.compile(".*#NDF(\\[[0-9]*\\])?"); for (Figure f : figures) { - Properties p = f.getProperties(); - int predCount; - String predCountString = p.get("predecessorCount"); - if (predCountString != null) { - predCount = Integer.parseInt(predCountString); - } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) { - predCount = 1; - } else { - predCount = 0; - } for (InputSlot is : f.getInputSlots()) { - Color color; - ConnectionStyle style = ConnectionStyle.NORMAL; - if (is.getPosition() < predCount) { - color = successorColor; - style = ConnectionStyle.BOLD; - } else { - color = usageColor; - } - - is.setColor(color); for (Connection c : is.getConnections()) { - if (c.getLabel() == null || !ndf.matcher(c.getLabel()).matches()) { - c.setColor(color); - if (c.getStyle() != ConnectionStyle.DASHED) { - c.setStyle(style); + String type = c.getType(); + if (type == "Association" && "EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) { + type = "Successor"; + } + + if (type != null) { + Color typeColor = usageColor.get(type); + if (typeColor == null) { + c.setColor(otherUsageColor); + } else { + c.setColor(typeColor); } - } else if ("EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class")) - || "EndNode".equals(c.getOutputSlot().getProperties().get("class"))) { - c.setColor(successorColor); - c.setStyle(ConnectionStyle.BOLD); + if (c.getStyle() != ConnectionStyle.DASHED && type == "Successor") { + c.setStyle(ConnectionStyle.BOLD); + } } } } } } - public Color getUsageColor() { - return usageColor; - } - - public void setUsageColor(Color usageColor) { - this.usageColor = usageColor; - } - - public void setMemoryColor(Color memoryColor) { - this.memoryColor = memoryColor; + public Color getUsageColor(String type) { + return usageColor.get(type); } - public Color getMemoryColor() { - return memoryColor; + public void setUsageColor(String type, Color usageColor) { + this.usageColor.put(type, usageColor); } - - public Color getSuccessorColor() { - return successorColor; + + public Color getOtherUsageColor() { + return otherUsageColor; } - - public void setSuccessorColor(Color successorColor) { - this.successorColor = successorColor; + + public void setOtherUsageColor(Color otherUsageColor) { + this.otherUsageColor = otherUsageColor; } } diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter Mon Jun 30 12:02:19 2014 +0200 @@ -1,4 +1,5 @@ var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter(); -f.setUsageColor(blue); -f.setSuccessorColor(red); +f.setUsageColor("Successor", red); +f.setUsageColor("Value", blue); +f.setUsageColor("Memory", new Color(0.0, 0.5, 0.0)); f.apply(graph); diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java --- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java Mon Jun 30 12:02:19 2014 +0200 @@ -55,11 +55,13 @@ private ConnectionStyle style; private List controlPoints; private String label; + private String type; - protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label) { + protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) { this.inputSlot = inputSlot; this.outputSlot = outputSlot; this.label = label; + this.type = type; this.inputSlot.connections.add(this); this.outputSlot.connections.add(this); controlPoints = new ArrayList<>(); @@ -105,6 +107,10 @@ public String getLabel() { return label; } + + public String getType() { + return type; + } public void remove() { inputSlot.getFigure().removePredecessor(outputSlot.getFigure()); @@ -116,10 +122,12 @@ public String getToolTipText() { StringBuilder builder = new StringBuilder(); if (label != null) { - builder.append(label).append(": from "); - } else { - builder.append("From "); + builder.append(label).append(": "); } + if (type != null) { + builder.append(type).append(" "); + } + builder.append("from "); builder.append(getOutputSlot().getFigure().getSource().getSourceNodes().get(0).getId()); builder.append(" to "); builder.append(getInputSlot().getFigure().getSource().getSourceNodes().get(0).getId()); diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java --- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Mon Jun 30 12:02:19 2014 +0200 @@ -82,10 +82,10 @@ return f; } - public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label) { + public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label, String type) { assert inputSlot.getFigure().getDiagram() == this; assert outputSlot.getFigure().getDiagram() == this; - return new Connection(inputSlot, outputSlot, label); + return new Connection(inputSlot, outputSlot, label, type); } public Map> calcSourceToFigureRelation() { @@ -145,7 +145,7 @@ } InputSlot inputSlot = toFigure.getInputSlots().get(toIndex); - Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel()); + Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel(), e.getType()); if (e.getState() == InputEdge.State.NEW) { c.setStyle(Connection.ConnectionStyle.BOLD); diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java Mon Jun 30 12:02:19 2014 +0200 @@ -26,6 +26,7 @@ import java.io.PrintStream; import java.util.ArrayList; +import java.util.List; public class Compilation implements LogEvent { @@ -44,6 +45,7 @@ private NMethod nmethod; private ArrayList phases = new ArrayList(4); private String failureReason; + private List eliminatedLocks = new ArrayList(); Compilation(int id) { this.id = id; @@ -77,9 +79,11 @@ sb.append("+"); sb.append(getBcount()); sb.append("\n"); - for (CallSite site : getCall().getCalls()) { - sb.append(site); - sb.append("\n"); + if (getCall().getCalls() != null) { + for (CallSite site : getCall().getCalls()) { + sb.append(site); + sb.append("\n"); + } } if (getLateInlineCall().getCalls() != null) { sb.append("late inline:\n"); @@ -91,15 +95,19 @@ return sb.toString(); } - public void printShort(PrintStream stream) { + public String shortName() { if (getMethod() == null) { - stream.println(getSpecial()); + return getSpecial(); } else { int bc = isOsr() ? getOsr_bci() : -1; - stream.print(getId() + getMethod().decodeFlags(bc) + getMethod().format(bc)); + return getId() + getMethod().decodeFlags(bc) + getMethod().format(bc); } } + public void printShort(PrintStream stream) { + stream.println(shortName()); + } + public void print(PrintStream stream) { print(stream, 0, false); } @@ -255,4 +263,12 @@ public Compilation getCompilation() { return this; } + + public void addEliminatedLock(JVMState jvms) { + eliminatedLocks.add(jvms); + } + + public List getEliminatedLocks() { + return eliminatedLocks; + } } diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/JVMState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/JVMState.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, 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.sun.hotspot.tools.compiler; + +public class JVMState { + final Method method; + final int bci; + JVMState outer; + + JVMState(Method method, int bci) { + this.method = method; + this.bci = bci; + } + + void push(JVMState jvms) { + if (outer == null) { + outer = jvms; + } else { + outer.push(jvms); + } + } +} diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java Mon Jun 30 12:02:19 2014 +0200 @@ -44,6 +44,7 @@ System.out.println(" -s: sort events by start time"); System.out.println(" -e: sort events by elapsed time"); System.out.println(" -n: sort events by name and start"); + System.out.println(" -L: print eliminated locks"); System.exit(exitcode); } @@ -52,6 +53,7 @@ boolean statistics = false; boolean printInlining = false; boolean cleanup = false; + boolean printEliminatedLocks = false; int index = 0; while (args.length > index) { @@ -75,6 +77,9 @@ } else if (args[index].equals("-i")) { printInlining = true; index++; + } else if (args[index].equals("-L")) { + printEliminatedLocks = true; + index++; } else { break; } @@ -87,11 +92,34 @@ while (index < args.length) { ArrayList events = LogParser.parse(args[index], cleanup); - if (statistics) { + if (printEliminatedLocks) { + Collections.sort(events, defaultSort); + for (LogEvent e : events) { + if (e instanceof Compilation) { + Compilation c = (Compilation) e; + List eliminated = c.getEliminatedLocks(); + if (!eliminated.isEmpty()) { + c.print(System.out); + System.out.println(" Eliminated locks"); + for (JVMState jvms : eliminated) { + System.err.print(" "); + while (jvms != null) { + System.out.printf(" %s.%s@%d", jvms.method.getHolder().replace('/', '.'), jvms.method.getName(), jvms.bci); + jvms = jvms.outer; + } + System.out.println(); + } + } + } + } + } else if (statistics) { printStatistics(events, System.out); } else { Collections.sort(events, defaultSort); for (LogEvent c : events) { + if (c instanceof NMethod) continue; + + System.out.printf("%f ", c.getStart()); if (printInlining && c instanceof Compilation) { Compilation comp = (Compilation)c; comp.print(System.out, true); @@ -141,7 +169,7 @@ nodes created in the phase, live nodes at the start of the phase, live nodes added in the phase. */ - out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getLiveNodes()); + // out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getLiveNodes()); } } else if (e instanceof MakeNotEntrantEvent) { MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e; diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Mon Jun 30 12:02:19 2014 +0200 @@ -89,15 +89,12 @@ if (result != 0) { return result; } - } - double difference = (a.getStart() - b.getStart()); - if (difference < 0) { + } else if (c1 == null && c2 != null) { return -1; - } - if (difference > 0) { + } else if (c2 == null && c1 != null) { return 1; } - return 0; + return Double.compare(a.getStart(), b.getStart()); } public boolean equals(Object other) { @@ -138,6 +135,7 @@ private HashMap types = new HashMap(); private HashMap methods = new HashMap(); private LinkedHashMap nmethods = new LinkedHashMap(); + private ArrayList notEntrantEvents = new ArrayList(); private HashMap compiles = new HashMap(); private String failureReason; private int bci; @@ -147,6 +145,8 @@ private Stack phaseStack = new Stack(); private UncommonTrapEvent currentTrap; private Stack late_inline_scope; + private JVMState eliminated_lock; + private boolean in_eliminate_lock; long parseLong(String l) { try { @@ -191,15 +191,34 @@ p.parse(new InputSource(reader), log); // Associate compilations with their NMethods - for (NMethod nm : log.nmethods.values()) { - Compilation c = log.compiles.get(nm.getId()); - nm.setCompilation(c); - // Native wrappers for methods don't have a compilation - if (c != null) { - c.setNMethod(nm); + for (LogEvent le : log.events) { + if (le instanceof BasicLogEvent) { + BasicLogEvent ble = (BasicLogEvent) le; + Compilation c = log.compiles.get(ble.getId()); + ble.setCompilation(c); + if (ble instanceof NMethod) { + NMethod nm = (NMethod) ble; + // Native wrappers for methods don't have a compilation and Graal methods don't either. + if (c != null) { + c.setNMethod(nm); + } + } else { + if (c == null) { + throw new InternalError("can't find compilation " + ble.getId() + " for " + ble); + } + } } } + + for (MakeNotEntrantEvent ne : log.notEntrantEvents) { + Compilation c = log.compiles.get(ne.getId()); + if (c == null) { + throw new InternalError("can't find compilation " + ne.getId()); + } + ne.setCompilation(c); + } + // Initially we want the LogEvent log sorted by timestamp Collections.sort(log.events, sortByStart); @@ -353,8 +372,9 @@ String id = makeId(atts); NMethod nm = nmethods.get(id); if (nm == null) throw new InternalError(); - LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id, - atts.getValue("zombie") != null, nm); + MakeNotEntrantEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id, + atts.getValue("zombie") != null, nm); + notEntrantEvents.add(e); events.add(e); } else if (qname.equals("uncommon_trap")) { String id = atts.getValue("compile_id"); @@ -374,6 +394,8 @@ late_inline_scope = new Stack(); site = new CallSite(-999, method(search(atts, "method"))); late_inline_scope.push(site); + } else if (qname.equals("eliminate_lock")) { + in_eliminate_lock = true; } else if (qname.equals("jvms")) { // if (currentTrap != null) { @@ -382,6 +404,13 @@ bci = Integer.parseInt(search(atts, "bci")); site = new CallSite(bci, method(search(atts, "method"))); late_inline_scope.push(site); + } else if (in_eliminate_lock) { + JVMState jvms = new JVMState(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci"))); + if (eliminated_lock == null) { + eliminated_lock = jvms; + } else { + eliminated_lock.push(jvms); + } } else { // Ignore , // , @@ -390,9 +419,10 @@ } else if (qname.equals("nmethod")) { String id = makeId(atts); NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")), - id, - parseLong(atts.getValue("address")), - parseLong(atts.getValue("size"))); + id, + atts.getValue("compile_kind"), + parseLong(atts.getValue("address")), + parseLong(atts.getValue("size"))); nmethods.put(id, nm); events.add(nm); } else if (qname.equals("parse")) { @@ -429,6 +459,13 @@ scopes.pop(); } else if (qname.equals("uncommon_trap")) { currentTrap = null; + } else if (qname.equals("eliminate_lock")) { + if (eliminated_lock != null) { + // There's no JVM state on the unlock, so ignore it + compile.addEliminatedLock(eliminated_lock); + } + eliminated_lock = null; + in_eliminate_lock = false; } else if (qname.equals("late_inline")) { // Populate late inlining info. diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/MakeNotEntrantEvent.java Mon Jun 30 12:02:19 2014 +0200 @@ -43,9 +43,9 @@ public void print(PrintStream stream) { if (isZombie()) { - stream.printf("%s make_zombie\n", getId()); + stream.printf("%s make_zombie\n", compilation.shortName()); } else { - stream.printf("%s make_not_entrant\n", getId()); + stream.printf("%s make_not_entrant\n", compilation.shortName()); } } diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/NMethod.java Mon Jun 30 12:02:19 2014 +0200 @@ -30,11 +30,17 @@ private long address; private long size; + private String compileKind; - NMethod(double s, String i, long a, long sz) { + NMethod(double s, String i, String k, long a, long sz) { super(s, i); address = a; size = sz; + if (k == null) { + compileKind = "normal"; + } else { + compileKind = k; + } } public void print(PrintStream out) { @@ -50,6 +56,10 @@ this.address = address; } + public String getKind() { + return compileKind; + } + public long getSize() { return size; } diff -r 51f392557124 -r 5f01f7c48d40 src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Mon Jun 30 12:02:19 2014 +0200 @@ -40,7 +40,6 @@ count = c; } - public void addJVMS(String method, int bci) { setJvms(getJvms() + " @" + bci + " " + method + "\n"); } @@ -50,7 +49,7 @@ } public void print(PrintStream stream) { - stream.printf("%s uncommon trap %s %s\n", getId(), getReason(), getAction()); + stream.printf("%s uncommon trap %s %s\n", compilation.shortName(), getReason(), getAction()); stream.print(getJvms()); } @@ -77,8 +76,4 @@ public void setJvms(String jvms) { this.jvms = jvms; } - - public void setCompilation(Compilation compilation) { - this.compilation = compilation; - } } diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/classfile/javaClasses.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -1532,6 +1532,7 @@ return; } +#ifdef GRAAL // Check for gpu exception to add as top frame Method* gpu_method = thread->get_gpu_exception_method(); if (gpu_method != NULL) { @@ -1541,6 +1542,7 @@ thread->set_gpu_exception_bci(0); thread->set_gpu_exception_method(NULL); } +#endif // Instead of using vframe directly, this version of fill_in_stack_trace // basically handles everything by hand. This significantly improved the diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/classfile/systemDictionary.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -2286,7 +2286,7 @@ spe = NULL; // Must create lots of stuff here, but outside of the SystemDictionary lock. m = Method::make_method_handle_intrinsic(iid, signature, CHECK_(empty)); - CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier, + nmethod* nm = CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier, methodHandle(), CompileThreshold, "MH", CHECK_(empty)); // Now grab the lock. We might have to throw away the new method, @@ -2299,9 +2299,12 @@ if (spe->method() == NULL) spe->set_method(m()); } + } else if (spe->method()->code() == NULL) { + nmethod* nm = CompileBroker::compile_method(spe->method(), InvocationEntryBci, CompLevel_highest_tier, + methodHandle(), CompileThreshold, "MH", CHECK_(empty)); } - assert(spe != NULL && spe->method() != NULL, ""); + guarantee(spe != NULL && spe->method() != NULL && spe->method()->code() != NULL, "Could not compile a method handle intrinsic"); return spe->method(); } diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/compiler/compileBroker.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -383,7 +383,7 @@ st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp } // print compiler name if requested - if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level)); + if (CIPrintCompilerName) st->print("%s:", CompileBroker::compiler_name(comp_level)); st->print("%4d ", compile_id); // print compilation number // For unloaded methods the transition to zombie occurs after the @@ -805,7 +805,19 @@ #if defined(COMPILERGRAAL) _compilers[1] = graal; - c2_count = UseGraalCompilationQueue ? 0 : c2_count; + if (UseGraalCompilationQueue) { + c2_count = 0; + } else { + if (FLAG_IS_DEFAULT(GraalThreads)) { + if (!TieredCompilation && FLAG_IS_DEFAULT(BootstrapGraal) || BootstrapGraal) { + // Graal will bootstrap so give it the same number of threads + // as we would give the Java based compilation queue. + c2_count = os::active_processor_count(); + } + } else { + c2_count = GraalThreads; + } + } #endif // COMPILERGRAAL #ifdef COMPILER2 @@ -1031,7 +1043,7 @@ char name_buffer[256]; for (int i = 0; i < c2_compiler_count; i++) { // Create a name for our thread. - sprintf(name_buffer, "C2 CompilerThread%d", i); + sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i); CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); // Shark and C2 CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_method_queue, counters, _compilers[1], CHECK); @@ -1199,6 +1211,13 @@ // Should this thread wait for completion of the compile? blocking = is_compile_blocking(method, osr_bci); +#ifdef COMPILERGRAAL + // Don't allow blocking compiles for requests triggered by Graal. + if (blocking && thread->is_Compiler_thread()) { + blocking = false; + } +#endif + // We will enter the compilation in the queue. // 14012000: Note that this sets the queued_for_compile bits in // the target method. We can now reason that a method cannot be diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -84,7 +84,7 @@ class CollectedHeap : public CHeapObj { friend class VMStructs; friend class IsGCActiveMark; // Block structured external access to _is_gc_active - friend class Hsail; // access to allocate_new_tlab + friend class HSAILAllocationInfo; // access to allocate_new_tlab #ifdef ASSERT static int _fire_out_of_memory_count; diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -88,6 +88,26 @@ return arr->length() * MapWordBits; } +static void set_vmreg_oops(OopMap* map, VMReg reg, oop bitset, int idx) { + bool is_oop = is_bit_set(bitset, 3 * idx); + if (is_oop) { + bool narrow1 = is_bit_set(bitset, 3 * idx + 1); + bool narrow2 = is_bit_set(bitset, 3 * idx + 2); + if (narrow1 || narrow2) { + if (narrow1) { + map->set_narrowoop(reg); + } + if (narrow2) { + map->set_narrowoop(reg->next()); + } + } else { + map->set_oop(reg); + } + } else { + map->set_value(reg); + } +} + // creates a HotSpot oop map out of the byte arrays provided by DebugInfo static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) { OopMap* map = new OopMap(total_frame_size, parameter_count); @@ -98,41 +118,23 @@ if (register_map != NULL) { for (jint i = 0; i < RegisterImpl::number_of_registers; i++) { - bool is_oop = is_bit_set(register_map, 2 * i); - VMReg hotspot_reg = get_hotspot_reg(i); - if (is_oop) { - if (is_bit_set(register_map, 2 * i + 1)) { - map->set_narrowoop(hotspot_reg); - } else { - map->set_oop(hotspot_reg); - } - } else { - map->set_value(hotspot_reg); + set_vmreg_oops(map, as_Register(i)->as_VMReg(), register_map, i); + } +#ifdef TARGET_ARCH_x86 + for (jint i = 0; i < XMMRegisterImpl::number_of_registers; i++) { + VMReg reg = as_XMMRegister(i)->as_VMReg(); + int idx = RegisterImpl::number_of_registers + 4 * i; + for (jint j = 0; j < 4; j++) { + set_vmreg_oops(map, reg->next(2 * j), register_map, idx + j); } } +#endif } for (jint i = 0; i < bitset_size(frame_map) / 3; i++) { - bool is_oop = is_bit_set(frame_map, i * 3); // HotSpot stack slots are 4 bytes VMReg reg = VMRegImpl::stack2reg(i * VMRegImpl::slots_per_word); - if (is_oop) { - bool narrow1 = is_bit_set(frame_map, i * 3 + 1); - bool narrow2 = is_bit_set(frame_map, i * 3 + 2); - if(narrow1 || narrow2) { - if(narrow1) { - map->set_narrowoop(reg); - } - if(narrow2) { - VMReg reg2 = VMRegImpl::stack2reg(i * VMRegImpl::slots_per_word + 1); - map->set_narrowoop(reg2); - } - } else { - map->set_oop(reg); - } - } else { - map->set_value(reg); - } + set_vmreg_oops(map, reg, frame_map, i); } if (callee_save_info != NULL) { diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -35,6 +35,7 @@ GraalCompiler::GraalCompiler() : AbstractCompiler(graal) { #ifdef COMPILERGRAAL _bootstrapping = false; + _compiled = 0; #endif assert(_instance == NULL, "only one instance allowed"); _instance = this; @@ -62,9 +63,10 @@ { HandleMark hm; - _bootstrapping = UseGraalCompilationQueue && (FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal); + bool bootstrap_now = UseGraalCompilationQueue && (FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal); if (UseGraalCompilationQueue) { + _bootstrapping = bootstrap_now; start_compilation_queue(); } @@ -72,7 +74,7 @@ // stop the VM deferring compilation now. CompilationPolicy::completed_vm_startup(); - if (_bootstrapping) { + if (bootstrap_now) { // Avoid -Xcomp and -Xbatch problems by turning on interpreter and background compilation for bootstrapping. FlagSetting a(UseInterpreter, true); FlagSetting b(BackgroundCompilation, true); @@ -119,13 +121,56 @@ void GraalCompiler::bootstrap() { JavaThread* THREAD = JavaThread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/CompilationQueue", THREAD); - KlassHandle klass = GraalRuntime::load_required_class(name); - JavaValue result(T_VOID); - TempNewSymbol bootstrap = SymbolTable::new_symbol("bootstrap", THREAD); - NoGraalCompilationScheduling ngcs(THREAD); - JavaCalls::call_static(&result, klass, bootstrap, vmSymbols::void_method_signature(), THREAD); - GUARANTEE_NO_PENDING_EXCEPTION("Error while calling bootstrap"); + _bootstrapping = true; + if (!UseGraalCompilationQueue) { + ResourceMark rm; + HandleMark hm; + if (PrintBootstrap) { + tty->print("Bootstrapping Graal"); + } + jlong start = os::javaTimeMillis(); + + Array* objectMethods = InstanceKlass::cast(SystemDictionary::Object_klass())->methods(); + // Initialize compile queue with a selected set of methods. + int len = objectMethods->length(); + for (int i = 0; i < len; i++) { + methodHandle mh = objectMethods->at(i); + if (!mh->is_native() && !mh->is_static() && !mh->is_initializer()) { + ResourceMark rm; + int hot_count = 10; // TODO: what's the appropriate value? + CompileBroker::compile_method(mh, InvocationEntryBci, CompLevel_full_optimization, mh, hot_count, "bootstrap", THREAD); + } + } + + int qsize; + jlong sleep_time = 1000; + int z = 0; + do { + os::sleep(THREAD, sleep_time, true); + sleep_time = 100; + qsize = CompileBroker::queue_size(CompLevel_full_optimization); + if (PrintBootstrap) { + while (z < (_compiled / 100)) { + ++z; + tty->print_raw("."); + } + } + } while (qsize != 0); + + if (PrintBootstrap) { + tty->print_cr(" in %d ms (compiled %d methods)", os::javaTimeMillis() - start, _compiled); + } + } else { + + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/CompilationQueue", THREAD); + KlassHandle klass = GraalRuntime::load_required_class(name); + JavaValue result(T_VOID); + TempNewSymbol bootstrap = SymbolTable::new_symbol("bootstrap", THREAD); + NoGraalCompilationScheduling ngcs(THREAD); + JavaCalls::call_static(&result, klass, bootstrap, vmSymbols::void_method_signature(), THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling bootstrap"); + } + _bootstrapping = false; } void GraalCompiler::compile_method(methodHandle method, int entry_bci, CompileTask* task, jboolean blocking) { @@ -138,6 +183,7 @@ return; } + HandleMark hm; ResourceMark rm; JavaValue result(T_VOID); JavaCallArguments args; @@ -147,6 +193,8 @@ args.push_int(blocking); JavaCalls::call_static(&result, SystemDictionary::CompilationTask_klass(), vmSymbols::compileMetaspaceMethod_name(), vmSymbols::compileMetaspaceMethod_signature(), &args, THREAD); GUARANTEE_NO_PENDING_EXCEPTION("Error while calling compile_method"); + + _compiled++; } diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/graal/graalCompiler.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -32,10 +32,10 @@ #ifdef COMPILERGRAAL bool _bootstrapping; + volatile int _compiled; // no synchronization so may not be 100% accurate void start_compilation_queue(); void shutdown_compilation_queue(); - void bootstrap(); #endif static GraalCompiler* _instance; @@ -61,6 +61,9 @@ virtual void initialize(); #ifdef COMPILERGRAAL + + void bootstrap(); + // Compilation entry point for methods virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -194,9 +194,9 @@ return (jlong) (address) method(); } -C2V_VMENTRY(jlong, findUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_method)) +C2V_VMENTRY(jlong, findUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_klass, jlong metaspace_method)) methodHandle method = asMethod(metaspace_method); - KlassHandle holder = method->method_holder(); + KlassHandle holder = asKlass(metaspace_klass); assert(!holder->is_interface(), "should be handled in Java code"); ResourceMark rm; MutexLocker locker(Compile_lock); @@ -367,7 +367,7 @@ methodHandle resolved_method; LinkResolver::linktime_resolve_interface_method(resolved_method, holder_klass, method_name, method_signature, caller_klass, true, CHECK_AND_CLEAR_0); if (resolved_method->is_private()) { - return (jlong) NULL; + return (jlong) (address) NULL; } assert(recv_klass->is_subtype_of(holder_klass), ""); // do actual lookup @@ -413,7 +413,7 @@ return (jlong) (address) selected_method; } } - return (jlong) NULL; + return (jlong) (address) NULL; C2V_END C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jlong metaspace_klass)) @@ -897,6 +897,14 @@ cp_cache_entry->set_dynamic_call(cp, callInfo); C2V_END +C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject)) + //see compute_recording_non_safepoints in debugInfroRec.cpp + if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) { + return true; + } + return DebugNonSafepoints; +C2V_END + // public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate); C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame, bool invalidate)) ResourceMark rm; @@ -1019,7 +1027,7 @@ {CC"exceptionTableStart", CC"("METASPACE_METHOD")J", FN_PTR(exceptionTableStart)}, {CC"exceptionTableLength", CC"("METASPACE_METHOD")I", FN_PTR(exceptionTableLength)}, {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, - {CC"findUniqueConcreteMethod", CC"("METASPACE_METHOD")"METASPACE_METHOD, FN_PTR(findUniqueConcreteMethod)}, + {CC"findUniqueConcreteMethod", CC"("METASPACE_KLASS METASPACE_METHOD")"METASPACE_METHOD, FN_PTR(findUniqueConcreteMethod)}, {CC"getKlassImplementor", CC"("METASPACE_KLASS")"METASPACE_KLASS, FN_PTR(getKlassImplementor)}, {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, {CC"methodIsIgnoredBySecurityStackWalk", CC"("METASPACE_METHOD")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)}, @@ -1068,6 +1076,7 @@ {CC"getTimeStamp", CC"()J", FN_PTR(getTimeStamp)}, {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "[JI)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)}, + {CC"shouldDebugNonSafepoints", CC"()Z", FN_PTR(shouldDebugNonSafepoints)}, }; int CompilerToVM_methods_count() { diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/graal/graalGlobals.hpp --- a/src/share/vm/graal/graalGlobals.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/graal/graalGlobals.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -52,7 +52,13 @@ COMPILERGRAAL_PRESENT(product(bool, BootstrapGraal, true, \ "Bootstrap Graal before running Java main method")) \ \ - COMPILERGRAAL_PRESENT(product(bool, UseGraalCompilationQueue, true, \ + COMPILERGRAAL_PRESENT(product(bool, PrintBootstrap, true, \ + "Print Graal bootstrap progress and summary")) \ + \ + COMPILERGRAAL_PRESENT(product(intx, GraalThreads, 1, \ + "Force number of Graal compiler threads to use")) \ + \ + COMPILERGRAAL_PRESENT(product(bool, UseGraalCompilationQueue, false, \ "Use non-native compilation queue for Graal")) \ \ product(bool, ForceGraalInitialization, false, \ diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -701,6 +701,35 @@ JVM_END #endif +jint GraalRuntime::check_arguments(TRAPS) { + KlassHandle nullHandle; + parse_arguments(nullHandle, THREAD); + if (HAS_PENDING_EXCEPTION) { + // Errors in parsing Graal arguments cause exceptions. + // We now load and initialize HotSpotOptions which in turn + // causes argument parsing to be redone with better error messages. + CLEAR_PENDING_EXCEPTION; + TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/graal/hotspot/HotSpotOptions;", THREAD); + instanceKlassHandle hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error in check_arguments"); + + parse_arguments(hotSpotOptionsClass, THREAD); + assert(HAS_PENDING_EXCEPTION, "must be"); + + ResourceMark rm; + Handle exception = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + oop message = java_lang_Throwable::message(exception); + if (message != NULL) { + tty->print_cr("Error parsing Graal options: %s", java_lang_String::as_utf8_string(message)); + } else { + call_printStackTrace(exception, THREAD); + } + return JNI_ERR; + } + return JNI_OK; +} + bool GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) { ResourceMark rm(THREAD); @@ -716,43 +745,51 @@ return CITime || CITimeEach; } +void GraalRuntime::check_required_value(const char* name, int name_len, const char* value, TRAPS) { + if (value == NULL) { + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=' format for %.*s option", name_len, name, name_len, name); + THROW_MSG(vmSymbols::java_lang_InternalError(), buf); + } +} + void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) { char first = arg[0]; char* name; size_t name_len; - Handle name_handle; - bool valid = true; + bool recognized = true; if (first == '+' || first == '-') { name = arg + 1; name_len = strlen(name); - name_handle = java_lang_String::create_from_str(name, CHECK); - valid = set_option(hotSpotOptionsClass, name, (int)name_len, name_handle, arg, CHECK); + recognized = set_option(hotSpotOptionsClass, name, (int)name_len, arg, CHECK); } else { char* sep = strchr(arg, '='); + name = arg; + char* value = NULL; if (sep != NULL) { - name = arg; name_len = sep - name; - // Temporarily replace '=' with NULL to create the Java string for the option name - *sep = '\0'; - name_handle = java_lang_String::create_from_str(arg, THREAD); - *sep = '='; - if (HAS_PENDING_EXCEPTION) { - return; + value = sep + 1; + } else { + name_len = strlen(name); + } + recognized = set_option(hotSpotOptionsClass, name, (int)name_len, value, CHECK); + } + + if (!recognized) { + bool throw_err = hotSpotOptionsClass.is_null(); + if (!hotSpotOptionsClass.is_null()) { + set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L); + if (!HAS_PENDING_EXCEPTION) { + throw_err = true; } - valid = set_option(hotSpotOptionsClass, name, (int)name_len, name_handle, sep + 1, CHECK); - } else { + } + + if (throw_err) { char buf[200]; - jio_snprintf(buf, sizeof(buf), "Value for option %s must use '-G:%s=' format", arg, arg); + jio_snprintf(buf, sizeof(buf), "Unrecognized Graal option %.*s", name_len, name); THROW_MSG(vmSymbols::java_lang_InternalError(), buf); } } - - if (!valid) { - set_option_helper(hotSpotOptionsClass, name_handle, Handle(), ' ', Handle(), 0L); - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Invalid Graal option %s", arg); - THROW_MSG(vmSymbols::java_lang_InternalError(), buf); - } } void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { @@ -802,7 +839,8 @@ } } -jlong GraalRuntime::parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS) { +jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS) { + check_required_value(name, name_len, value, CHECK_(0L)); union { jint i; jlong l; @@ -829,23 +867,44 @@ } ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %s: %s", (spec == 'i' ? "numeric" : "float/double"), java_lang_String::as_utf8_string(name()), value); + bool missing = strlen(value) == 0; + if (missing) { + jio_snprintf(buf, sizeof(buf), "Missing %s value for Graal option %.*s", (spec == 'i' ? "numeric" : "float/double"), name_len, name); + } else { + jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %.*s: %s", (spec == 'i' ? "numeric" : "float/double"), name_len, name, value); + } THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); } -void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { +void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { Thread* THREAD = Thread::current(); + Handle name_handle; + if (name != NULL) { + if ((int) strlen(name) > name_len) { + // Temporarily replace '=' with NULL to create the Java string for the option name + char save = name[name_len]; + name[name_len] = '\0'; + name_handle = java_lang_String::create_from_str(name, THREAD); + name[name_len] = '='; + if (HAS_PENDING_EXCEPTION) { + return; + } + } else { + assert((int) strlen(name) == name_len, "must be"); + name_handle = java_lang_String::create_from_str(name, CHECK); + } + } + TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD); TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD); JavaValue result(T_VOID); JavaCallArguments args; - args.push_oop(name()); + args.push_oop(name_handle()); args.push_oop(option()); args.push_int(spec); args.push_oop(stringValue()); args.push_long(primitiveValue); - JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, THREAD); - GUARANTEE_NO_PENDING_EXCEPTION("Error while calling set_option_helper"); + JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, CHECK); } Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) { @@ -900,20 +959,23 @@ } } -void GraalRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) { - Thread* THREAD = Thread::current(); - CLEAR_PENDING_EXCEPTION; - +void GraalRuntime::call_printStackTrace(Handle exception, Thread* thread) { assert(exception->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected"); JavaValue result(T_VOID); JavaCalls::call_virtual(&result, exception, - KlassHandle(THREAD, + KlassHandle(thread, SystemDictionary::Throwable_klass()), vmSymbols::printStackTrace_name(), vmSymbols::void_method_signature(), - THREAD); + thread); +} +void GraalRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) { + Thread* THREAD = Thread::current(); + CLEAR_PENDING_EXCEPTION; + tty->print_cr(message); + call_printStackTrace(exception, THREAD); vm_abort(dump_core); } diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -45,11 +45,12 @@ * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles). * * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption()) - * @param name name option option + * @param name option name + * @param name_len length of option name * @param value string value to parse * @throws InternalError if value could not be parsed according to spec */ - static jlong parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS); + static jlong parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS); /** * Loads default option value overrides from a /lib/graal.options if it exists. Each @@ -72,15 +73,26 @@ * The definition of this method is in graalRuntime.inline.hpp * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. * + * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option + * @param name option name + * @param name_len length of option name * @returns true if the option was found * @throws InternalError if there was a problem setting the option's value */ - static bool set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS); + static bool set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS); + + /** + * Raises an InternalError for an option that expects a value but was specified without a "=" prefix. + */ + static void check_required_value(const char* name, int name_len, const char* value, TRAPS); /** * Java call to HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) + * + * @param name option name + * @param name_len length of option name */ - static void set_option_helper(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); + static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); /** * Instantiates a service object, calls its default constructor and returns it. @@ -122,6 +134,11 @@ */ static void abort_on_pending_exception(Handle exception, const char* message, bool dump_core = false); + /** + * Calls Throwable.printStackTrace() on a given exception. + */ + static void call_printStackTrace(Handle exception, Thread* thread); + #define GUARANTEE_NO_PENDING_EXCEPTION(error_message) do { \ if (HAS_PENDING_EXCEPTION) { \ GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, error_message); \ @@ -132,6 +149,18 @@ static BufferBlob* initialize_buffer_blob(); + /** + * Checks that all Graal specific VM options presented by the launcher are recognized + * and formatted correctly. To set relevant Java fields from the option, parse_arguments() + * must be called. This method makes no Java calls apart from creating exception objects + * if there is an errors in the Graal options. + */ + static jint check_arguments(TRAPS); + + /** + * Parses the Graal specific VM options that were presented by the launcher and sets + * the relevants Java fields. + */ static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS); static BasicType kindToBasicType(jchar ch); diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/prims/jni.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -5188,6 +5188,9 @@ } } else { // Graal is initialized on a CompilerThread + if (FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal) { + GraalCompiler::instance()->bootstrap(); + } } #endif diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/runtime/advancedThresholdPolicy.cpp --- a/src/share/vm/runtime/advancedThresholdPolicy.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -345,6 +345,17 @@ if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) { next_level = CompLevel_full_optimization; } else if ((this->*p)(i, b, cur_level)) { +#ifdef COMPILERGRAAL + // Since Graal takes a while to warm up, its queue inevitably backs up during + // early VM execution. As of 2014-06-13, Graal's inliner assumes that the root + // compilation method and all potential inlinees have mature profiles (which + // includes type profiling). If it sees immature profiles, Graal's inliner + // can perform pathologically bad (e.g., causing OutOfMemoryErrors due to + // exploring/inlining too many graphs). Since a rewrite of the inliner is + // in progress, we simply disable the dialing back heuristic for now and will + // revisit this decision once the new inliner is completed. + next_level = CompLevel_full_profile; +#else // C1-generated fully profiled code is about 30% slower than the limited profile // code that has only invocation and backedge counters. The observation is that // if C2 queue is large enough we can spend too much time in the fully profiled code @@ -358,6 +369,7 @@ } else { next_level = CompLevel_full_profile; } +#endif } break; case CompLevel_limited_profile: diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -1981,19 +1981,19 @@ // Note: Keep this in sync. with enum DeoptReason. "none", "null_check", - "null_assert" GRAAL_ONLY("|unreached0"), + "null_assert" GRAAL_ONLY("_or_unreached0"), "range_check", "class_check", "array_check", - "intrinsic" GRAAL_ONLY("|type_checked_inlining"), - "bimorphic" GRAAL_ONLY("|optimized_type_check"), + "intrinsic" GRAAL_ONLY("_or_type_checked_inlining"), + "bimorphic" GRAAL_ONLY("_or_optimized_type_check"), "unloaded", - "uninitialized" GRAAL_ONLY("|unresolved"), + "uninitialized" GRAAL_ONLY("_or_unresolved"), "unreached", - "unhandled" GRAAL_ONLY("|not_compiled_exception_handler"), + "unhandled" GRAAL_ONLY("_or_not_compiled_exception_handler"), "constraint", "div0_check", - "age" GRAAL_ONLY("|jsr_mismatch"), + "age" GRAAL_ONLY("_or_jsr_mismatch"), "predicate", "loop_limit_check", GRAAL_ONLY("aliasing") diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/runtime/sharedRuntime.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -886,7 +886,7 @@ // If there's no PcDesc then we'll die way down inside of // deopt instead of just getting normal error reporting, // so only go there if it will succeed. - target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check); + return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check); } else { #endif target_pc = nm->continuation_for_implicit_exception(pc); @@ -910,7 +910,7 @@ #endif #ifdef GRAAL if (nm->is_compiled_by_graal() && nm->pc_desc_at(pc) != NULL) { - target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check); + return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check); } else { #endif target_pc = nm->continuation_for_implicit_exception(pc); @@ -928,11 +928,17 @@ assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind"); - // for AbortVMOnException flag - NOT_PRODUCT(Exceptions::debug_check_abort("java.lang.NullPointerException")); if (exception_kind == IMPLICIT_NULL) { +#ifndef PRODUCT + // for AbortVMOnException flag + Exceptions::debug_check_abort("java.lang.NullPointerException"); +#endif //PRODUCT Events::log_exception(thread, "Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); } else { +#ifndef PRODUCT + // for AbortVMOnException flag + Exceptions::debug_check_abort("java.lang.ArithmeticException"); +#endif //PRODUCT Events::log_exception(thread, "Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); } return target_pc; diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/runtime/thread.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -31,6 +31,7 @@ #include "compiler/compileBroker.hpp" #ifdef GRAAL #include "graal/graalCompiler.hpp" +#include "graal/graalRuntime.hpp" #endif #include "interpreter/interpreter.hpp" #include "interpreter/linkResolver.hpp" @@ -54,6 +55,9 @@ #include "runtime/fprofiler.hpp" #include "runtime/frame.inline.hpp" #include "runtime/gpu.hpp" +#ifdef GRAAL +# include "hsail/vm/gpu_hsail.hpp" +#endif #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" @@ -1467,8 +1471,11 @@ clear_must_deopt_id(); set_monitor_chunks(NULL); set_next(NULL); +#ifdef GRAAL set_gpu_exception_bci(0); set_gpu_exception_method(NULL); + set_gpu_hsail_deopt_info(NULL); +#endif set_thread_state(_thread_new); #if INCLUDE_NMT set_recorder(NULL); @@ -2853,6 +2860,13 @@ // a scan. cf->do_code_blob(_scanned_nmethod); } + +#ifdef GRAAL + Hsail::HSAILDeoptimizationInfo* gpu_hsail_deopt_info = (Hsail::HSAILDeoptimizationInfo*) get_gpu_hsail_deopt_info(); + if (gpu_hsail_deopt_info != NULL) { + gpu_hsail_deopt_info->oops_do(f); + } +#endif } void JavaThread::nmethods_do(CodeBlobClosure* cf) { @@ -3718,6 +3732,14 @@ Chunk::start_chunk_pool_cleaner_task(); } +#ifdef GRAAL + status = GraalRuntime::check_arguments(main_thread); + if (status != JNI_OK) { + *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again + return status; + } +#endif + // initialize compiler(s) #if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) || defined(COMPILERGRAAL) CompileBroker::compilation_init(); diff -r 51f392557124 -r 5f01f7c48d40 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Mon Jun 30 08:50:26 2014 +0200 +++ b/src/share/vm/runtime/thread.hpp Mon Jun 30 12:02:19 2014 +0200 @@ -944,15 +944,24 @@ volatile address _exception_handler_pc; // PC for handler of exception volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site. +#ifdef GRAAL // Record the method and bci from a gpu kernel exception so // it can be added into the exception stack trace jint _gpu_exception_bci; Method* _gpu_exception_method; + // Record the hsailDeoptimization info so gc oops_do processing can find it + void* _gpu_hsail_deopt_info; +#endif + public: +#ifdef GRAAL void set_gpu_exception_bci(jint bci) { _gpu_exception_bci = bci; } jint get_gpu_exception_bci() { return _gpu_exception_bci; } void set_gpu_exception_method(Method* method) { _gpu_exception_method = method; } Method* get_gpu_exception_method() { return _gpu_exception_method; } + void set_gpu_hsail_deopt_info(void * deoptInfo) { _gpu_hsail_deopt_info = deoptInfo; } + void* get_gpu_hsail_deopt_info() { return _gpu_hsail_deopt_info; } +#endif private: // support for JNI critical regions diff -r 51f392557124 -r 5f01f7c48d40 test/whitelist_baseline.txt