# HG changeset patch # User Stefan Anzinger # Date 1425319882 -3600 # Node ID 96ab2078eeaff57b70a9e6e7a0369d6ad40ed6c8 # Parent 00d7b0adaf6645888c401dc3256b41d7dbb9df10# Parent a0284c1724e6ab3923979f2ee6fa233289cfffc7 Merge diff -r 00d7b0adaf66 -r 96ab2078eeaf .hgtags --- a/.hgtags Mon Mar 02 18:44:14 2015 +0100 +++ b/.hgtags Mon Mar 02 19:11:22 2015 +0100 @@ -525,3 +525,4 @@ ae5b662550836e851c39e4fbb5c80517fc62488f graal-0.5 3b60f720b955c466d913abb0113af9b38962950b graal-0.6 1b0ef9634252c422b6f9839fc62eebc112545486 gpu-0.1 +9a12234da10cfa6934617274c203672389a1bbdd baseline-0.1 diff -r 00d7b0adaf66 -r 96ab2078eeaf agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java --- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java Mon Mar 02 18:44:14 2015 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java Mon Mar 02 19:11:22 2015 +0100 @@ -65,9 +65,6 @@ } } - public void visitValueLocation(Address valueAddr) { - } - public void visitNarrowOopLocation(Address narrowOopAddr) { addressVisitor.visitCompOopAddress(narrowOopAddr); } @@ -198,9 +195,9 @@ } } - // We want narow oop, value and oop oop_types + // We want narow oop and oop oop_types OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] { - OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE + OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE }; { @@ -213,8 +210,6 @@ // to detect in the debugging system // assert(Universe::is_heap_or_null(*loc), "found non oop pointer"); visitor.visitOopLocation(loc); - } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) { - visitor.visitValueLocation(loc); } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) { visitor.visitNarrowOopLocation(loc); } diff -r 00d7b0adaf66 -r 96ab2078eeaf agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java --- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java Mon Mar 02 18:44:14 2015 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java Mon Mar 02 19:11:22 2015 +0100 @@ -49,7 +49,6 @@ // Types of OopValues static int UNUSED_VALUE; static int OOP_VALUE; - static int VALUE_VALUE; static int NARROWOOP_VALUE; static int CALLEE_SAVED_VALUE; static int DERIVED_OOP_VALUE; @@ -73,7 +72,6 @@ REGISTER_MASK_IN_PLACE = db.lookupIntConstant("OopMapValue::register_mask_in_place").intValue(); UNUSED_VALUE = db.lookupIntConstant("OopMapValue::unused_value").intValue(); OOP_VALUE = db.lookupIntConstant("OopMapValue::oop_value").intValue(); - VALUE_VALUE = db.lookupIntConstant("OopMapValue::value_value").intValue(); NARROWOOP_VALUE = db.lookupIntConstant("OopMapValue::narrowoop_value").intValue(); CALLEE_SAVED_VALUE = db.lookupIntConstant("OopMapValue::callee_saved_value").intValue(); DERIVED_OOP_VALUE = db.lookupIntConstant("OopMapValue::derived_oop_value").intValue(); @@ -82,7 +80,6 @@ public static abstract class OopTypes { public static final OopTypes UNUSED_VALUE = new OopTypes() { int getValue() { return OopMapValue.UNUSED_VALUE; }}; public static final OopTypes OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.OOP_VALUE; }}; - public static final OopTypes VALUE_VALUE = new OopTypes() { int getValue() { return OopMapValue.VALUE_VALUE; }}; public static final OopTypes NARROWOOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.NARROWOOP_VALUE; }}; public static final OopTypes CALLEE_SAVED_VALUE = new OopTypes() { int getValue() { return OopMapValue.CALLEE_SAVED_VALUE; }}; public static final OopTypes DERIVED_OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.DERIVED_OOP_VALUE; }}; @@ -105,7 +102,6 @@ // Querying public boolean isOop() { return (getValue() & TYPE_MASK_IN_PLACE) == OOP_VALUE; } - public boolean isValue() { return (getValue() & TYPE_MASK_IN_PLACE) == VALUE_VALUE; } public boolean isNarrowOop() { return (getValue() & TYPE_MASK_IN_PLACE) == NARROWOOP_VALUE; } public boolean isCalleeSaved() { return (getValue() & TYPE_MASK_IN_PLACE) == CALLEE_SAVED_VALUE; } public boolean isDerivedOop() { return (getValue() & TYPE_MASK_IN_PLACE) == DERIVED_OOP_VALUE; } @@ -117,7 +113,6 @@ int which = (getValue() & TYPE_MASK_IN_PLACE); if (which == UNUSED_VALUE) return OopTypes.UNUSED_VALUE; else if (which == OOP_VALUE) return OopTypes.OOP_VALUE; - else if (which == VALUE_VALUE) return OopTypes.VALUE_VALUE; else if (which == NARROWOOP_VALUE) return OopTypes.NARROWOOP_VALUE; else if (which == CALLEE_SAVED_VALUE) return OopTypes.CALLEE_SAVED_VALUE; else if (which == DERIVED_OOP_VALUE) return OopTypes.DERIVED_OOP_VALUE; diff -r 00d7b0adaf66 -r 96ab2078eeaf agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java --- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java Mon Mar 02 18:44:14 2015 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,6 +31,5 @@ public interface OopMapVisitor { public void visitOopLocation(Address oopAddr); public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr); - public void visitValueLocation(Address valueAddr); public void visitNarrowOopLocation(Address narrowOopAddr); } diff -r 00d7b0adaf66 -r 96ab2078eeaf agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java Mon Mar 02 18:44:14 2015 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java Mon Mar 02 19:11:22 2015 +0100 @@ -544,9 +544,6 @@ } } - public void visitValueLocation(Address valueAddr) { - } - public void visitNarrowOopLocation(Address compOopAddr) { addressVisitor.visitCompOopAddress(compOopAddr); } diff -r 00d7b0adaf66 -r 96ab2078eeaf agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java --- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Mon Mar 02 18:44:14 2015 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Mon Mar 02 19:11:22 2015 +0100 @@ -1222,9 +1222,6 @@ oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE); buf.append(omvIterator.iterate(oms, "NarrowOops:", false)); - oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE); - buf.append(omvIterator.iterate(oms, "Values:", false)); - oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); buf.append(omvIterator.iterate(oms, "Callee saved:", true)); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java Mon Mar 02 19:11:22 2015 +0100 @@ -48,6 +48,17 @@ /** * Creates a new {@link BailoutException}. * + * + * @param args parameters to the formatter + */ + public BailoutException(Throwable cause, String format, Object... args) { + super(String.format(Locale.ENGLISH, format, args), cause); + this.permanent = true; + } + + /** + * Creates a new {@link BailoutException}. + * * @param permanent specifies whether this exception will occur again if compilation is retried * @param args parameters to the formatter */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Mon Mar 02 19:11:22 2015 +0100 @@ -170,7 +170,7 @@ Kind kind = values[i].getKind(); if (kind.needsTwoSlots()) { assert values.length > i + 1 : String.format("missing second word %s", this); - assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal; + assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal : this; } } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java Mon Mar 02 19:11:22 2015 +0100 @@ -64,7 +64,7 @@ /** * Creates a CSA layout. - * + * * @param size size (in bytes) of the CSA. If this is {@code -1}, then the CSA size will be * computed from {@code registers}. * @param slotSize the size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the @@ -113,7 +113,7 @@ /** * Gets the offset of a given register in the CSA. - * + * * @return the offset (in bytes) of {@code reg} in the CSA * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA */ @@ -123,7 +123,7 @@ /** * Gets the index of a given register in the CSA. - * + * * @return the index of {@code reg} in the CSA * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA */ @@ -136,7 +136,7 @@ /** * Gets the offset of a given register in the CSA. - * + * * @return the offset (in bytes) of {@code reg} in the CSA * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA */ @@ -146,7 +146,7 @@ /** * Determines if the CSA includes a slot for a given register. - * + * * @param reg the register to test * @return true if the CSA contains a slot for {@code reg} */ @@ -156,7 +156,7 @@ /** * Gets the register whose slot in the CSA is at a given index. - * + * * @param index an index of a slot in the CSA * @return the register whose slot in the CSA is at {@code index} or {@code null} if * {@code index} does not denote a slot in the CSA aligned with a register diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java Mon Mar 02 19:11:22 2015 +0100 @@ -78,7 +78,7 @@ /** * Creates a description of the registers and stack locations used by a call. - * + * * @param stackSize amount of stack space (in bytes) required for the stack-based arguments of * the call * @param returnLocation the location for the return value or {@link Value#ILLEGAL} if a void diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -29,7 +29,7 @@ /** * Gets a textual disassembly of some given installed code. - * + * * @return a non-zero length string containing a disassembly of {@code code} or null if * {@code code} is {@link InstalledCode#isValid() invalid} or it could not be * disassembled for some other reason diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java Mon Mar 02 19:11:22 2015 +0100 @@ -57,7 +57,7 @@ /** * Determines if the foreign call target destroys all registers. - * + * * @return {@code true} if the register allocator must save all live registers around a call to * this target */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/MemoryBarriers.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/MemoryBarriers.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/MemoryBarriers.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,7 +24,7 @@ /** * Constants and intrinsic definition for memory barriers. - * + * * The documentation for each constant is taken from Doug Lea's The JSR-133 Cookbook for Compiler * Writers. @@ -32,14 +32,14 @@ * The {@code JMM_*} constants capture the memory barriers necessary to implement the Java Memory * Model with respect to volatile field accesses. Their values are explained by this comment from * templateTable_i486.cpp in the HotSpot source code: - * + * *
  * Volatile variables demand their effects be made known to all CPU's in
  * order.  Store buffers on most chips allow reads & writes to reorder; the
  * JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of
  * memory barrier (i.e., it's not sufficient that the interpreter does not
  * reorder volatile references, the hardware also must not reorder them).
- * 
+ *
  * According to the new Java Memory Model (JMM):
  * (1) All volatiles are serialized wrt to each other.
  * ALSO reads & writes act as acquire & release, so:
@@ -50,7 +50,7 @@
  * that happen BEFORE the write float down to after the write.  It's OK for
  * non-volatile memory refs that happen after the volatile write to float up
  * before it.
- * 
+ *
  * We only put in barriers around volatile refs (they are expensive), not
  * _between_ memory refs (which would require us to track the flavor of the
  * previous memory refs).  Requirements (2) and (3) require some barriers
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterAttributes.java
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterAttributes.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterAttributes.java	Mon Mar 02 19:11:22 2015 +0100
@@ -47,7 +47,7 @@
      * Creates a map from register {@linkplain Register#number numbers} to register
      * {@linkplain RegisterAttributes attributes} for a given register configuration and set of
      * registers.
-     * 
+     *
      * @param registerConfig a register configuration
      * @param registers a set of registers
      * @return an array whose length is the max register number in {@code registers} plus 1. An
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Mon Mar 02 19:11:22 2015 +0100
@@ -29,7 +29,7 @@
 
 /**
  * Manages a list of unique deoptimization reasons.
- * 
+ *
  */
 public abstract class SpeculationLog {
     private volatile Object lastFailed;
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackLockValue.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackLockValue.java	Mon Mar 02 19:11:22 2015 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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.code;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents lock information in the debug information.
+ */
+public final class StackLockValue extends AbstractValue implements JavaValue {
+
+    private static final long serialVersionUID = 8241681800464483691L;
+
+    private JavaValue owner;
+    private StackSlotValue slot;
+    private final boolean eliminated;
+
+    public StackLockValue(JavaValue owner, StackSlotValue slot, boolean eliminated) {
+        super(LIRKind.Illegal);
+        this.owner = owner;
+        this.slot = slot;
+        this.eliminated = eliminated;
+    }
+
+    public JavaValue getOwner() {
+        return owner;
+    }
+
+    public void setOwner(JavaValue newOwner) {
+        this.owner = newOwner;
+    }
+
+    public Value getSlot() {
+        return slot;
+    }
+
+    public boolean isEliminated() {
+        return eliminated;
+    }
+
+    @Override
+    public String toString() {
+        return "monitor[" + owner + (slot != null ? ", " + slot : "") + (eliminated ? ", eliminated" : "") + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 43;
+        int result = super.hashCode();
+        result = prime * result + (eliminated ? 1231 : 1237);
+        result = prime * result + owner.hashCode();
+        result = prime * result + slot.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof StackLockValue) {
+            StackLockValue other = (StackLockValue) obj;
+            return super.equals(obj) && eliminated == other.eliminated && owner.equals(other.owner) && slot.equals(other.slot);
+        }
+        return false;
+    }
+
+    public void setSlot(StackSlotValue stackSlot) {
+        assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot);
+        slot = stackSlot;
+    }
+}
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ControlFlowAnchorDirectiveTest.java
--- a/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ControlFlowAnchorDirectiveTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ControlFlowAnchorDirectiveTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -106,7 +106,7 @@
 
     @Test
     public void testDuplicate() {
-        test("verifyDuplicateSnippet", 42);
+        // test("verifyDuplicateSnippet", 42);
         test("preventDuplicateSnippet", 42);
     }
 
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/IterationDirectiveTest.java
--- a/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/IterationDirectiveTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/IterationDirectiveTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -51,7 +51,7 @@
 
     @Override
     protected boolean checkLowTierGraph(StructuredGraph graph) {
-        NodeIterable loopBeginNodes = graph.getNodes(LoopBeginNode.class);
+        NodeIterable loopBeginNodes = graph.getNodes(LoopBeginNode.TYPE);
         Assert.assertEquals("LoopBeginNode count", 1, loopBeginNodes.count());
 
         LoopBeginNode loopBeginNode = loopBeginNodes.first();
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/OpaqueDirectiveTest.java
--- a/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/OpaqueDirectiveTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/OpaqueDirectiveTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -123,7 +123,7 @@
     @Override
     protected boolean checkLowTierGraph(StructuredGraph graph) {
         OpaqueSnippet snippet = graph.method().getAnnotation(OpaqueSnippet.class);
-        for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
+        for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) {
             Assert.assertEquals(snippet.expectedReturnNode(), returnNode.result().getClass());
         }
         return true;
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ProbabilityDirectiveTest.java
--- a/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ProbabilityDirectiveTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ProbabilityDirectiveTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -48,7 +48,7 @@
 
     @Override
     protected boolean checkLowTierGraph(StructuredGraph graph) {
-        NodeIterable ifNodes = graph.getNodes(IfNode.class);
+        NodeIterable ifNodes = graph.getNodes(IfNode.TYPE);
         Assert.assertEquals("IfNode count", 1, ifNodes.count());
 
         IfNode ifNode = ifNodes.first();
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Mon Mar 02 19:11:22 2015 +0100
@@ -46,6 +46,15 @@
         assert !Double.isNaN(notRecordedProbability);
         this.notRecordedProbability = notRecordedProbability;
         assert isSorted();
+        assert totalProbablility() >= 0 && totalProbablility() <= 1.0001 : totalProbablility() + " " + this;
+    }
+
+    private double totalProbablility() {
+        double total = notRecordedProbability;
+        for (T item : pitems) {
+            total += item.probability;
+        }
+        return total;
     }
 
     /**
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java	Mon Mar 02 19:11:22 2015 +0100
@@ -30,7 +30,7 @@
     /**
      * Gets a textual disassembly of the bytecode for a given method. In the absence of bytecode
      * rewriting, disassembling a method will produce the same result.
-     * 
+     *
      * @return a non-zero length string containing a disassembly of {@code method}'s bytecode or
      *         null if {@code method} has no bytecode (i.e., {@code method.getCodeSize() == 0})
      */
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExceptionHandler.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExceptionHandler.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExceptionHandler.java	Mon Mar 02 19:11:22 2015 +0100
@@ -37,7 +37,7 @@
 
     /**
      * Creates a new exception handler with the specified ranges.
-     * 
+     *
      * @param startBCI the start index of the protected range
      * @param endBCI the end index of the protected range
      * @param catchBCI the index of the handler
@@ -83,7 +83,7 @@
 
     /**
      * Checks whether this handler catches all exceptions.
-     * 
+     *
      * @return {@code true} if this handler catches all exceptions
      */
     public boolean isCatchAll() {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Mon Mar 02 19:11:22 2015 +0100
@@ -41,6 +41,21 @@
         public static TriState get(boolean value) {
             return value ? TRUE : FALSE;
         }
+
+        /**
+         * This is optimistic about {@link #UNKNOWN} (it prefers known values over {@link #UNKNOWN})
+         * and pesimistic about known (it perfers {@link #TRUE} over {@link #FALSE}).
+         */
+        public static TriState merge(TriState a, TriState b) {
+            if (a == TRUE || b == TRUE) {
+                return TRUE;
+            }
+            if (a == FALSE || b == FALSE) {
+                return FALSE;
+            }
+            assert a == UNKNOWN && b == UNKNOWN;
+            return UNKNOWN;
+        }
     }
 
     /**
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Mar 02 19:11:22 2015 +0100
@@ -282,7 +282,7 @@
 
     /**
      * Checks whether the method has a receiver parameter - i.e., whether it is not static.
-     * 
+     *
      * @return whether the method has a receiver parameter
      */
     default boolean hasReceiver() {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Mon Mar 02 19:11:22 2015 +0100
@@ -38,7 +38,7 @@
 
     /**
      * Creates an {@link AMD64Address} with given base register, no scaling and no displacement.
-     * 
+     *
      * @param base the base register
      */
     public AMD64Address(Register base) {
@@ -48,7 +48,7 @@
     /**
      * Creates an {@link AMD64Address} with given base register, no scaling and a given
      * displacement.
-     * 
+     *
      * @param base the base register
      * @param displacement the displacement
      */
@@ -59,7 +59,7 @@
     /**
      * Creates an {@link AMD64Address} with given base and index registers, scaling and
      * displacement. This is the most general constructor.
-     * 
+     *
      * @param base the base register
      * @param index the index register
      * @param scale the scaling factor
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Mar 02 19:11:22 2015 +0100
@@ -999,7 +999,7 @@
 
     // @formatter:off
     /**
-     * Branch on (Integer|Floatingpoint) Condition Codes
+     * Branch on (Integer|Floatingpoint) Condition Codes.
      * 
      * | 00  |annul| cond| op2 |               disp22                 |
      * |31 30|29   |28 25|24 22|21                                   0|
@@ -1043,7 +1043,7 @@
 
     // @formatter:off
     /**
-     * Used for fbpcc (Float) and bpcc (Integer)
+     * Used for fbpcc (Float) and bpcc (Integer).
      * 
      * | 00  |an|cond | op2 |cc1 2|p |           disp19               |
      * |31 30|29|28 25|24 22|21 20|19|                               0|
@@ -1237,12 +1237,12 @@
         int d10 = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
         assert isSimm(d10, 10) && isImm(rs2, 5);
         d10 &= (1 << 10) - 1;
-        final int c_lo = cf.value & 0b111;
-        final int c_hi = cf.value >> 3;
-        final int d10_lo = d10 & ((1 << 8) - 1);
-        final int d10_hi = d10 >> 8;
-        int a = c_hi << 4 | 0b1000 | c_lo;
-        int b = cc2 << 21 | d10_hi << D10HI_SHIFT | rs1.encoding << 14 | i << 13 | d10_lo << D10LO_SHIFT | rs2;
+        final int cLo = cf.value & 0b111;
+        final int cHi = cf.value >> 3;
+        final int d10Lo = d10 & ((1 << 8) - 1);
+        final int d10Hi = d10 >> 8;
+        int a = cHi << 4 | 0b1000 | cLo;
+        int b = cc2 << 21 | d10Hi << D10HI_SHIFT | rs1.encoding << 14 | i << 13 | d10Lo << D10LO_SHIFT | rs2;
         fmt00(a, Op2s.Bpr.value, b);
     }
 
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeLookupSwitch.java
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeLookupSwitch.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeLookupSwitch.java	Mon Mar 02 19:11:22 2015 +0100
@@ -34,7 +34,7 @@
 
     /**
      * Constructor for a {@link BytecodeStream}.
-     * 
+     *
      * @param stream the {@code BytecodeStream} containing the switch instruction
      * @param bci the index in the stream of the switch instruction
      */
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java	Mon Mar 02 19:11:22 2015 +0100
@@ -36,7 +36,7 @@
 
     /**
      * Creates a new {@code BytecodeStream} for the specified bytecode.
-     * 
+     *
      * @param code the array of bytes that contains the bytecode
      */
     public BytecodeStream(byte[] code) {
@@ -54,7 +54,7 @@
 
     /**
      * Gets the next bytecode index (no side-effects).
-     * 
+     *
      * @return the next bytecode index
      */
     public int nextBCI() {
@@ -63,7 +63,7 @@
 
     /**
      * Gets the current bytecode index.
-     * 
+     *
      * @return the current bytecode index
      */
     public int currentBCI() {
@@ -72,7 +72,7 @@
 
     /**
      * Gets the bytecode index of the end of the code.
-     * 
+     *
      * @return the index of the end of the code
      */
     public int endBCI() {
@@ -82,7 +82,7 @@
     /**
      * Gets the current opcode. This method will never return the {@link Bytecodes#WIDE WIDE}
      * opcode, but will instead return the opcode that is modified by the {@code WIDE} opcode.
-     * 
+     *
      * @return the current opcode; {@link Bytecodes#END} if at or beyond the end of the code
      */
     public int currentBC() {
@@ -96,7 +96,7 @@
     /**
      * Reads the index of a local variable for one of the load or store instructions. The WIDE
      * modifier is handled internally.
-     * 
+     *
      * @return the index of the local variable
      */
     public int readLocalIndex() {
@@ -109,7 +109,7 @@
 
     /**
      * Read the delta for an {@link Bytecodes#IINC} bytecode.
-     * 
+     *
      * @return the delta for the {@code IINC}
      */
     public int readIncrement() {
@@ -122,7 +122,7 @@
 
     /**
      * Read the destination of a {@link Bytecodes#GOTO} or {@code IF} instructions.
-     * 
+     *
      * @return the destination bytecode index
      */
     public int readBranchDest() {
@@ -136,7 +136,7 @@
 
     /**
      * Read a signed 4-byte integer from the bytecode stream at the specified bytecode index.
-     * 
+     *
      * @param bci the bytecode index
      * @return the integer value
      */
@@ -147,7 +147,7 @@
 
     /**
      * Reads an unsigned, 1-byte value from the bytecode stream at the specified bytecode index.
-     * 
+     *
      * @param bci the bytecode index
      * @return the byte
      */
@@ -157,7 +157,7 @@
 
     /**
      * Reads a constant pool index for the current instruction.
-     * 
+     *
      * @return the constant pool index
      */
     public char readCPI() {
@@ -169,7 +169,7 @@
 
     /**
      * Reads a constant pool index for an invokedynamic instruction.
-     * 
+     *
      * @return the constant pool index
      */
     public int readCPI4() {
@@ -179,7 +179,7 @@
 
     /**
      * Reads a signed, 1-byte value for the current instruction (e.g. BIPUSH).
-     * 
+     *
      * @return the byte
      */
     public byte readByte() {
@@ -188,7 +188,7 @@
 
     /**
      * Reads a signed, 2-byte short for the current instruction (e.g. SIPUSH).
-     * 
+     *
      * @return the short value
      */
     public short readShort() {
@@ -199,7 +199,7 @@
      * Sets the bytecode index to the specified value. If {@code bci} is beyond the end of the
      * array, {@link #currentBC} will return {@link Bytecodes#END} and other methods may throw
      * {@link ArrayIndexOutOfBoundsException}.
-     * 
+     *
      * @param bci the new bytecode index
      */
     public void setBCI(int bci) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeSwitch.java
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeSwitch.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeSwitch.java	Mon Mar 02 19:11:22 2015 +0100
@@ -44,7 +44,7 @@
 
     /**
      * Constructor for a {@link BytecodeStream}.
-     * 
+     *
      * @param stream the {@code BytecodeStream} containing the switch instruction
      * @param bci the index in the stream of the switch instruction
      */
@@ -56,7 +56,7 @@
 
     /**
      * Gets the current bytecode index.
-     * 
+     *
      * @return the current bytecode index
      */
     public int bci() {
@@ -65,7 +65,7 @@
 
     /**
      * Gets the index of the instruction denoted by the {@code i}'th switch target.
-     * 
+     *
      * @param i index of the switch target
      * @return the index of the instruction denoted by the {@code i}'th switch target
      */
@@ -75,7 +75,7 @@
 
     /**
      * Gets the index of the instruction for the default switch target.
-     * 
+     *
      * @return the index of the instruction for the default switch target
      */
     public int defaultTarget() {
@@ -84,7 +84,7 @@
 
     /**
      * Gets the offset from the start of the switch instruction to the default switch target.
-     * 
+     *
      * @return the offset to the default switch target
      */
     public int defaultOffset() {
@@ -93,7 +93,7 @@
 
     /**
      * Gets the key at {@code i}'th switch target index.
-     * 
+     *
      * @param i the switch target index
      * @return the key at {@code i}'th switch target index
      */
@@ -101,7 +101,7 @@
 
     /**
      * Gets the offset from the start of the switch instruction for the {@code i}'th switch target.
-     * 
+     *
      * @param i the switch target index
      * @return the offset to the {@code i}'th switch target
      */
@@ -109,14 +109,14 @@
 
     /**
      * Gets the number of switch targets.
-     * 
+     *
      * @return the number of switch targets
      */
     public abstract int numberOfCases();
 
     /**
      * Gets the total size in bytes of the switch instruction.
-     * 
+     *
      * @return the total size in bytes of the switch instruction
      */
     public abstract int size();
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeTableSwitch.java
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeTableSwitch.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeTableSwitch.java	Mon Mar 02 19:11:22 2015 +0100
@@ -34,7 +34,7 @@
 
     /**
      * Constructor for a {@link BytecodeStream}.
-     * 
+     *
      * @param stream the {@code BytecodeStream} containing the switch instruction
      * @param bci the index in the stream of the switch instruction
      */
@@ -44,7 +44,7 @@
 
     /**
      * Gets the low key of the table switch.
-     * 
+     *
      * @return the low key
      */
     public int lowKey() {
@@ -53,7 +53,7 @@
 
     /**
      * Gets the high key of the table switch.
-     * 
+     *
      * @return the high key
      */
     public int highKey() {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytes.java
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytes.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytes.java	Mon Mar 02 19:11:22 2015 +0100
@@ -29,7 +29,7 @@
 
     /**
      * Gets a signed 1-byte value.
-     * 
+     *
      * @param data the array containing the data
      * @param bci the start index of the value to retrieve
      * @return the signed 1-byte value at index {@code bci} in array {@code data}
@@ -40,7 +40,7 @@
 
     /**
      * Gets a signed 2-byte big-endian value.
-     * 
+     *
      * @param data the array containing the data
      * @param bci the start index of the value to retrieve
      * @return the signed 2-byte, big-endian, value at index {@code bci} in array {@code data}
@@ -51,7 +51,7 @@
 
     /**
      * Gets an unsigned 1-byte value.
-     * 
+     *
      * @param data the array containing the data
      * @param bci the start index of the value to retrieve
      * @return the unsigned 1-byte value at index {@code bci} in array {@code data}
@@ -62,7 +62,7 @@
 
     /**
      * Gets an unsigned 2-byte big-endian value.
-     * 
+     *
      * @param data the array containing the data
      * @param bci the start index of the value to retrieve
      * @return the unsigned 2-byte, big-endian, value at index {@code bci} in array {@code data}
@@ -73,7 +73,7 @@
 
     /**
      * Gets a signed 4-byte big-endian value.
-     * 
+     *
      * @param data the array containing the data
      * @param bci the start index of the value to retrieve
      * @return the signed 4-byte, big-endian, value at index {@code bci} in array {@code data}
@@ -84,7 +84,7 @@
 
     /**
      * Gets either a signed 2-byte or a signed 4-byte big-endian value.
-     * 
+     *
      * @param data the array containing the data
      * @param bci the start index of the value to retrieve
      * @param fourByte if true, this method will return a 4-byte value
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Mar 02 19:11:22 2015 +0100
@@ -81,7 +81,7 @@
 
     private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(Kind.Int));
 
-    private class AMD64SpillMoveFactory implements LIR.SpillMoveFactory {
+    private class AMD64SpillMoveFactory implements LIRGeneratorTool.SpillMoveFactory {
 
         @Override
         public LIRInstruction createMove(AllocatableValue result, Value input) {
@@ -91,7 +91,10 @@
 
     public AMD64LIRGenerator(LIRKindTool lirKindTool, Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
         super(lirKindTool, providers, cc, lirGenRes);
-        lirGenRes.getLIR().setSpillMoveFactory(new AMD64SpillMoveFactory());
+    }
+
+    public SpillMoveFactory getSpillMoveFactory() {
+        return new AMD64SpillMoveFactory();
     }
 
     @Override
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon Mar 02 19:11:22 2015 +0100
@@ -61,7 +61,21 @@
         if ((valueNode instanceof IntegerDivNode) || (valueNode instanceof IntegerRemNode)) {
             FixedBinaryNode divRem = (FixedBinaryNode) valueNode;
             FixedNode node = divRem.next();
-            while (node instanceof FixedWithNextNode) {
+            while (true) {
+                if (node instanceof IfNode) {
+                    IfNode ifNode = (IfNode) node;
+                    double probability = ifNode.getTrueSuccessorProbability();
+                    if (probability == 1.0) {
+                        node = ifNode.trueSuccessor();
+                    } else if (probability == 0.0) {
+                        node = ifNode.falseSuccessor();
+                    } else {
+                        break;
+                    }
+                } else if (!(node instanceof FixedWithNextNode)) {
+                    break;
+                }
+
                 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node;
                 if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
                     FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java	Mon Mar 02 19:11:22 2015 +0100
@@ -22,24 +22,20 @@
  */
 package com.oracle.graal.compiler.common;
 
-import java.util.concurrent.*;
-
-public abstract class FieldIntrospection extends UnsafeAccess {
+public abstract class FieldIntrospection extends UnsafeAccess {
 
-    protected static final ConcurrentHashMap, FieldIntrospection> allClasses = new ConcurrentHashMap<>();
-
-    private final Class clazz;
+    private final Class clazz;
 
     /**
      * The set of fields in {@link #clazz} that do long belong to a more specific category.
      */
     protected Fields data;
 
-    public FieldIntrospection(Class clazz) {
+    public FieldIntrospection(Class clazz) {
         this.clazz = clazz;
     }
 
-    public Class getClazz() {
+    public Class getClazz() {
         return clazz;
     }
 
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Mon Mar 02 19:11:22 2015 +0100
@@ -143,6 +143,9 @@
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue PrintFilter = new OptionValue<>(null);
 
+    @Option(help = "", type = OptionType.Debug)
+    public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false);
+
     // Debug settings:
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue BootstrapReplacements = new OptionValue<>(false);
@@ -201,7 +204,7 @@
     public static final OptionValue PrintBailout = new OptionValue<>(false);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue TraceEscapeAnalysis = new OptionValue<>(false);
+    public static final StableOptionValue TraceEscapeAnalysis = new StableOptionValue<>(false);
 
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue ExitVMOnBailout = new OptionValue<>(false);
@@ -307,7 +310,7 @@
     public static final OptionValue OptFloatingReads = new OptionValue<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue OptTailDuplication = new OptionValue<>(true);
+    public static final OptionValue OptTailDuplication = new OptionValue<>(false);
 
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
@@ -334,6 +337,9 @@
     @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug)
     public static final OptionValue MaximumLoopExplosionCount = new OptionValue<>(10000);
 
+    @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug)
+    public static final OptionValue FailedLoopExplosionIsFatal = new OptionValue<>(false);
+
     /**
      * Counts the various paths taken through snippets.
      */
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/ComputeBlockOrder.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/ComputeBlockOrder.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/ComputeBlockOrder.java	Mon Mar 02 19:11:22 2015 +0100
@@ -66,7 +66,7 @@
      *
      * @return sorted list of blocks
      */
-    public static > List computeLinearScanOrder(int blockCount, T startBlock) {
+    public static > List computeLinearScanOrder(int blockCount, T startBlock) {
         List order = new ArrayList<>();
         BitSet visitedBlocks = new BitSet(blockCount);
         PriorityQueue worklist = initializeWorklist(startBlock, visitedBlocks);
@@ -80,7 +80,7 @@
      *
      * @return sorted list of blocks
      */
-    public static > List computeCodeEmittingOrder(int blockCount, T startBlock) {
+    public static > List computeCodeEmittingOrder(int blockCount, T startBlock) {
         List order = new ArrayList<>();
         BitSet visitedBlocks = new BitSet(blockCount);
         PriorityQueue worklist = initializeWorklist(startBlock, visitedBlocks);
@@ -92,7 +92,7 @@
     /**
      * Iteratively adds paths to the code emission block order.
      */
-    private static > void computeCodeEmittingOrder(List order, PriorityQueue worklist, BitSet visitedBlocks) {
+    private static > void computeCodeEmittingOrder(List order, PriorityQueue worklist, BitSet visitedBlocks) {
         while (!worklist.isEmpty()) {
             T nextImportantPath = worklist.poll();
             addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks);
@@ -102,7 +102,7 @@
     /**
      * Iteratively adds paths to the linear scan block order.
      */
-    private static > void computeLinearScanOrder(List order, PriorityQueue worklist, BitSet visitedBlocks) {
+    private static > void computeLinearScanOrder(List order, PriorityQueue worklist, BitSet visitedBlocks) {
         while (!worklist.isEmpty()) {
             T nextImportantPath = worklist.poll();
             addPathToLinearScanOrder(nextImportantPath, order, worklist, visitedBlocks);
@@ -112,7 +112,7 @@
     /**
      * Initializes the priority queue used for the work list of blocks and adds the start block.
      */
-    private static > PriorityQueue initializeWorklist(T startBlock, BitSet visitedBlocks) {
+    private static > PriorityQueue initializeWorklist(T startBlock, BitSet visitedBlocks) {
         PriorityQueue result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, new BlockOrderComparator<>());
         result.add(startBlock);
         visitedBlocks.set(startBlock.getId());
@@ -122,7 +122,7 @@
     /**
      * Add a linear path to the linear scan order greedily following the most likely successor.
      */
-    private static > void addPathToLinearScanOrder(T block, List order, PriorityQueue worklist, BitSet visitedBlocks) {
+    private static > void addPathToLinearScanOrder(T block, List order, PriorityQueue worklist, BitSet visitedBlocks) {
         block.setLinearScanNumber(order.size());
         order.add(block);
         T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks);
@@ -151,7 +151,7 @@
     /**
      * Add a linear path to the code emission order greedily following the most likely successor.
      */
-    private static > void addPathToCodeEmittingOrder(T initialBlock, List order, PriorityQueue worklist, BitSet visitedBlocks) {
+    private static > void addPathToCodeEmittingOrder(T initialBlock, List order, PriorityQueue worklist, BitSet visitedBlocks) {
         T block = initialBlock;
         while (block != null) {
             // Skip loop headers if there is only a single loop end block to
@@ -191,7 +191,7 @@
     /**
      * Adds a block to the ordering.
      */
-    private static > void addBlock(T header, List order) {
+    private static > void addBlock(T header, List order) {
         assert !order.contains(header) : "Cannot insert block twice";
         order.add(header);
     }
@@ -199,7 +199,7 @@
     /**
      * Find the highest likely unvisited successor block of a given block.
      */
-    private static > T findAndMarkMostLikelySuccessor(T block, BitSet visitedBlocks) {
+    private static > T findAndMarkMostLikelySuccessor(T block, BitSet visitedBlocks) {
         T result = null;
         for (T successor : block.getSuccessors()) {
             assert successor.probability() >= 0.0 : "Probabilities must be positive";
@@ -216,7 +216,7 @@
     /**
      * Add successor blocks into the given work list if they are not already marked as visited.
      */
-    private static > void enqueueSuccessors(T block, PriorityQueue worklist, BitSet visitedBlocks) {
+    private static > void enqueueSuccessors(T block, PriorityQueue worklist, BitSet visitedBlocks) {
         for (T successor : block.getSuccessors()) {
             if (!visitedBlocks.get(successor.getId())) {
                 visitedBlocks.set(successor.getId());
@@ -229,14 +229,14 @@
      * Skip the loop header block if the loop consists of more than one block and it has only a
      * single loop end block.
      */
-    private static > boolean skipLoopHeader(AbstractBlock block) {
+    private static > boolean skipLoopHeader(AbstractBlockBase block) {
         return (block.isLoopHeader() && !block.isLoopEnd() && block.getLoop().numBackedges() == 1);
     }
 
     /**
      * Checks that the ordering contains the expected number of blocks.
      */
-    private static boolean checkOrder(List> order, int expectedBlockCount) {
+    private static boolean checkOrder(List> order, int expectedBlockCount) {
         assert order.size() == expectedBlockCount : String.format("Number of blocks in ordering (%d) does not match expected block count (%d)", order.size(), expectedBlockCount);
         return true;
     }
@@ -244,7 +244,7 @@
     /**
      * Comparator for sorting blocks based on loop depth and probability.
      */
-    private static class BlockOrderComparator> implements Comparator {
+    private static class BlockOrderComparator> implements Comparator {
 
         @Override
         public int compare(T a, T b) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * 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.compiler.common.cfg;
-
-import java.util.*;
-
-public interface AbstractBlock> {
-
-    int getId();
-
-    Loop getLoop();
-
-    void setLoop(Loop loop);
-
-    int getLoopDepth();
-
-    boolean isLoopHeader();
-
-    boolean isLoopEnd();
-
-    boolean isExceptionEntry();
-
-    List getPredecessors();
-
-    int getPredecessorCount();
-
-    List getSuccessors();
-
-    int getSuccessorCount();
-
-    int getLinearScanNumber();
-
-    void setLinearScanNumber(int linearScanNumber);
-
-    boolean isAligned();
-
-    void setAlign(boolean align);
-
-    T getDominator();
-
-    void setDominator(T block);
-
-    List getDominated();
-
-    void setDominated(List blocks);
-
-    T getPostdominator();
-
-    double probability();
-
-}
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java	Mon Mar 02 19:11:22 2015 +0100
@@ -24,9 +24,10 @@
 
 import java.util.*;
 
-public abstract class AbstractBlockBase> implements AbstractBlock {
+public abstract class AbstractBlockBase> {
 
     protected int id;
+    protected int domDepth;
 
     protected List predecessors;
     protected List successors;
@@ -72,6 +73,11 @@
 
     public void setDominator(T dominator) {
         this.dominator = dominator;
+        this.domDepth = dominator.domDepth + 1;
+    }
+
+    public int getDominatorDepth() {
+        return domDepth;
     }
 
     public List getDominated() {
@@ -113,4 +119,20 @@
     public void setAlign(boolean align) {
         this.align = align;
     }
+
+    public abstract boolean isExceptionEntry();
+
+    public abstract Loop getLoop();
+
+    public abstract int getLoopDepth();
+
+    public abstract boolean isLoopEnd();
+
+    public abstract boolean isLoopHeader();
+
+    public abstract T getPostdominator();
+
+    public abstract double probability();
+
+    public abstract T getDominator(int distance);
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java	Mon Mar 02 19:11:22 2015 +0100
@@ -24,9 +24,7 @@
 
 import java.util.*;
 
-import com.oracle.graal.compiler.common.*;
-
-public interface AbstractControlFlowGraph> {
+public interface AbstractControlFlowGraph> {
 
     int BLOCK_ID_INITIAL = -1;
     int BLOCK_ID_VISITED = -2;
@@ -48,7 +46,7 @@
     /**
      * Computes the dominators of control flow graph.
      */
-    static > void computeDominators(AbstractControlFlowGraph cfg) {
+    static > void computeDominators(AbstractControlFlowGraph cfg) {
         List reversePostOrder = cfg.getBlocks();
         assert reversePostOrder.get(0).getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator";
         for (int i = 1; i < reversePostOrder.size(); i++) {
@@ -72,27 +70,23 @@
     /**
      * True if block {@code a} is dominated by block {@code b}.
      */
-    static boolean isDominatedBy(AbstractBlock a, AbstractBlock b) {
-        assert a != null;
-        AbstractBlock dominator = a;
-        int i = 0;
-        while (dominator != null) {
-            if (i++ == Integer.MAX_VALUE) { // For safety
-                throw GraalInternalError.shouldNotReachHere();
-            }
-            if (dominator == b) {
-                return true;
-            }
-            dominator = dominator.getDominator();
+    static boolean isDominatedBy(AbstractBlockBase a, AbstractBlockBase b) {
+        assert a != null && b != null;
+        if (a == b) {
+            return true;
         }
-        return false;
+        if (a.getDominatorDepth() < b.getDominatorDepth()) {
+            return false;
+        }
+
+        return b == (AbstractBlockBase) a.getDominator(a.getDominatorDepth() - b.getDominatorDepth());
     }
 
     /**
      * True if block {@code a} dominates block {@code b}.
      */
-    static boolean dominates(AbstractBlock a, AbstractBlock b) {
-        assert a != null;
+    static boolean dominates(AbstractBlockBase a, AbstractBlockBase b) {
+        assert a != null && b != null;
         return isDominatedBy(b, a);
     }
 
@@ -104,31 +98,36 @@
      * @see #getBlocks()
      * @see CFGVerifier
      */
-    static AbstractBlock commonDominator(AbstractBlock a, AbstractBlock b) {
+    static AbstractBlockBase commonDominator(AbstractBlockBase a, AbstractBlockBase b) {
         if (a == null) {
             return b;
         }
         if (b == null) {
             return a;
         }
-        AbstractBlock iterA = a;
-        AbstractBlock iterB = b;
+
+        AbstractBlockBase iterA = a;
+        AbstractBlockBase iterB = b;
+        int aDomDepth = a.getDominatorDepth();
+        int bDomDepth = b.getDominatorDepth();
+        if (aDomDepth > bDomDepth) {
+            iterA = a.getDominator(aDomDepth - bDomDepth);
+        } else {
+            iterB = b.getDominator(bDomDepth - aDomDepth);
+        }
+
         while (iterA != iterB) {
-            if (iterA.getId() > iterB.getId()) {
-                iterA = iterA.getDominator();
-            } else {
-                assert iterB.getId() > iterA.getId();
-                iterB = iterB.getDominator();
-            }
+            iterA = iterA.getDominator();
+            iterB = iterB.getDominator();
         }
         return iterA;
     }
 
     /**
-     * @see AbstractControlFlowGraph#commonDominator(AbstractBlock, AbstractBlock)
+     * @see AbstractControlFlowGraph#commonDominator(AbstractBlockBase, AbstractBlockBase)
      */
     @SuppressWarnings("unchecked")
-    static > T commonDominatorTyped(T a, T b) {
+    static > T commonDominatorTyped(T a, T b) {
         return (T) commonDominator(a, b);
     }
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/BlockMap.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/BlockMap.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/BlockMap.java	Mon Mar 02 19:11:22 2015 +0100
@@ -31,11 +31,11 @@
         data = (T[]) new Object[cfg.getBlocks().size()];
     }
 
-    public T get(AbstractBlock block) {
+    public T get(AbstractBlockBase block) {
         return data[block.getId()];
     }
 
-    public void put(AbstractBlock block, T value) {
+    public void put(AbstractBlockBase block, T value) {
         data[block.getId()] = value;
     }
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/CFGVerifier.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/CFGVerifier.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/CFGVerifier.java	Mon Mar 02 19:11:22 2015 +0100
@@ -26,7 +26,7 @@
 
 public class CFGVerifier {
 
-    public static , C extends AbstractControlFlowGraph> boolean verify(C cfg) {
+    public static , C extends AbstractControlFlowGraph> boolean verify(C cfg) {
         for (T block : cfg.getBlocks()) {
             assert block.getId() >= 0;
             assert cfg.getBlocks().get(block.getId()) == block;
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/DominatorOptimizationProblem.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/DominatorOptimizationProblem.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/DominatorOptimizationProblem.java	Mon Mar 02 19:11:22 2015 +0100
@@ -36,7 +36,7 @@
  */
 public abstract class DominatorOptimizationProblem, C> {
 
-    private List> blocks;
+    private List> blocks;
     private EnumMap flags;
     private BlockMap costs;
 
@@ -47,9 +47,9 @@
         assert verify(blocks);
     }
 
-    private static boolean verify(List> blocks) {
+    private static boolean verify(List> blocks) {
         for (int i = 0; i < blocks.size(); i++) {
-            AbstractBlock block = blocks.get(i);
+            AbstractBlockBase block = blocks.get(i);
             if (i != block.getId()) {
                 assert false : String.format("Id index mismatch @ %d vs. %s.getId()==%d", i, block, block.getId());
                 return false;
@@ -58,12 +58,12 @@
         return true;
     }
 
-    public final List> getBlocks() {
+    public final List> getBlocks() {
         return blocks;
     }
 
-    public final AbstractBlock getBlockForId(int id) {
-        AbstractBlock block = blocks.get(id);
+    public final AbstractBlockBase getBlockForId(int id) {
+        AbstractBlockBase block = blocks.get(id);
         assert block.getId() == id : "wrong block-to-id mapping";
         return block;
     }
@@ -71,7 +71,7 @@
     /**
      * Sets a flag for a block.
      */
-    public final void set(E flag, AbstractBlock block) {
+    public final void set(E flag, AbstractBlockBase block) {
         BitSet bitSet = flags.get(flag);
         if (bitSet == null) {
             bitSet = new BitSet(blocks.size());
@@ -83,7 +83,7 @@
     /**
      * Checks whether a flag is set for a block.
      */
-    public final boolean get(E flag, AbstractBlock block) {
+    public final boolean get(E flag, AbstractBlockBase block) {
         BitSet bitSet = flags.get(flag);
         return bitSet == null ? false : bitSet.get(block.getId());
     }
@@ -91,14 +91,14 @@
     /**
      * Returns a {@linkplain Stream} of blocks for which {@code flag} is set.
      */
-    public final Stream> stream(E flag) {
+    public final Stream> stream(E flag) {
         return getBlocks().stream().filter(block -> get(flag, block));
     }
 
     /**
      * Returns the cost object associated with {@code block}. Might return {@code null} if not set.
      */
-    public final C getCost(AbstractBlock block) {
+    public final C getCost(AbstractBlockBase block) {
         C cost = costs.get(block);
         return cost;
     }
@@ -106,7 +106,7 @@
     /**
      * Sets the cost for a {@code block}.
      */
-    public final void setCost(AbstractBlock block, C cost) {
+    public final void setCost(AbstractBlockBase block, C cost) {
         costs.put(block, cost);
     }
 
@@ -114,13 +114,13 @@
      * Sets {@code flag} for all blocks along the dominator path from {@code block} to the root
      * until a block it finds a block where {@code flag} is already set.
      */
-    public final void setDominatorPath(E flag, AbstractBlock block) {
+    public final void setDominatorPath(E flag, AbstractBlockBase block) {
         BitSet bitSet = flags.get(flag);
         if (bitSet == null) {
             bitSet = new BitSet(blocks.size());
             flags.put(flag, bitSet);
         }
-        for (AbstractBlock b = block; b != null && !bitSet.get(b.getId()); b = b.getDominator()) {
+        for (AbstractBlockBase b = block; b != null && !bitSet.get(b.getId()); b = b.getDominator()) {
             // mark block
             bitSet.set(b.getId());
         }
@@ -129,7 +129,7 @@
     /**
      * Returns a {@link Stream} of flags associated with {@code block}.
      */
-    public final Stream getFlagsForBlock(AbstractBlock block) {
+    public final Stream getFlagsForBlock(AbstractBlockBase block) {
         return getFlags().stream().filter(flag -> get(flag, block));
     }
 
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/Loop.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/Loop.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/Loop.java	Mon Mar 02 19:11:22 2015 +0100
@@ -25,7 +25,7 @@
 
 import java.util.*;
 
-public abstract class Loop> {
+public abstract class Loop> {
 
     private final Loop parent;
     private final List> children;
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableCFG.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableCFG.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableCFG.java	Mon Mar 02 19:11:22 2015 +0100
@@ -31,7 +31,7 @@
  */
 public interface PrintableCFG {
 
-    List> getBlocks();
+    List> getBlocks();
 
     /**
      * Applies {@code action} to all extra property pairs (name, value) of {@code block}.
@@ -39,7 +39,7 @@
      * @param block a block from {@link #getBlocks()}.
      * @param action a {@link BiConsumer consumer}.
      */
-    default void forEachPropertyPair(AbstractBlock block, BiConsumer action) {
+    default void forEachPropertyPair(AbstractBlockBase block, BiConsumer action) {
         // no extra properties per default
     }
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableDominatorOptimizationProblem.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableDominatorOptimizationProblem.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableDominatorOptimizationProblem.java	Mon Mar 02 19:11:22 2015 +0100
@@ -33,7 +33,7 @@
         super(keyType, cfg);
     }
 
-    public void forEachPropertyPair(AbstractBlock block, BiConsumer action) {
+    public void forEachPropertyPair(AbstractBlockBase block, BiConsumer action) {
         // for each flag
         getFlags().forEach(flag -> ((BiConsumer) (name, value) -> action.accept(name, value ? "true" : "false")).accept(getName(flag), get(flag, block)));
         // for each property
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/ArrayMap.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/ArrayMap.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/ArrayMap.java	Mon Mar 02 19:11:22 2015 +0100
@@ -45,7 +45,7 @@
     /**
      * Constructs a new {@code ArrayMap} that initially covers the specified interval. Note that
      * this map will automatically expand if necessary later.
-     * 
+     *
      * @param low the low index, inclusive
      * @param high the high index, exclusive
      */
@@ -56,7 +56,7 @@
 
     /**
      * Puts a new value in the map at the specified index.
-     * 
+     *
      * @param i the index at which to store the value
      * @param value the value to store at the specified index
      */
@@ -81,7 +81,7 @@
 
     /**
      * Gets the value at the specified index in the map.
-     * 
+     *
      * @param i the index
      * @return the value at the specified index; {@code null} if there is no value at the specified
      *         index, or if the index is out of the currently stored range
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/IntList.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/IntList.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/IntList.java	Mon Mar 02 19:11:22 2015 +0100
@@ -26,7 +26,7 @@
 
 /**
  * An expandable and indexable list of {@code int}s.
- * 
+ *
  * This class avoids the boxing/unboxing incurred by {@code ArrayList}.
  */
 public final class IntList {
@@ -36,7 +36,7 @@
 
     /**
      * Creates an int list with a specified initial capacity.
-     * 
+     *
      * @param initialCapacity
      */
     public IntList(int initialCapacity) {
@@ -45,7 +45,7 @@
 
     /**
      * Creates an int list with a specified initial array.
-     * 
+     *
      * @param array the initial array used for the list (no copy is made)
      * @param initialSize the initial {@linkplain #size() size} of the list (must be less than or
      *            equal to {@code array.length}
@@ -58,7 +58,7 @@
 
     /**
      * Makes a new int list by copying a range from a given int list.
-     * 
+     *
      * @param other the list from which a range of values is to be copied into the new list
      * @param startIndex the index in {@code other} at which to start copying
      * @param length the number of values to copy from {@code other}
@@ -70,7 +70,7 @@
 
     /**
      * Makes a new int list by copying a range from a given int list.
-     * 
+     *
      * @param other the list from which a range of values is to be copied into the new list
      * @param startIndex the index in {@code other} at which to start copying
      * @param length the number of values to copy from {@code other}
@@ -91,7 +91,7 @@
 
     /**
      * Appends a value to the end of this list, increasing its {@linkplain #size() size} by 1.
-     * 
+     *
      * @param value the value to append
      */
     public void add(int value) {
@@ -104,7 +104,7 @@
 
     /**
      * Gets the value in this list at a given index.
-     * 
+     *
      * @param index the index of the element to return
      * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
      */
@@ -124,7 +124,7 @@
 
     /**
      * Sets a value at a given index in this list.
-     * 
+     *
      * @param index the index of the element to update
      * @param value the new value of the element
      * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
@@ -138,11 +138,11 @@
 
     /**
      * Adjusts the {@linkplain #size() size} of this int list.
-     * 
+     *
      * If {@code newSize < size()}, the size is changed to {@code newSize}. If
      * {@code newSize > size()}, sufficient 0 elements are {@linkplain #add(int) added} until
      * {@code size() == newSize}.
-     * 
+     *
      * @param newSize the new size of this int list
      */
     public void setSize(int newSize) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCAllocatorTest.java
--- a/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCAllocatorTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCAllocatorTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -47,7 +47,7 @@
 
     @Test
     public void test2() {
-        testAllocation("test2snippet", 2, 1, 0);
+        testAllocation("test2snippet", 1, 0, 0);
     }
 
     public static long test2snippet(long x) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Mar 02 19:11:22 2015 +0100
@@ -70,7 +70,7 @@
 
     private StackSlotValue tmpStackSlot;
 
-    private class SPARCSpillMoveFactory implements LIR.SpillMoveFactory {
+    private class SPARCSpillMoveFactory implements LIRGeneratorTool.SpillMoveFactory {
 
         @Override
         public LIRInstruction createMove(AllocatableValue result, Value input) {
@@ -80,7 +80,10 @@
 
     public SPARCLIRGenerator(LIRKindTool lirKindTool, Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
         super(lirKindTool, providers, cc, lirGenRes);
-        lirGenRes.getLIR().setSpillMoveFactory(new SPARCSpillMoveFactory());
+    }
+
+    public SpillMoveFactory getSpillMoveFactory() {
+        return new SPARCSpillMoveFactory();
     }
 
     @Override
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -300,8 +300,8 @@
 
     final ValueNode getResult(String snippet) {
         processMethod(snippet);
-        assertDeepEquals(1, graph.getNodes(ReturnNode.class).count());
-        return graph.getNodes(ReturnNode.class).first().result();
+        assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count());
+        return graph.getNodes(ReturnNode.TYPE).first().result();
     }
 
     private void processMethod(final String snippet) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Mon Mar 02 19:11:22 2015 +0100
@@ -47,7 +47,6 @@
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.VerifyPhase.VerificationError;
-import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.phases.verify.*;
@@ -199,7 +198,6 @@
      * Checks the invariants for a single graph.
      */
     private static void checkGraph(HighTierContext context, StructuredGraph graph, boolean verifyEquals) {
-        InferStamps.inferStamps(graph);
         if (verifyEquals) {
             new VerifyUsageWithEquals(Value.class).apply(graph, context);
             new VerifyUsageWithEquals(Register.class).apply(graph, context);
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -131,8 +131,8 @@
         result = getResult(getCanonicalizedGraph("integerTestCanonicalization2"));
         assertTrue(result.isConstant() && result.asJavaConstant().asLong() == 1);
         StructuredGraph graph = getCanonicalizedGraph("integerTestCanonicalization3");
-        assertDeepEquals(1, graph.getNodes(ReturnNode.class).count());
-        assertTrue(graph.getNodes(ReturnNode.class).first().result() instanceof ConditionalNode);
+        assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count());
+        assertTrue(graph.getNodes(ReturnNode.TYPE).first().result() instanceof ConditionalNode);
     }
 
     public static int integerTestCanonicalization1(boolean b) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -294,8 +294,8 @@
 
     protected void assertConstantReturn(StructuredGraph graph, int value) {
         String graphString = getCanonicalGraphString(graph, false, true);
-        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1);
-        ValueNode result = graph.getNodes(ReturnNode.class).first().result();
+        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.TYPE).count(), 1);
+        ValueNode result = graph.getNodes(ReturnNode.TYPE).first().result();
         Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant());
         Assert.assertEquals("unexpected ReturnNode result kind: " + graphString, result.asJavaConstant().getKind(), Kind.Int);
         Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asJavaConstant().asInt(), value);
@@ -801,8 +801,9 @@
         PhaseSuite suite = getDefaultGraphBuilderSuite().copy();
         ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class);
         GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous();
+        GraphBuilderConfiguration gbConfCopy = gbConf.copy().copyPluginsFrom(graphBuilderPhase.getGraphBuilderConfig());
         iterator.remove();
-        iterator.add(new GraphBuilderPhase(gbConf, graphBuilderPhase.getGraphBuilderPlugins()));
+        iterator.add(new GraphBuilderPhase(gbConfCopy));
         return suite;
     }
 
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -194,7 +194,7 @@
 
     private void test(String snippet) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
-        ParameterNode param = graph.getNodes(ParameterNode.class).iterator().next();
+        ParameterNode param = graph.getNodes(ParameterNode.TYPE).iterator().next();
         ConstantNode constant = ConstantNode.forInt(0, graph);
         for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) {
             n.replaceFirstInput(param, constant);
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -115,7 +115,7 @@
     private StructuredGraph getCanonicalizedGraph(String snippet) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
         new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders()));
-        for (FrameState state : graph.getNodes(FrameState.class).snapshot()) {
+        for (FrameState state : graph.getNodes(FrameState.TYPE).snapshot()) {
             state.replaceAtUsages(null);
             state.safeDelete();
         }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LongNodeChainTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LongNodeChainTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.schedule.SchedulePhase.SchedulingStrategy;
+import com.oracle.graal.phases.tiers.*;
+
+public class LongNodeChainTest extends GraalCompilerTest {
+
+    public static final int N = 100000;
+
+    @Ignore
+    @Test
+    public void testLongAddChain() {
+        longAddChain(true);
+        longAddChain(false);
+    }
+
+    private void longAddChain(boolean reverse) {
+        HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO);
+        ValueNode constant = graph.unique(ConstantNode.forPrimitive(JavaConstant.INT_1));
+        ValueNode value = null;
+        if (reverse) {
+            AddNode addNode = graph.unique(new AddNode(constant, constant));
+            value = addNode;
+            for (int i = 1; i < N; ++i) {
+                AddNode newAddNode = graph.addWithoutUnique(new AddNode(constant, constant));
+                addNode.setY(newAddNode);
+                addNode = newAddNode;
+            }
+        } else {
+            value = constant;
+            for (int i = 0; i < N; ++i) {
+                value = graph.unique(new AddNode(constant, value));
+            }
+        }
+        ReturnNode returnNode = graph.add(new ReturnNode(value));
+        graph.start().setNext(returnNode);
+
+        for (SchedulingStrategy s : SchedulingStrategy.values()) {
+            new SchedulePhase(s).apply(graph);
+        }
+
+        new CanonicalizerPhase(false).apply(graph, context);
+        JavaConstant asConstant = (JavaConstant) returnNode.result().asConstant();
+        Assert.assertEquals(N + 1, asConstant.asInt());
+    }
+}
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -264,8 +264,8 @@
     public void testArrayCopy() {
         SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES);
         StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph();
-        assertDeepEquals(1, graph.getNodes(ReturnNode.class).count());
-        ReturnNode ret = graph.getNodes(ReturnNode.class).first();
+        assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count());
+        ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first();
         assertTrue(ret.result() + " should be a FloatingReadNode", ret.result() instanceof FloatingReadNode);
         assertDeepEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result()));
         assertReadWithinAllReturnBlocks(schedule, true);
@@ -543,11 +543,11 @@
 
     private void assertReadWithinAllReturnBlocks(SchedulePhase schedule, boolean withinReturnBlock) {
         StructuredGraph graph = schedule.getCFG().graph;
-        assertTrue(graph.getNodes(ReturnNode.class).isNotEmpty());
+        assertTrue(graph.getNodes(ReturnNode.TYPE).isNotEmpty());
 
         int withRead = 0;
         int returnBlocks = 0;
-        for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) {
+        for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) {
             Block block = schedule.getCFG().getNodeToBlock().get(returnNode);
             for (Node node : schedule.getBlockToNodesMap().get(block)) {
                 if (node instanceof FloatingReadNode) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -61,6 +61,6 @@
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
         Debug.dump(graph, "Graph");
-        assertDeepEquals(returnCount, graph.getNodes(ReturnNode.class).count());
+        assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count());
     }
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -69,7 +69,7 @@
     @Test
     public void test2() {
         StructuredGraph graph = parseAndProcess("test2Snippet");
-        NodeIterable monitors = graph.getNodes(MonitorExitNode.class);
+        NodeIterable monitors = graph.getNodes(MonitorExitNode.TYPE);
         Assert.assertEquals(1, monitors.count());
         Assert.assertEquals(monitors.first().stateAfter().bci, 3);
     }
@@ -85,7 +85,7 @@
 
     private StructuredGraph parseAndProcess(String snippet) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
-        ParameterNode param = graph.getNodes(ParameterNode.class).first();
+        ParameterNode param = graph.getNodes(ParameterNode.TYPE).first();
         if (param != null) {
             ConstantNode constant = ConstantNode.forInt(0, graph);
             for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -137,7 +137,7 @@
     }
 
     private static Invoke getInvoke(String name, StructuredGraph graph) {
-        for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) {
+        for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) {
             if (callTarget.targetMethod().getName().equals(name)) {
                 return callTarget.invoke();
             }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodePosIteratorTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodePosIteratorTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodePosIteratorTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -33,6 +33,7 @@
 
     @NodeInfo
     static final class TestNode extends Node {
+        public static final NodeClass TYPE = NodeClass.create(TestNode.class);
         @Successor Node s1;
         @Successor Node s2;
         @Successor NodeSuccessorList stail;
@@ -42,6 +43,7 @@
         @Input FloatingNode i2;
 
         public TestNode() {
+            super(TYPE);
         }
 
     }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -59,7 +59,7 @@
     private void test(String snippet, String reference) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
         Debug.dump(graph, "Graph");
-        for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) {
+        for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) {
             fs.replaceAtUsages(null);
             GraphUtil.killWithUnusedFloatingInputs(fs);
         }
@@ -67,7 +67,7 @@
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
 
         StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES);
-        for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) {
+        for (FrameState fs : referenceGraph.getNodes(FrameState.TYPE).snapshot()) {
             fs.replaceAtUsages(null);
             GraphUtil.killWithUnusedFloatingInputs(fs);
         }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -91,7 +91,7 @@
 
             Debug.dump(graph, "After lowering");
 
-            for (FloatingReadNode node : graph.getNodes(ParameterNode.class).first().usages().filter(FloatingReadNode.class)) {
+            for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) {
                 // Checking that the parameter a is not directly used for the access to field
                 // x10 (because x10 must be guarded by the checkcast).
                 Assert.assertTrue(node.location().getLocationIdentity().isImmutable());
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -66,7 +66,7 @@
         for (BinaryArithmeticNode node : graph.getNodes().filter(BinaryArithmeticNode.class)) {
             if (!(node instanceof AddNode)) {
                 assertTrue(nodeToBlock.get(node) == nodeToBlock.get(loopExit));
-                assertTrue(list.indexOf(node) < list.indexOf(loopExit));
+                assertTrue(list.indexOf(node) + " < " + list.indexOf(loopExit) + ", " + node + ", " + loopExit, list.indexOf(node) < list.indexOf(loopExit));
             }
         }
     }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -43,8 +43,8 @@
     public void testImplies() {
         StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES);
 
-        AbstractEndNode trueEnd = graph.add(new EndNode());
-        AbstractEndNode falseEnd = graph.add(new EndNode());
+        EndNode trueEnd = graph.add(new EndNode());
+        EndNode falseEnd = graph.add(new EndNode());
 
         AbstractBeginNode trueBegin = graph.add(new BeginNode());
         trueBegin.setNext(trueEnd);
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -64,7 +64,7 @@
         public RegisterStats(LIR lir) {
             this.lir = lir;
 
-            for (AbstractBlock block : lir.codeEmittingOrder()) {
+            for (AbstractBlockBase block : lir.codeEmittingOrder()) {
                 for (LIRInstruction instr : lir.getLIRforBlock(block)) {
                     collectStats(instr);
                 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Mon Mar 02 19:11:22 2015 +0100
@@ -158,7 +158,7 @@
             new DeadCodeEliminationPhase().apply(graph);
             new CanonicalizerPhase(true).apply(graph, context);
             new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true), null).apply(graph, context);
-            returnNodes = graph.getNodes(ReturnNode.class).snapshot();
+            returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot();
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -79,8 +79,8 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertDeepEquals(1, graph.getNodes(ReturnNode.class).count());
-        return graph.getNodes(ReturnNode.class).first();
+        assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count());
+        return graph.getNodes(ReturnNode.TYPE).first();
     }
 
     private void processMethod(final String snippet) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -199,7 +199,7 @@
     public void testPhi() {
         processMethod("testPhiSnippet");
         assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
-        List returnNodes = graph.getNodes(ReturnNode.class).snapshot();
+        List returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot();
         assertDeepEquals(2, returnNodes.size());
         assertTrue(returnNodes.get(0).predecessor() instanceof StoreFieldNode);
         assertTrue(returnNodes.get(1).predecessor() instanceof StoreFieldNode);
@@ -239,8 +239,8 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertDeepEquals(1, graph.getNodes(ReturnNode.class).count());
-        return graph.getNodes(ReturnNode.class).first();
+        assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count());
+        return graph.getNodes(ReturnNode.TYPE).first();
     }
 
     protected void processMethod(final String snippet) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -177,7 +177,7 @@
     @SafeVarargs
     protected final void testPartialEscapeAnalysis(final String snippet, double expectedProbability, int expectedCount, Class... invalidNodeClasses) {
         prepareGraph(snippet, false);
-        for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class)) {
+        for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.TYPE)) {
             merge.setStateAfter(null);
         }
         new DeadCodeEliminationPhase().apply(graph);
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -66,7 +66,7 @@
             new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
 
             // remove framestates in order to trigger the simplification.
-            cleanup: for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) {
+            cleanup: for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) {
                 for (Node input : fs.inputs()) {
                     if (input instanceof NewInstanceNode) {
                         fs.replaceAtUsages(null);
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Mar 02 19:11:22 2015 +0100
@@ -44,9 +44,9 @@
 import com.oracle.graal.lir.framemap.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.phases.*;
-import com.oracle.graal.lir.phases.LIRHighTierPhase.LIRHighTierContext;
-import com.oracle.graal.lir.phases.LIRLowTierPhase.LIRLowTierContext;
-import com.oracle.graal.lir.phases.LIRMidTierPhase.LIRMidTierContext;
+import com.oracle.graal.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
+import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
+import com.oracle.graal.lir.phases.AllocationPhase.AllocationContext;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
@@ -340,7 +340,7 @@
                 throw Debug.handle(e);
             }
 
-            try (Scope s = Debug.scope("LIRTier", nodeLirGen)) {
+            try (Scope s = Debug.scope("LIRStages", nodeLirGen)) {
                 return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lirSuites);
             } catch (Throwable e) {
                 throw Debug.handle(e);
@@ -350,16 +350,16 @@
         }
     }
 
-    public static > LIRGenerationResult emitLowLevel(TargetDescription target, List codeEmittingOrder, List linearScanOrder, LIRGenerationResult lirGenRes,
+    public static > LIRGenerationResult emitLowLevel(TargetDescription target, List codeEmittingOrder, List linearScanOrder, LIRGenerationResult lirGenRes,
                     LIRGeneratorTool lirGen, LIRSuites lirSuites) {
-        LIRHighTierContext highTierContext = new LIRHighTierContext(lirGen);
-        lirSuites.getHighTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, highTierContext);
+        PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
+        lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, preAllocOptContext);
 
-        LIRMidTierContext midTierContext = new LIRMidTierContext();
-        lirSuites.getMidTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, midTierContext);
+        AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory());
+        lirSuites.getAllocationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, allocContext);
 
-        LIRLowTierContext lowTierContext = new LIRLowTierContext();
-        lirSuites.getLowTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, lowTierContext);
+        PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext();
+        lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, postAllocOptContext);
 
         return lirGenRes;
     }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 02 19:11:22 2015 +0100
@@ -98,7 +98,9 @@
                                 }
                             }
                             if (pos != vobj.entryCount()) {
-                                values = Arrays.copyOf(values, pos);
+                                JavaValue[] newValues = new JavaValue[pos];
+                                System.arraycopy(values, 0, newValues, 0, pos);
+                                values = newValues;
                             }
                         }
                         entry.getValue().setValues(values);
@@ -111,6 +113,7 @@
         }
         objectStates.clear();
 
+        assert frame.validateFormat();
         return newLIRFrameState(exceptionEdge, frame, virtualObjectsArray);
     }
 
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java	Mon Mar 02 19:11:22 2015 +0100
@@ -71,7 +71,7 @@
         /**
          * Prints this column's label to a given stream after padding the stream with '_' characters
          * until its {@linkplain LogStream#position() position} is equal to this column's position.
-         * 
+         *
          * @param out the print stream
          */
         public void printLabel(LogStream out) {
@@ -82,7 +82,7 @@
         /**
          * Prints space characters to a given stream until its {@linkplain LogStream#position()
          * position} is equal to this column's position.
-         * 
+         *
          * @param out the print stream
          */
         public void advance(LogStream out) {
@@ -116,7 +116,7 @@
     /**
      * Prints an instruction listing on one line. The instruction listing is composed of the columns
      * specified by {@link InstructionLineColumn}.
-     * 
+     *
      * @param instruction the instruction to print
      */
     public void printInstructionListing(ValueNode instruction) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Mar 02 19:11:22 2015 +0100
@@ -329,7 +329,7 @@
 
         gen.emitIncomingValues(params);
 
-        for (ParameterNode param : graph.getNodes(ParameterNode.class)) {
+        for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
             Value paramValue = params[param.index()];
             assert paramValue.getLIRKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp()));
             setResult(param, gen.emitMove(paramValue));
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Mon Mar 02 19:11:22 2015 +0100
@@ -455,7 +455,7 @@
         }
 
         String generatePositionDeclaration() {
-            return String.format("Position[] %s_positions = MatchRuleRegistry.findPositions(lookup, %s.class, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass,
+            return String.format("Position[] %s_positions = MatchRuleRegistry.findPositions(%s.TYPE, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass,
                             String.join("\", \"", nodeType.inputs));
         }
     }
@@ -535,7 +535,7 @@
             out.println("    }");
             out.println();
             out.println("    @Override");
-            out.println("    public List<" + desc + "> statements(MatchRuleRegistry.NodeClassLookup lookup) {");
+            out.println("    public List<" + desc + "> statements() {");
             out.println("        // Checkstyle: stop ");
 
             for (String positionDeclaration : info.positionDeclarations) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java	Mon Mar 02 19:11:22 2015 +0100
@@ -23,8 +23,6 @@
 package com.oracle.graal.compiler.match;
 
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
-import static com.oracle.graal.graph.Edges.Type.*;
-
 import java.util.*;
 import java.util.Map.Entry;
 
@@ -39,41 +37,25 @@
 public class MatchRuleRegistry {
 
     /**
-     * Helper interface for mapping between Class and NodeClass. In static compilation environments,
-     * the current NodeClass might not be the same NodeClass used in the target so this provides a
-     * level of indirection.
-     */
-    public interface NodeClassLookup {
-        NodeClass get(Class theClass);
-    }
-
-    static class DefaultNodeClassLookup implements NodeClassLookup {
-        public NodeClass get(Class theClass) {
-            return NodeClass.get(theClass);
-        }
-    }
-
-    /**
      * Convert a list of field names into {@link com.oracle.graal.graph.Position} objects that can
      * be used to read them during a match. The names should already have been confirmed to exist in
      * the type.
      *
-     * @param theClass
+     * @param nodeClass
      * @param names
      * @return an array of Position objects corresponding to the named fields.
      */
-    public static Position[] findPositions(NodeClassLookup lookup, Class theClass, String[] names) {
+    public static Position[] findPositions(NodeClass nodeClass, String[] names) {
         Position[] result = new Position[names.length];
-        NodeClass nodeClass = lookup.get(theClass);
         for (int i = 0; i < names.length; i++) {
-            Edges edges = nodeClass.getEdges(Inputs);
+            Edges edges = nodeClass.getInputEdges();
             for (int e = 0; e < edges.getDirectCount(); e++) {
                 if (names[i].equals(edges.getName(e))) {
                     result[i] = new Position(edges, e, Node.NOT_ITERABLE);
                 }
             }
             if (result[i] == null) {
-                throw new GraalInternalError("unknown field \"%s\" in class %s", names[i], theClass);
+                throw new GraalInternalError("unknown field \"%s\" in class %s", names[i], nodeClass);
             }
         }
         return result;
@@ -91,8 +73,7 @@
         Map, List> result = registry.get(theClass);
 
         if (result == null) {
-            NodeClassLookup lookup = new DefaultNodeClassLookup();
-            Map, List> rules = createRules(theClass, lookup);
+            Map, List> rules = createRules(theClass);
             registry.put(theClass, rules);
             assert registry.get(theClass) == rules;
             result = rules;
@@ -120,7 +101,7 @@
      * This is a separate, public method so that external clients can create rules with a custom
      * lookup and without the default caching behavior.
      */
-    public static Map, List> createRules(Class theClass, NodeClassLookup lookup) {
+    public static Map, List> createRules(Class theClass) {
         HashMap, MatchStatementSet> matchSets = new HashMap<>();
         Iterable sl = Services.load(MatchStatementSet.class);
         for (MatchStatementSet rules : sl) {
@@ -134,7 +115,7 @@
         do {
             MatchStatementSet matchSet = matchSets.get(currentClass);
             if (matchSet != null) {
-                List statements = matchSet.statements(lookup);
+                List statements = matchSet.statements();
                 for (MatchStatement statement : statements) {
                     Class nodeClass = statement.getPattern().nodeClass();
                     List current = rules.get(nodeClass);
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java	Mon Mar 02 19:11:22 2015 +0100
@@ -37,5 +37,5 @@
     /**
      * @return the {@link MatchStatement}s available for this {@link NodeLIRBuilder} subclass.
      */
-    List statements(MatchRuleRegistry.NodeClassLookup lookup);
+    List statements();
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java	Mon Mar 02 19:11:22 2015 +0100
@@ -24,9 +24,9 @@
 
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.lir.phases.*;
-import com.oracle.graal.lir.phases.LIRHighTierPhase.*;
-import com.oracle.graal.lir.phases.LIRLowTierPhase.*;
-import com.oracle.graal.lir.phases.LIRMidTierPhase.*;
+import com.oracle.graal.lir.phases.PreAllocationOptimizationPhase.*;
+import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.*;
+import com.oracle.graal.lir.phases.AllocationPhase.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -45,16 +45,16 @@
         return new LowTier();
     }
 
-    public LIRPhaseSuite createLIRHighTier() {
-        return new LIRHighTier();
+    public LIRPhaseSuite createPreAllocationOptimizationStage() {
+        return new PreAllocationOptimizationStage();
     }
 
-    public LIRPhaseSuite createLIRMidTier() {
-        return new LIRMidTier();
+    public LIRPhaseSuite createAllocationStage() {
+        return new AllocationStage();
     }
 
-    public LIRPhaseSuite createLIRLowTier() {
-        return new LIRLowTier();
+    public LIRPhaseSuite createPostAllocationOptimizationStage() {
+        return new PostAllocationOptimizationStage();
     }
 
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/GraphChangeMonitoringPhase.java
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/GraphChangeMonitoringPhase.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/GraphChangeMonitoringPhase.java	Mon Mar 02 19:11:22 2015 +0100
@@ -22,12 +22,14 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import java.util.*;
 import java.util.stream.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.Graph.NodeEvent;
 import com.oracle.graal.graph.Graph.NodeEventScope;
+import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.util.*;
@@ -72,7 +74,11 @@
                 Debug.handle(t);
             }
         }
-        if (!listener.getNodes().isEmpty()) {
+        /*
+         * Ignore LogicConstantNode since those are sometimes created and deleted as part of running
+         * a phase.
+         */
+        if (listener.getNodes().stream().filter(e -> !(e instanceof LogicConstantNode)).findFirst().get() != null) {
             /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */
             listener = new HashSetNodeEventListener();
             try (NodeEventScope s = graph.trackNodeEvents(listener)) {
@@ -81,10 +87,11 @@
                         Debug.dump(BasePhase.PHASE_DUMP_LEVEL, graph, "*** Before phase %s", getName());
                     }
                     super.run(graph, context);
+                    Set collect = listener.getNodes().stream().filter(e -> !e.isAlive()).filter(e -> !(e instanceof LogicConstantNode)).collect(Collectors.toSet());
                     if (Debug.isDumpEnabled(BasePhase.PHASE_DUMP_LEVEL)) {
-                        Debug.dump(BasePhase.PHASE_DUMP_LEVEL, graph, "*** After phase %s", getName());
+                        Debug.dump(BasePhase.PHASE_DUMP_LEVEL, graph, "*** After phase %s %s", getName(), collect);
                     }
-                    Debug.log("*** %s %s %s\n", message, graph, listener.getNodes().stream().filter(e -> !e.isAlive()).collect(Collectors.toSet()));
+                    Debug.log("*** %s %s %s\n", message, graph, collect);
                 }
             }
         } else {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfigScope.java
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfigScope.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfigScope.java	Mon Mar 02 19:11:22 2015 +0100
@@ -27,7 +27,7 @@
 /**
  * A utility for scoping a change to the current debug
  * {@linkplain DebugScope#setConfig(DebugConfig) configuration}. For example:
- * 
+ *
  * 
  *     DebugConfig config = ...;
  *     try (DebugConfigScope s = new DebugConfigScope(config)) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.debug/src/com/oracle/graal/debug/LogStream.java
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/LogStream.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/LogStream.java	Mon Mar 02 19:11:22 2015 +0100
@@ -26,20 +26,20 @@
 
 /**
  * A utility for printing compiler debug and informational output to an output stream.
- * 
+ *
  * A {@link LogStream} instance maintains an internal buffer that is flushed to the underlying
  * output stream every time one of the {@code println} methods is invoked, or a newline character (
  * {@code '\n'}) is written.
- * 
+ *
  * All of the {@code print} and {@code println} methods return the {code LogStream} instance on
  * which they were invoked. This allows chaining of these calls to mitigate use of String
  * concatenation by the caller.
- * 
+ *
  * A {@code LogStream} maintains a current {@linkplain #indentationLevel() indentation} level. Each
  * line of output written to this stream has {@code n} spaces prefixed to it where {@code n} is the
  * value that would be returned by {@link #indentationLevel()} when the first character of a new
  * line is written.
- * 
+ *
  * A {@code LogStream} maintains a current {@linkplain #position() position} for the current line
  * being written. This position can be advanced to a specified position by
  * {@linkplain #fillTo(int, char) filling} this stream with a given character.
@@ -87,7 +87,7 @@
 
     /**
      * Creates a new log stream.
-     * 
+     *
      * @param os the underlying output stream to which prints are sent
      */
     public LogStream(OutputStream os) {
@@ -98,7 +98,7 @@
     /**
      * Creates a new log stream that shares the same {@linkplain #ps output stream} as a given
      * {@link LogStream}.
-     * 
+     *
      * @param log a LogStream whose output stream is shared with this one
      */
     public LogStream(LogStream log) {
@@ -147,7 +147,7 @@
 
     /**
      * Gets the current column position of this log stream.
-     * 
+     *
      * @return the current column position of this log stream
      */
     public int position() {
@@ -157,7 +157,7 @@
 
     /**
      * Gets the current indentation level for this log stream.
-     * 
+     *
      * @return the current indentation level for this log stream.
      */
     public int indentationLevel() {
@@ -166,7 +166,7 @@
 
     /**
      * Adjusts the current indentation level of this log stream.
-     * 
+     *
      * @param delta
      */
     public void adjustIndentation(int delta) {
@@ -202,7 +202,7 @@
     /**
      * Advances this stream's {@linkplain #position() position} to a given position by repeatedly
      * appending a given character as necessary.
-     * 
+     *
      * @param position the position to which this stream's position will be advanced
      * @param filler the character used to pad the stream
      */
@@ -218,7 +218,7 @@
 
     /**
      * Writes a boolean value to this stream as {@code "true"} or {@code "false"}.
-     * 
+     *
      * @param b the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -233,7 +233,7 @@
     /**
      * Writes a boolean value to this stream followed by a {@linkplain #LINE_SEPARATOR line
      * separator}.
-     * 
+     *
      * @param b the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -248,7 +248,7 @@
 
     /**
      * Writes a character value to this stream.
-     * 
+     *
      * @param c the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -268,7 +268,7 @@
     /**
      * Writes a character value to this stream followed by a {@linkplain #LINE_SEPARATOR line
      * separator}.
-     * 
+     *
      * @param c the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -283,7 +283,7 @@
 
     /**
      * Prints an int value.
-     * 
+     *
      * @param i the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -297,7 +297,7 @@
 
     /**
      * Writes an int value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
-     * 
+     *
      * @param i the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -312,7 +312,7 @@
 
     /**
      * Writes a float value to this stream.
-     * 
+     *
      * @param f the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -327,7 +327,7 @@
     /**
      * Writes a float value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}
      * .
-     * 
+     *
      * @param f the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -342,7 +342,7 @@
 
     /**
      * Writes a long value to this stream.
-     * 
+     *
      * @param l the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -356,7 +356,7 @@
 
     /**
      * Writes a long value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}.
-     * 
+     *
      * @param l the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -371,7 +371,7 @@
 
     /**
      * Writes a double value to this stream.
-     * 
+     *
      * @param d the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -386,7 +386,7 @@
     /**
      * Writes a double value to this stream followed by a {@linkplain #LINE_SEPARATOR line
      * separator}.
-     * 
+     *
      * @param d the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -403,7 +403,7 @@
      * Writes a {@code String} value to this stream. This method ensures that the
      * {@linkplain #position() position} of this stream is updated correctly with respect to any
      * {@linkplain #LINE_SEPARATOR line separators} present in {@code s}.
-     * 
+     *
      * @param s the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -436,7 +436,7 @@
     /**
      * Writes a {@code String} value to this stream followed by a {@linkplain #LINE_SEPARATOR line
      * separator}.
-     * 
+     *
      * @param s the value to be printed
      * @return this {@link LogStream} instance
      */
@@ -450,7 +450,7 @@
 
     /**
      * Writes a formatted string to this stream.
-     * 
+     *
      * @param format a format string as described in {@link String#format(String, Object...)}
      * @param args the arguments to be formatted
      * @return this {@link LogStream} instance
@@ -464,7 +464,7 @@
 
     /**
      * Writes a {@linkplain #LINE_SEPARATOR line separator} to this stream.
-     * 
+     *
      * @return this {@code LogStream} instance
      */
     public LogStream println() {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTY.java
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTY.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTY.java	Mon Mar 02 19:11:22 2015 +0100
@@ -46,7 +46,7 @@
          * Creates an object that will suppress {@link TTY} for the current thread if the given
          * filter does not match the given object. To revert the suppression state to how it was
          * before this call, the {@link #remove()} method must be called on the suppression object.
-         * 
+         *
          * @param filter the pattern for matching. If {@code null}, then the match is successful. If
          *            it starts with "~", then a regular expression
          *            {@linkplain Pattern#matches(String, CharSequence) match} is performed where
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,10 @@
 
     @NodeInfo
     static final class TestNode extends Node {
+        public static final NodeClass TYPE = NodeClass.create(TestNode.class);
+
         protected TestNode() {
+            super(TYPE);
         }
     }
 
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Mon Mar 02 19:11:22 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,17 +35,22 @@
 
     @NodeInfo
     static final class Def extends Node {
+        public static final NodeClass TYPE = NodeClass.create(Def.class);
+
         protected Def() {
+            super(TYPE);
         }
     }
 
     @NodeInfo
     static final class Use extends Node {
+        public static final NodeClass TYPE = NodeClass.create(Use.class);
         @Input Def in0;
         @Input Def in1;
         @Input Def in2;
 
         public Use(Def in0, Def in1, Def in2) {
+            super(TYPE);
             this.in0 = in0;
             this.in1 = in1;
             this.in2 = in2;
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeValidationChecksTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeValidationChecksTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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.test;
+
+import org.junit.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+
+public class NodeValidationChecksTest {
+
+    @NodeInfo
+    static final class TestNode extends Node {
+        public static final NodeClass TYPE = NodeClass.create(TestNode.class);
+
+        @Input TestNode input;
+        @Successor TestNode successor;
+
+        public TestNode(TestNode input, TestNode successor) {
+            super(TYPE);
+            this.input = input;
+            this.successor = successor;
+        }
+    }
+
+    @Test
+    public void testInputNotAlive() {
+        Graph graph = new Graph();
+        TestNode node = new TestNode(null, null);
+        try {
+            graph.add(new TestNode(node, null));
+            Assert.fail("Exception expected.");
+        } catch (IllegalStateException e) {
+            Assert.assertTrue(e.getMessage().contains("Input"));
+            Assert.assertTrue(e.getMessage().contains("not alive"));
+        }
+    }
+
+    @Test
+    public void testSuccessorNotAlive() {
+        Graph graph = new Graph();
+        TestNode node = new TestNode(null, null);
+        try {
+            graph.add(new TestNode(null, node));
+            Assert.fail("Exception expected.");
+        } catch (IllegalStateException e) {
+            Assert.assertTrue(e.getMessage().contains("Successor"));
+            Assert.assertTrue(e.getMessage().contains("not alive"));
+        }
+    }
+}
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Mon Mar 02 19:11:22 2015 +0100
@@ -34,11 +34,13 @@
 public class TypedNodeIteratorTest {
 
     @NodeInfo
-    static class TestNode extends Node implements IterableNodeType, TestNodeInterface {
+    static final class TestNode extends Node implements IterableNodeType, TestNodeInterface {
 
+        public static final NodeClass TYPE = NodeClass.create(TestNode.class);
         protected final String name;
 
         public TestNode(String name) {
+            super(TYPE);
             this.name = name;
         }
 
@@ -51,8 +53,8 @@
     public void singleNodeTest() {
         Graph graph = new Graph();
         graph.add(new TestNode("a"));
-        assertTrue(graph.hasNode(TestNode.class));
-        assertEquals("a", toString(graph.getNodes(TestNode.class)));
+        assertTrue(graph.hasNode(TestNode.TYPE));
+        assertEquals("a", toString(graph.getNodes(TestNode.TYPE)));
     }
 
     @Test
@@ -61,7 +63,7 @@
         Graph graph = new Graph();
         graph.add(testNode);
         testNode.safeDelete();
-        assertEquals("", toString(graph.getNodes(TestNode.class)));
+        assertEquals("", toString(graph.getNodes(TestNode.TYPE)));
     }
 
     @Test
@@ -71,16 +73,16 @@
         graph.add(new TestNode("a"));
         graph.add(testNode);
         testNode.safeDelete();
-        assertEquals("a", toString(graph.getNodes(TestNode.class)));
+        assertEquals("a", toString(graph.getNodes(TestNode.TYPE)));
         graph.add(new TestNode("c"));
-        assertEquals("ac", toString(graph.getNodes(TestNode.class)));
+        assertEquals("ac", toString(graph.getNodes(TestNode.TYPE)));
     }
 
     @Test
     public void iteratorBehaviorTest() {
         Graph graph = new Graph();
         graph.add(new TestNode("a"));
-        Iterator iterator = graph.getNodes(TestNode.class).iterator();
+        Iterator iterator = graph.getNodes(TestNode.TYPE).iterator();
         assertTrue(iterator.hasNext());
         assertEquals("a", iterator.next().getName());
         assertFalse(iterator.hasNext());
@@ -99,7 +101,7 @@
     public void complicatedIterationTest() {
         Graph graph = new Graph();
         graph.add(new TestNode("a"));
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
+        for (TestNode tn : graph.getNodes(TestNode.TYPE)) {
             String name = tn.getName();
             for (int i = 0; i < name.length(); ++i) {
                 char c = name.charAt(i);
@@ -119,7 +121,7 @@
                     graph.add(new TestNode("e"));
                     graph.add(new TestNode("d"));
                 } else if (c == 'd') {
-                    for (TestNode tn2 : graph.getNodes(TestNode.class)) {
+                    for (TestNode tn2 : graph.getNodes(TestNode.TYPE)) {
                         if (tn2.getName().equals("e")) {
                             tn2.safeDelete();
                         } else if (tn2.getName().equals("c")) {
@@ -131,7 +133,7 @@
                 }
             }
         }
-        assertEquals("dddd", toString(graph.getNodes(TestNode.class)));
+        assertEquals("dddd", toString(graph.getNodes(TestNode.TYPE)));
     }
 
     @Test
@@ -140,7 +142,7 @@
         graph.add(new TestNode("a"));
         StringBuilder sb = new StringBuilder();
         int z = 0;
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
+        for (TestNode tn : graph.getNodes(TestNode.TYPE)) {
             if (z == 0) {
                 graph.add(new TestNode("b"));
             }
@@ -150,7 +152,7 @@
         assertEquals(2, z);
         assertEquals("ab", sb.toString());
         z = 0;
-        for (TestNode tn : graph.getNodes(TestNode.class)) {
+        for (TestNode tn : graph.getNodes(TestNode.TYPE)) {
             if (z == 0) {
                 graph.add(new TestNode("c"));
             }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Mon Mar 02 19:11:22 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,9 +34,15 @@
     @NodeInfo
     static class NodeA extends Node implements TestNodeInterface {
 
+        public static final NodeClass TYPE = NodeClass.create(NodeA.class);
         protected final String name;
 
         public NodeA(String name) {
+            this(TYPE, name);
+        }
+
+        protected NodeA(NodeClass c, String name) {
+            super(c);
             this.name = name;
         }
 
@@ -47,25 +53,38 @@
 
     @NodeInfo
     static class NodeB extends NodeA implements IterableNodeType {
+        public static final NodeClass TYPE = NodeClass.create(NodeB.class);
 
         public NodeB(String name) {
-            super(name);
+            this(TYPE, name);
+        }
+
+        protected NodeB(NodeClass c, String name) {
+            super(c, name);
         }
 
     }
 
     @NodeInfo
     static class NodeC extends NodeB {
+        public static final NodeClass TYPE = NodeClass.create(NodeC.class);
+
         public NodeC(String name) {
-            super(name);
+            this(TYPE, name);
+        }
+
+        protected NodeC(NodeClass c, String name) {
+            super(c, name);
         }
 
     }
 
     @NodeInfo
-    static class NodeD extends NodeC {
+    static final class NodeD extends NodeC {
+        public static final NodeClass TYPE = NodeClass.create(NodeD.class);
+
         public NodeD(String name) {
-            super(name);
+            super(TYPE, name);
         }
 
     }
@@ -76,8 +95,8 @@
         graph.add(new NodeB("b"));
         graph.add(new NodeD("d"));
 
-        Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class)));
-        Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class)));
+        Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.TYPE)));
+        Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.TYPE)));
     }
 
     @Test
@@ -86,21 +105,21 @@
         graph.add(new NodeB("b1"));
         NodeD d1 = graph.add(new NodeD("d1"));
         StringBuilder sb = new StringBuilder();
-        for (NodeB tn : graph.getNodes(NodeB.class)) {
+        for (NodeB tn : graph.getNodes(NodeB.TYPE)) {
             if (tn == d1) {
                 graph.add(new NodeB("b2"));
             }
             sb.append(tn.getName());
         }
         assertEquals("b1d1b2", sb.toString());
-        for (NodeB tn : graph.getNodes(NodeB.class)) {
+        for (NodeB tn : graph.getNodes(NodeB.TYPE)) {
             if (tn == d1) {
                 graph.add(new NodeB("b3"));
             }
             assertNotNull(tn);
         }
-        assertEquals(4, graph.getNodes(NodeB.class).count());
-        assertEquals(1, graph.getNodes(NodeD.class).count());
+        assertEquals(4, graph.getNodes(NodeB.TYPE).count());
+        assertEquals(1, graph.getNodes(NodeD.TYPE).count());
     }
 
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java	Mon Mar 02 19:11:22 2015 +0100
@@ -27,6 +27,7 @@
 import static com.oracle.graal.graph.Node.*;
 
 import java.util.*;
+import java.util.function.*;
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.NodeClass.EdgeInfo;
@@ -60,20 +61,20 @@
         }
     }
 
-    private static Node getNode(Node node, long offset) {
+    private static Node getNodeUnsafe(Node node, long offset) {
         return (Node) unsafe.getObject(node, offset);
     }
 
     @SuppressWarnings("unchecked")
-    private static NodeList getNodeList(Node node, long offset) {
+    private static NodeList getNodeListUnsafe(Node node, long offset) {
         return (NodeList) unsafe.getObject(node, offset);
     }
 
-    private static void putNode(Node node, long offset, Node value) {
+    private static void putNodeUnsafe(Node node, long offset, Node value) {
         unsafe.putObject(node, offset, value);
     }
 
-    private static void putNodeList(Node node, long offset, NodeList value) {
+    private static void putNodeListUnsafe(Node node, long offset, NodeList value) {
         unsafe.putObject(node, offset, value);
     }
 
@@ -92,9 +93,8 @@
      * @param index the index of a non-list the edge (must be less than {@link #getDirectCount()})
      * @return the Node at the other edge of the requested edge
      */
-    public Node getNode(Node node, int index) {
-        assert index >= 0 && index < directCount;
-        return getNode(node, offsets[index]);
+    public static Node getNode(Node node, long[] offsets, int index) {
+        return getNodeUnsafe(node, offsets[index]);
     }
 
     /**
@@ -105,9 +105,8 @@
      *            {@link #getDirectCount()})
      * @return the {@link NodeList} at the other edge of the requested edge
      */
-    public NodeList getNodeList(Node node, int index) {
-        assert index >= directCount && index < getCount();
-        return getNodeList(node, offsets[index]);
+    public static NodeList getNodeList(Node node, long[] offsets, int index) {
+        return getNodeListUnsafe(node, offsets[index]);
     }
 
     /**
@@ -118,18 +117,22 @@
      * @param node the node whose edges are to be cleared
      */
     public void clear(Node node) {
+        final long[] curOffsets = this.offsets;
+        final Type curType = this.type;
         int index = 0;
-        while (index < getDirectCount()) {
-            initializeNode(node, index++, null);
+        int curDirectCount = getDirectCount();
+        while (index < curDirectCount) {
+            initializeNode(node, curOffsets, index++, null);
         }
-        while (index < getCount()) {
-            NodeList list = getNodeList(node, index);
+        int curCount = getCount();
+        while (index < curCount) {
+            NodeList list = getNodeList(node, curOffsets, index);
             if (list != null) {
                 int size = list.initialSize;
-                NodeList newList = type == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size);
+                NodeList newList = curType == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size);
 
                 // replacing with a new list object is the expected behavior!
-                initializeList(node, index, newList);
+                initializeList(node, curOffsets, index, newList);
             }
             index++;
         }
@@ -144,12 +147,14 @@
      */
     public void initializeLists(Node node, Node prototype) {
         int index = getDirectCount();
+        final long[] curOffsets = this.offsets;
+        final Edges.Type curType = this.type;
         while (index < getCount()) {
-            NodeList list = getNodeList(prototype, index);
+            NodeList list = getNodeList(prototype, curOffsets, index);
             if (list != null) {
                 int size = list.initialSize;
-                NodeList newList = type == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size);
-                initializeList(node, index, newList);
+                NodeList newList = curType == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size);
+                initializeList(node, curOffsets, index, newList);
             }
             index++;
         }
@@ -166,16 +171,20 @@
         assert fromNode != toNode;
         assert fromNode.getNodeClass().getClazz() == toNode.getNodeClass().getClazz();
         int index = 0;
-        while (index < getDirectCount()) {
-            initializeNode(toNode, index, getNode(fromNode, index));
+        final long[] curOffsets = this.offsets;
+        final Type curType = this.type;
+        int curDirectCount = getDirectCount();
+        while (index < curDirectCount) {
+            initializeNode(toNode, curOffsets, index, getNode(fromNode, curOffsets, index));
             index++;
         }
-        while (index < getCount()) {
-            NodeList list = getNodeList(toNode, index);
-            NodeList fromList = getNodeList(fromNode, index);
+        int curCount = getCount();
+        while (index < curCount) {
+            NodeList list = getNodeList(toNode, curOffsets, index);
+            NodeList fromList = getNodeList(fromNode, curOffsets, index);
             if (list == null || list == fromList) {
-                list = type == Edges.Type.Inputs ? new NodeInputList<>(toNode, fromList) : new NodeSuccessorList<>(toNode, fromList);
-                initializeList(toNode, index, list);
+                list = curType == Edges.Type.Inputs ? new NodeInputList<>(toNode, fromList) : new NodeSuccessorList<>(toNode, fromList);
+                initializeList(toNode, curOffsets, index, list);
             } else {
                 list.copy(fromList);
             }
@@ -194,17 +203,20 @@
      */
     public boolean replaceFirst(Node node, Node key, Node replacement) {
         int index = 0;
-        while (index < getDirectCount()) {
-            Node edge = getNode(node, index);
+        final long[] curOffsets = this.getOffsets();
+        int curDirectCount = getDirectCount();
+        while (index < curDirectCount) {
+            Node edge = getNode(node, curOffsets, index);
             if (edge == key) {
                 assert replacement == null || getType(index).isAssignableFrom(replacement.getClass()) : "Can not assign " + replacement.getClass() + " to " + getType(index) + " in " + node;
-                initializeNode(node, index, replacement);
+                initializeNode(node, curOffsets, index, replacement);
                 return true;
             }
             index++;
         }
-        while (index < getCount()) {
-            NodeList list = getNodeList(node, index);
+        int curCount = getCount();
+        while (index < curCount) {
+            NodeList list = getNodeList(node, curOffsets, index);
             if (list != null) {
                 if (list.replaceFirst(key, replacement)) {
                     return true;
@@ -228,13 +240,12 @@
      * @param index the index of the edge (between 0 and {@link #getCount()})
      * @param value the node to be written to the edge
      */
-    public void initializeNode(Node node, int index, Node value) {
-        putNode(node, offsets[index], value);
+    public static void initializeNode(Node node, long[] offsets, int index, Node value) {
+        putNodeUnsafe(node, offsets[index], value);
     }
 
-    public void initializeList(Node node, int index, NodeList value) {
-        assert index >= directCount;
-        putNodeList(node, offsets[index], value);
+    public static void initializeList(Node node, long[] offsets, int index, NodeList value) {
+        putNodeListUnsafe(node, offsets[index], value);
     }
 
     /**
@@ -247,21 +258,22 @@
      */
     public void setNode(Node node, int index, Node value) {
         assert index < directCount;
-        Node old = getNode(node, offsets[index]);
-        putNode(node, offsets[index], value);
+        Node old = getNodeUnsafe(node, offsets[index]);
+        putNodeUnsafe(node, offsets[index], value);
         update(node, old, value);
     }
 
     protected abstract void update(Node node, Node oldValue, Node newValue);
 
     public boolean contains(Node node, Node value) {
+        final long[] curOffsets = this.offsets;
         for (int i = 0; i < directCount; i++) {
-            if (getNode(node, i) == value) {
+            if (getNode(node, curOffsets, i) == value) {
                 return true;
             }
         }
         for (int i = directCount; i < getCount(); i++) {
-            NodeList curList = getNodeList(node, i);
+            NodeList curList = getNodeList(node, curOffsets, i);
             if (curList != null && curList.contains(value)) {
                 return true;
             }
@@ -275,15 +287,16 @@
     public boolean areEqualIn(Node node, Node other) {
         assert node.getNodeClass().getClazz() == other.getNodeClass().getClazz();
         int index = 0;
+        final long[] curOffsets = this.offsets;
         while (index < directCount) {
-            if (getNode(other, index) != getNode(node, index)) {
+            if (getNode(other, curOffsets, index) != getNode(node, curOffsets, index)) {
                 return false;
             }
             index++;
         }
         while (index < getCount()) {
-            NodeList list = getNodeList(other, index);
-            if (!Objects.equals(list, getNodeList(node, index))) {
+            NodeList list = getNodeList(other, curOffsets, index);
+            if (!Objects.equals(list, getNodeList(node, curOffsets, index))) {
                 return false;
             }
             index++;
@@ -305,6 +318,9 @@
         NodeList list;
         protected boolean needsForward;
         protected Node nextElement;
+        protected final int directCount;
+        protected final int count;
+        protected final long[] offsets;
 
         /**
          * Creates an iterator that will iterate over some given edges in a given node.
@@ -315,14 +331,17 @@
             index = NOT_ITERABLE;
             subIndex = 0;
             needsForward = true;
+            this.directCount = edges.getDirectCount();
+            this.offsets = edges.getOffsets();
+            this.count = edges.getCount();
         }
 
         void forward() {
             needsForward = false;
-            if (index < edges.getDirectCount()) {
+            if (index < directCount) {
                 index++;
-                while (index < edges.getDirectCount()) {
-                    nextElement = edges.getNode(node, index);
+                while (index < directCount) {
+                    nextElement = Edges.getNode(node, offsets, index);
                     if (nextElement != null) {
                         return;
                     }
@@ -339,7 +358,7 @@
         private void forwardNodeList() {
             do {
                 if (subIndex == 0) {
-                    list = edges.getNodeList(node, index);
+                    list = Edges.getNodeList(node, offsets, index);
                 }
                 if (list != null) {
                     while (subIndex < list.size()) {
@@ -360,7 +379,7 @@
                 forward();
             }
             needsForward = true;
-            if (index < edges.getCount()) {
+            if (index < count) {
                 return nextElement;
             }
             throw new NoSuchElementException();
@@ -384,7 +403,7 @@
                 forward();
             }
             needsForward = true;
-            if (index < edges.getDirectCount()) {
+            if (index < directCount) {
                 return new Position(edges, index, NOT_ITERABLE);
             } else {
                 return new Position(edges, index, subIndex);
@@ -398,6 +417,7 @@
     }
 
     private static class AllEdgesIterator extends EdgesIterator {
+
         AllEdgesIterator(Node node, Edges edges) {
             super(node, edges);
         }
@@ -405,10 +425,10 @@
         @Override
         void forward() {
             needsForward = false;
-            if (index < edges.getDirectCount()) {
+            if (index < directCount) {
                 index++;
                 if (index < edges.getDirectCount()) {
-                    nextElement = edges.getNode(node, index);
+                    nextElement = Edges.getNode(node, edges.getOffsets(), index);
                     return;
                 }
             } else {
@@ -416,7 +436,7 @@
             }
             while (index < edges.getCount()) {
                 if (subIndex == 0) {
-                    list = edges.getNodeList(node, index);
+                    list = Edges.getNodeList(node, edges.getOffsets(), index);
                 }
                 if (list != null) {
                     if (subIndex < list.size()) {
@@ -467,6 +487,9 @@
         }
     }
 
+    static int cnt1;
+    static int cnt2;
+
     public NodeClassIterable getIterable(final Node node) {
         return new NodeClassIterable() {
 
@@ -493,4 +516,34 @@
     public Type type() {
         return type;
     }
+
+    public void accept(Node node, BiConsumer consumer) {
+        int index = 0;
+        int curDirectCount = this.directCount;
+        final long[] curOffsets = this.offsets;
+        while (index < curDirectCount) {
+            Node curNode = getNode(node, curOffsets, index);
+            if (curNode != null) {
+                consumer.accept(node, curNode);
+            }
+            index++;
+        }
+        int count = getCount();
+        while (index < count) {
+            NodeList list = getNodeList(node, curOffsets, index);
+            if (list != null) {
+                for (int i = 0; i < list.size(); ++i) {
+                    Node curNode = list.get(i);
+                    if (curNode != null) {
+                        consumer.accept(node, curNode);
+                    }
+                }
+            }
+            index++;
+        }
+    }
+
+    public long[] getOffsets() {
+        return this.offsets;
+    }
 }
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Mar 02 19:11:22 2015 +0100
@@ -452,18 +452,17 @@
         return uniqueHelper(node, true);
     }
 
-    @SuppressWarnings("unchecked")
      T uniqueHelper(T node, boolean addIfMissing) {
         assert node.getNodeClass().valueNumberable();
-        Node other = this.findDuplicate(node);
+        T other = this.findDuplicate(node);
         if (other != null) {
-            return (T) other;
+            return other;
         } else {
-            Node result = addIfMissing ? addHelper(node) : node;
+            T result = addIfMissing ? addHelper(node) : node;
             if (node.getNodeClass().isLeafNode()) {
                 putNodeIntoCache(result);
             }
-            return (T) result;
+            return result;
         }
     }
 
@@ -484,41 +483,45 @@
         return result;
     }
 
-    public Node findDuplicate(Node node) {
-        NodeClass nodeClass = node.getNodeClass();
+    @SuppressWarnings("unchecked")
+    public  T findDuplicate(T node) {
+        NodeClass nodeClass = node.getNodeClass();
         assert nodeClass.valueNumberable();
         if (nodeClass.isLeafNode()) {
             // Leaf node: look up in cache
             Node cachedNode = findNodeInCache(node);
             if (cachedNode != null) {
-                return cachedNode;
+                return (T) cachedNode;
             } else {
                 return null;
             }
         } else {
-            // Non-leaf node: look for another usage of the node's inputs that
-            // has the same data, inputs and successors as the node. To reduce
-            // the cost of this computation, only the input with estimated highest
-            // usage count is considered.
-
+            /*
+             * Non-leaf node: look for another usage of the node's inputs that has the same data,
+             * inputs and successors as the node. To reduce the cost of this computation, only the
+             * input with lowest usage count is considered. If this node is the only user of any
+             * input then the search can terminate early. The usage count is only incremented once
+             * the Node is in the Graph, so account for that in the test.
+             */
+            final int earlyExitUsageCount = node.graph() != null ? 1 : 0;
             int minCount = Integer.MAX_VALUE;
             Node minCountNode = null;
             for (Node input : node.inputs()) {
                 if (input != null) {
-                    int estimate = input.getUsageCount();
-                    if (estimate == 0) {
+                    int usageCount = input.getUsageCount();
+                    if (usageCount == earlyExitUsageCount) {
                         return null;
-                    } else if (estimate < minCount) {
-                        minCount = estimate;
+                    } else if (usageCount < minCount) {
+                        minCount = usageCount;
                         minCountNode = input;
                     }
                 }
             }
             if (minCountNode != null) {
                 for (Node usage : minCountNode.usages()) {
-                    if (usage != node && nodeClass == usage.getNodeClass() && node.valueEquals(usage) && nodeClass.getEdges(Inputs).areEqualIn(node, usage) &&
+                    if (usage != node && nodeClass == usage.getNodeClass() && node.valueEquals(usage) && nodeClass.getInputEdges().areEqualIn(node, usage) &&
                                     nodeClass.getEdges(Successors).areEqualIn(node, usage)) {
-                        return usage;
+                        return (T) usage;
                     }
                 }
                 return null;
@@ -625,7 +628,11 @@
     // Fully qualified annotation name is required to satisfy javac
     @com.oracle.graal.nodeinfo.NodeInfo
     static final class PlaceHolderNode extends Node {
+
+        public static final NodeClass TYPE = NodeClass.create(PlaceHolderNode.class);
+
         public PlaceHolderNode() {
+            super(TYPE);
         }
 
     }
@@ -685,11 +692,10 @@
      * Returns an {@link Iterable} providing all the live nodes whose type is compatible with
      * {@code type}.
      *
-     * @param type the type of node to return
+     * @param nodeClass the type of node to return
      * @return an {@link Iterable} providing all the matching nodes
      */
-    public  NodeIterable getNodes(final Class type) {
-        final NodeClass nodeClass = NodeClass.get(type);
+    public  NodeIterable getNodes(final NodeClass nodeClass) {
         return new NodeIterable() {
 
             @Override
@@ -705,7 +711,7 @@
      * @param type the type of node that is checked for occurrence
      * @return whether there is at least one such node
      */
-    public  boolean hasNode(final Class type) {
+    public  boolean hasNode(final NodeClass type) {
         return getNodes(type).iterator().hasNext();
     }
 
@@ -738,7 +744,9 @@
         assert !isFrozen();
         assert node.id() == Node.INITIAL_ID;
         if (nodes.length == nodesSize) {
-            nodes = Arrays.copyOf(nodes, (nodesSize * 2) + 1);
+            Node[] newNodes = new Node[(nodesSize * 2) + 1];
+            System.arraycopy(nodes, 0, newNodes, 0, nodesSize);
+            nodes = newNodes;
         }
         int id = nodesSize;
         nodes[id] = node;
@@ -761,8 +769,9 @@
     }
 
     /**
-     * Rebuilds the lists used to support {@link #getNodes(Class)}. This is useful for serialization
-     * where the underlying {@linkplain NodeClass#iterableId() iterable ids} may have changed.
+     * Rebuilds the lists used to support {@link #getNodes(NodeClass)}. This is useful for
+     * serialization where the underlying {@linkplain NodeClass#iterableId() iterable ids} may have
+     * changed.
      */
     private void recomputeIterableNodeLists() {
         iterableNodesFirst.clear();
@@ -819,8 +828,8 @@
         return true;
     }
 
-    Node getNode(int i) {
-        return nodes[i];
+    public Node getNode(int id) {
+        return nodes[id];
     }
 
     /**
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java	Mon Mar 02 19:11:22 2015 +0100
@@ -23,7 +23,7 @@
 package com.oracle.graal.graph;
 
 /**
- * A marker for a node type supporting {@linkplain Graph#getNodes(Class) fast iteration} of its
+ * A marker for a node type supporting {@linkplain Graph#getNodes(NodeClass) fast iteration} of its
  * instances in a graph. The support for fast iteration comes with a memory cost (e.g., extra data
  * structures {@link Graph}) so only node types for which fast iteration provides a compilation
  * performance benefit should implement this interface.
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Mar 02 19:11:22 2015 +0100
@@ -27,6 +27,7 @@
 
 import java.lang.annotation.*;
 import java.util.*;
+import java.util.function.*;
 
 import sun.misc.*;
 
@@ -76,6 +77,7 @@
 @NodeInfo
 public abstract class Node implements Cloneable, Formattable {
 
+    public static final NodeClass TYPE = null;
     public static final boolean USE_UNSAFE_TO_CLONE = Boolean.parseBoolean(System.getProperty("graal.node.useUnsafeToClone", "true"));
 
     static final int DELETED_ID_START = -1000000000;
@@ -160,6 +162,14 @@
          * ignored and can therefore safely be {@code null}.
          */
         boolean setStampFromReturnType() default false;
+
+        /**
+         * Determines if this intrinsic can be compile-time executed. An attempt to execute a call
+         * (via reflection) to this intrinsic at compile-time will be made if all of its arguments
+         * are compile-time constant. If the execution succeeds without an exception, the result is
+         * inserted as a constant node in the graph.
+         */
+        boolean foldable() default false;
     }
 
     /**
@@ -193,14 +203,15 @@
     int extraUsagesCount;
 
     private Node predecessor;
-    private NodeClass nodeClass;
+    private NodeClass nodeClass;
 
     public static final int NODE_LIST = -2;
     public static final int NOT_ITERABLE = -1;
 
-    public Node() {
+    public Node(NodeClass c) {
         init();
-        this.nodeClass = NodeClass.get(this.getClass());
+        assert c.getJavaClass() == this.getClass();
+        this.nodeClass = c;
     }
 
     final void init() {
@@ -276,7 +287,16 @@
      * @return an {@link NodeClassIterable iterable} for all non-null input edges.
      */
     public NodeClassIterable inputs() {
-        return getNodeClass().getEdges(Inputs).getIterable(this);
+        return nodeClass.getInputEdges().getIterable(this);
+    }
+
+    /**
+     * Applies the given consumer to all inputs of this node.
+     *
+     * @param consumer the consumer to be applied to the inputs
+     */
+    public void acceptInputs(BiConsumer consumer) {
+        nodeClass.getInputEdges().accept(this, consumer);
     }
 
     /**
@@ -286,7 +306,16 @@
      * @return an {@link NodeClassIterable iterable} for all non-null successor edges.
      */
     public NodeClassIterable successors() {
-        return getNodeClass().getEdges(Successors).getIterable(this);
+        return nodeClass.getSuccessorEdges().getIterable(this);
+    }
+
+    /**
+     * Applies the given consumer to all successors of this node.
+     *
+     * @param consumer the consumer to be applied to the inputs
+     */
+    public void acceptSuccessors(BiConsumer consumer) {
+        nodeClass.getSuccessorEdges().accept(this, consumer);
     }
 
     /**
@@ -332,7 +361,9 @@
             if (length == 0) {
                 extraUsages = new Node[4];
             } else if (extraUsagesCount == length) {
-                extraUsages = Arrays.copyOf(extraUsages, length * 2 + 1);
+                Node[] newExtraUsages = new Node[length * 2 + 1];
+                System.arraycopy(extraUsages, 0, newExtraUsages, 0, length);
+                extraUsages = newExtraUsages;
             }
             extraUsages[extraUsagesCount++] = node;
         }
@@ -371,7 +402,7 @@
      * @param node the node to remove
      * @return whether or not {@code usage} was in the usage list
      */
-    private boolean removeUsage(Node node) {
+    public boolean removeUsage(Node node) {
         assert node != null;
         // It is critical that this method maintains the invariant that
         // the usage list has no null element preceding a non-null element
@@ -395,6 +426,7 @@
 
     private void clearUsages() {
         incUsageModCount();
+        maybeNotifyZeroUsages(this);
         usage0 = null;
         usage1 = null;
         extraUsages = NO_NODES;
@@ -489,15 +521,21 @@
         assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id);
         this.graph = newGraph;
         newGraph.register(this);
-        for (Node input : inputs()) {
-            updateUsages(null, input);
-        }
-        for (Node successor : successors()) {
-            updatePredecessor(null, successor);
-        }
+        this.acceptInputs((n, i) -> {
+            if (!i.isAlive()) {
+                throw new IllegalStateException(String.format("Input %s of newly created node %s is not alive.", i, n));
+            }
+            n.updateUsages(null, i);
+        });
+        this.acceptSuccessors((n, s) -> {
+            if (!s.isAlive()) {
+                throw new IllegalStateException(String.format("Successor %s of newly created node %s is not alive.", s, n));
+            }
+            n.updatePredecessor(null, s);
+        });
     }
 
-    public final NodeClass getNodeClass() {
+    public final NodeClass getNodeClass() {
         return nodeClass;
     }
 
@@ -516,7 +554,7 @@
     public void replaceAtUsages(Node other) {
         assert checkReplaceWith(other);
         for (Node usage : usages()) {
-            boolean result = usage.getNodeClass().getEdges(Inputs).replaceFirst(usage, this, other);
+            boolean result = usage.getNodeClass().getInputEdges().replaceFirst(usage, this, other);
             assert assertTrue(result, "not found in inputs, usage: %s", usage);
             if (other != null) {
                 maybeNotifyInputChanged(usage);
@@ -542,7 +580,7 @@
         while (index < this.getUsageCount()) {
             Node usage = getUsageAt(index);
             if (usagePredicate.apply(usage)) {
-                boolean result = usage.getNodeClass().getEdges(Inputs).replaceFirst(usage, this, other);
+                boolean result = usage.getNodeClass().getInputEdges().replaceFirst(usage, this, other);
                 assert assertTrue(result, "not found in inputs, usage: %s", usage);
                 if (other != null) {
                     maybeNotifyInputChanged(usage);
@@ -585,7 +623,7 @@
         if (graph != null) {
             assert !graph.isFrozen();
             NodeEventListener listener = graph.nodeEventListener;
-            if (listener != null) {
+            if (listener != null && node.isAlive()) {
                 listener.usagesDroppedToZero(node);
             }
             if (Fingerprint.ENABLED) {
@@ -597,7 +635,7 @@
     public void replaceAtPredecessor(Node other) {
         assert checkReplaceWith(other);
         if (predecessor != null) {
-            boolean result = predecessor.getNodeClass().getEdges(Successors).replaceFirst(predecessor, this, other);
+            boolean result = predecessor.getNodeClass().getSuccessorEdges().replaceFirst(predecessor, this, other);
             assert assertTrue(result, "not found in successors, predecessor: %s", predecessor);
             predecessor.updatePredecessor(this, other);
         }
@@ -605,22 +643,22 @@
 
     public void replaceAndDelete(Node other) {
         assert checkReplaceWith(other);
-        if (other != null) {
-            clearSuccessors();
-            replaceAtUsages(other);
-            replaceAtPredecessor(other);
-        }
+        assert other != null;
+        clearInputs();
+        clearSuccessors();
+        replaceAtUsages(other);
+        replaceAtPredecessor(other);
         safeDelete();
     }
 
     public void replaceFirstSuccessor(Node oldSuccessor, Node newSuccessor) {
-        if (getNodeClass().getEdges(Successors).replaceFirst(this, oldSuccessor, newSuccessor)) {
+        if (nodeClass.getSuccessorEdges().replaceFirst(this, oldSuccessor, newSuccessor)) {
             updatePredecessor(oldSuccessor, newSuccessor);
         }
     }
 
     public void replaceFirstInput(Node oldInput, Node newInput) {
-        if (getNodeClass().getEdges(Inputs).replaceFirst(this, oldInput, newInput)) {
+        if (nodeClass.getInputEdges().replaceFirst(this, oldInput, newInput)) {
             updateUsages(oldInput, newInput);
         }
     }
@@ -638,7 +676,7 @@
         assert assertFalse(isDeleted(), "cannot clear inputs of deleted node");
 
         unregisterInputs();
-        getNodeClass().getEdges(Inputs).clear(this);
+        getNodeClass().getInputEdges().clear(this);
     }
 
     private boolean removeThisFromUsages(Node n) {
@@ -646,17 +684,14 @@
     }
 
     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;
-        }
+        this.acceptSuccessors((n, successor) -> successor.predecessor = null);
     }
 
     public void clearSuccessors() {
         assert assertFalse(isDeleted(), "cannot clear successors of deleted node");
 
         unregisterSuccessors();
-        getNodeClass().getEdges(Successors).clear(this);
+        getNodeClass().getSuccessorEdges().clear(this);
     }
 
     private boolean checkDeletion() {
@@ -673,6 +708,10 @@
         assert checkDeletion();
         unregisterInputs();
         unregisterSuccessors();
+        markDeleted();
+    }
+
+    public void markDeleted() {
         graph.unregister(this);
         id = DELETED_ID_START - id;
         assert isDeleted();
@@ -739,7 +778,7 @@
      * @return the copy of this node
      */
     final Node clone(Graph into, EnumSet edgesToCopy) {
-        final NodeClass nodeClassTmp = getNodeClass();
+        final NodeClass nodeClassTmp = getNodeClass();
         boolean useIntoLeafNodeCache = false;
         if (into != null) {
             if (nodeClassTmp.valueNumberable() && nodeClassTmp.isLeafNode()) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Mon Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java	Mon Mar 02 19:11:22 2015 +0100
@@ -60,6 +60,10 @@
     public boolean isMarked(Node node) {
         assert check(node, false);
         int id = nodeIdAccessor.getNodeId(node);
+        return isMarked(id);
+    }
+
+    public boolean isMarked(int id) {
         return (bits[id >> SHIFT] & (1L << id)) != 0;
     }
 
@@ -67,7 +71,7 @@
         assert check(node, true);
         int id = nodeIdAccessor.getNodeId(node);
         checkGrow(id);
-        return (bits[id >> SHIFT] & (1L << id)) != 0;
+        return isMarked(id);
     }
 
     public void mark(Node node) {
diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Mar 02 19:11:22 2015 +0100
@@ -30,6 +30,7 @@
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.concurrent.atomic.*;
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
@@ -40,6 +41,7 @@
 import com.oracle.graal.graph.Node.OptionalInput;
 import com.oracle.graal.graph.Node.Successor;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.nodeinfo.*;
 
 /**
@@ -50,12 +52,9 @@
  * 
  • The identifier for an {@link IterableNodeType} class.
  • * */ -public final class NodeClass extends FieldIntrospection { - - private static final Object GetNodeClassLock = new Object(); +public final class NodeClass extends FieldIntrospection { // Timers for creation of a NodeClass instance - private static final DebugTimer Init = Debug.timer("NodeClass.Init"); private static final DebugTimer Init_FieldScanning = Debug.timer("NodeClass.Init.FieldScanning"); private static final DebugTimer Init_FieldScanningInner = Debug.timer("NodeClass.Init.FieldScanning.Inner"); private static final DebugTimer Init_AnnotationParsing = Debug.timer("NodeClass.Init.AnnotationParsing"); @@ -73,45 +72,36 @@ /** * Gets the {@link NodeClass} associated with a given {@link Class}. */ - @SuppressWarnings("unchecked") - public static NodeClass get(Class c) { - Class key = (Class) c; + public static NodeClass create(Class c) { + assert get(c) == null; + Class superclass = c.getSuperclass(); + NodeClass nodeSuperclass = null; + if (superclass != NODE_CLASS) { + nodeSuperclass = get(superclass); + } + return new NodeClass<>(c, nodeSuperclass); + } - NodeClass value = (NodeClass) allClasses.get(key); - // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get} - // are used makes the double-checked locking idiom work. - if (value == null) { - // The creation of a NodeClass must be serialized as the NodeClass constructor accesses - // both FieldIntrospection.allClasses and NodeClass.nextIterableId. - synchronized (GetNodeClassLock) { - try (TimerCloseable t = Init.start()) { - value = (NodeClass) allClasses.get(key); - if (value == null) { - Class superclass = c.getSuperclass(); - NodeClass superNodeClass = null; - if (superclass != NODE_CLASS) { - // Ensure NodeClass for superclass exists - superNodeClass = get(superclass); - } - value = new NodeClass(key, superNodeClass); - Object old = allClasses.putIfAbsent(key, value); - assert old == null : old + " " + key; - } - } - } + @SuppressWarnings("unchecked") + public static NodeClass get(Class superclass) { + try { + Field field = superclass.getDeclaredField("TYPE"); + field.setAccessible(true); + return (NodeClass) field.get(null); + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { + throw new RuntimeException(e); } - return value; } private static final Class NODE_CLASS = Node.class; private static final Class INPUT_LIST_CLASS = NodeInputList.class; private static final Class SUCCESSOR_LIST_CLASS = NodeSuccessorList.class; - private static int nextIterableId = 0; + private static AtomicInteger nextIterableId = new AtomicInteger(); private final InputEdges inputs; private final SuccessorEdges successors; - private final NodeClass superNodeClass; + private final NodeClass superNodeClass; private final boolean canGVN; private final int startGVNNumber; @@ -129,21 +119,27 @@ private final boolean isCanonicalizable; /** + * Determines if this node type implements {@link BinaryCommutative}. + */ + private final boolean isCommutative; + + /** * Determines if this node type implements {@link Simplifiable}. */ private final boolean isSimplifiable; private final boolean isLeafNode; - public NodeClass(Class clazz, NodeClass superNodeClass) { + public NodeClass(Class clazz, NodeClass superNodeClass) { this(clazz, superNodeClass, new FieldsScanner.DefaultCalcOffset(), null, 0); } - public NodeClass(Class clazz, NodeClass superNodeClass, FieldsScanner.CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { + public NodeClass(Class clazz, NodeClass superNodeClass, FieldsScanner.CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { super(clazz); this.superNodeClass = superNodeClass; assert NODE_CLASS.isAssignableFrom(clazz); this.isCanonicalizable = Canonicalizable.class.isAssignableFrom(clazz); + this.isCommutative = BinaryCommutative.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"; } @@ -183,9 +179,9 @@ } else if (IterableNodeType.class.isAssignableFrom(clazz)) { ITERABLE_NODE_TYPES.increment(); try (TimerCloseable t1 = Init_IterableIds.start()) { - this.iterableId = nextIterableId++; + this.iterableId = nextIterableId.getAndIncrement(); - NodeClass snc = superNodeClass; + NodeClass snc = superNodeClass; while (snc != null && IterableNodeType.class.isAssignableFrom(snc.getClazz())) { assert !containsId(this.iterableId, snc.iterableIds); snc.iterableIds = Arrays.copyOf(snc.iterableIds, snc.iterableIds.length + 1); @@ -249,6 +245,13 @@ } /** + * Determines if this node type implements {@link BinaryCommutative}. + */ + public boolean isCommutative() { + return isCommutative; + } + + /** * Determines if this node type implements {@link Simplifiable}. */ public boolean isSimplifiable() { @@ -256,7 +259,7 @@ } static int allocatedNodeIterabledIds() { - return nextIterableId; + return nextIterableId.get(); } public EnumSet getAllowedUsageTypes() { @@ -316,7 +319,7 @@ int directInputs; int directSuccessors; - protected NodeFieldsScanner(FieldsScanner.CalcOffset calc, NodeClass superNodeClass) { + protected NodeFieldsScanner(FieldsScanner.CalcOffset calc, NodeClass superNodeClass) { super(calc); if (superNodeClass != null) { translateInto(superNodeClass.inputs, inputs); @@ -564,7 +567,7 @@ return true; } - public boolean isValid(Position pos, NodeClass from, Edges fromEdges) { + public boolean isValid(Position pos, NodeClass from, Edges fromEdges) { if (this == from) { return true; } @@ -580,30 +583,38 @@ static void updateEdgesInPlace(Node node, InplaceUpdateClosure duplicationReplacement, Edges edges) { int index = 0; - while (index < edges.getDirectCount()) { - Node edge = edges.getNode(node, index); + Type curType = edges.type(); + int directCount = edges.getDirectCount(); + final long[] curOffsets = edges.getOffsets(); + while (index < directCount) { + Node edge = Edges.getNode(node, curOffsets, index); if (edge != null) { - Node newEdge = duplicationReplacement.replacement(edge, edges.type()); - if (edges.type() == Edges.Type.Inputs) { + Node newEdge = duplicationReplacement.replacement(edge, curType); + if (curType == Edges.Type.Inputs) { node.updateUsages(null, newEdge); } else { node.updatePredecessor(null, newEdge); } - assert newEdge == null || edges.getType(index).isAssignableFrom(newEdge.getClass()) : "Can not assign " + newEdge.getClass() + " to " + edges.getType(index) + " in " + node; - edges.initializeNode(node, index, newEdge); + assert assertUpdateValid(node, edges, index, newEdge); + Edges.initializeNode(node, curOffsets, index, newEdge); } index++; } while (index < edges.getCount()) { - NodeList list = edges.getNodeList(node, index); + NodeList list = Edges.getNodeList(node, curOffsets, index); if (list != null) { - edges.initializeList(node, index, updateEdgeListCopy(node, list, duplicationReplacement, edges.type())); + Edges.initializeList(node, curOffsets, index, updateEdgeListCopy(node, list, duplicationReplacement, curType)); } index++; } } + private static boolean assertUpdateValid(Node node, Edges edges, int index, Node newEdge) { + assert newEdge == null || edges.getType(index).isAssignableFrom(newEdge.getClass()) : "Can not assign " + newEdge.getClass() + " to " + edges.getType(index) + " in " + node; + return true; + } + void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) { updateEdgesInPlace(node, duplicationReplacement, inputs); updateEdgesInPlace(node, duplicationReplacement, successors); @@ -629,6 +640,14 @@ return type == Edges.Type.Inputs ? inputs : successors; } + public Edges getInputEdges() { + return inputs; + } + + public Edges getSuccessorEdges() { + return successors; + } + /** * Initializes a fresh allocated node for which no constructor is called yet. Needed to * implement node factories in svm. @@ -641,14 +660,15 @@ private void initNullEdgeLists(Node node, Edges.Type type) { Edges edges = getEdges(type); + final long[] curOffsets = edges.getOffsets(); for (int inputPos = edges.getDirectCount(); inputPos < edges.getCount(); inputPos++) { - if (edges.getNodeList(node, inputPos) == null) { - edges.initializeList(node, inputPos, type == Edges.Type.Inputs ? new NodeInputList<>(node) : new NodeSuccessorList<>(node)); + if (Edges.getNodeList(node, curOffsets, inputPos) == null) { + Edges.initializeList(node, curOffsets, inputPos, type == Edges.Type.Inputs ? new NodeInputList<>(node) : new NodeSuccessorList<>(node)); } } } - public Class getJavaClass() { + public Class getJavaClass() { return getClazz(); } @@ -702,7 +722,7 @@ // re-wire inputs for (Node oldNode : nodes) { Node node = newNodes.get(oldNode); - NodeClass nodeClass = node.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); if (replacements == null || replacements.replacement(oldNode) == oldNode) { nodeClass.updateInputSuccInPlace(node, replacementClosure); } else { @@ -746,8 +766,8 @@ } private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node, Edges.Type type) { - NodeClass nodeClass = node.getNodeClass(); - NodeClass oldNodeClass = oldNode.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); + NodeClass oldNodeClass = oldNode.getNodeClass(); Edges oldEdges = oldNodeClass.getEdges(type); for (NodePosIterator oldIter = oldEdges.getIterable(oldNode).iterator(); oldIter.hasNext();) { Position pos = oldIter.nextPosition(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeFlood.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeFlood.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeFlood.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,10 +24,11 @@ import java.util.*; -public class NodeFlood implements Iterable { +public final class NodeFlood implements Iterable { private final NodeBitMap visited; private final Queue worklist; + private int totalMarkedCount; public NodeFlood(Graph graph) { visited = graph.createNodeBitMap(); @@ -38,15 +39,24 @@ if (node != null && !visited.isMarked(node)) { visited.mark(node); worklist.add(node); + totalMarkedCount++; } } + public int getTotalMarkedCount() { + return totalMarkedCount; + } + public void addAll(Iterable nodes) { for (Node node : nodes) { this.add(node); } } + public NodeBitMap getVisited() { + return visited; + } + public boolean isMarked(Node node) { return visited.isMarked(node); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeIdAccessor.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeIdAccessor.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeIdAccessor.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,7 +40,7 @@ /** * Verifies that node identifiers have not changed since this object was created. - * + * * @return true if the check succeeds * @throws VerificationError if the check fails */ diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Mon Mar 02 19:11:22 2015 +0100 @@ -143,7 +143,9 @@ if (length == 0) { nodes = new Node[2]; } else if (size == length) { - nodes = Arrays.copyOf(nodes, nodes.length * 2 + 1); + Node[] newNodes = new Node[nodes.length * 2 + 1]; + System.arraycopy(nodes, 0, newNodes, 0, length); + nodes = newNodes; } nodes[size++] = node; update(null, (T) node); @@ -186,7 +188,9 @@ void copy(NodeList other) { self.incModCount(); incModCount(); - nodes = Arrays.copyOf(other.nodes, other.size); + Node[] newNodes = new Node[other.size]; + System.arraycopy(other.nodes, 0, newNodes, 0, newNodes.length); + nodes = newNodes; size = other.size; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUnionFind.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUnionFind.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUnionFind.java Mon Mar 02 19:11:22 2015 +0100 @@ -73,12 +73,14 @@ private void union(int a, int b) { int aRoot = find(a); int bRoot = find(b); - if (rank[aRoot] < rank[bRoot]) { - parent[aRoot] = bRoot; - } else { - parent[bRoot] = aRoot; - if (rank[aRoot] == rank[bRoot]) { - rank[aRoot]++; + if (aRoot != bRoot) { + if (rank[aRoot] < rank[bRoot]) { + parent[aRoot] = bRoot; + } else { + parent[bRoot] = aRoot; + if (rank[aRoot] == rank[bRoot]) { + rank[aRoot]++; + } } } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeWorkList.java Mon Mar 02 19:11:22 2015 +0100 @@ -157,7 +157,7 @@ } private boolean checkInfiniteWork(Node node) { - if (lastPull == node) { + if (lastPull == node && !node.hasNoUsages()) { if (firstNoChange == null) { firstNoChange = node; lastChain = node; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java Mon Mar 02 19:11:22 2015 +0100 @@ -53,9 +53,9 @@ public Node get(Node node) { if (index < edges.getDirectCount()) { - return edges.getNode(node, index); + return Edges.getNode(node, edges.getOffsets(), index); } else { - return edges.getNodeList(node, index).get(subIndex); + return Edges.getNodeList(node, edges.getOffsets(), index).get(subIndex); } } @@ -75,15 +75,15 @@ if (index < edges.getDirectCount()) { edges.setNode(node, index, value); } else { - edges.getNodeList(node, index).set(subIndex, value); + Edges.getNodeList(node, edges.getOffsets(), index).set(subIndex, value); } } public void initialize(Node node, Node value) { if (index < edges.getDirectCount()) { - edges.initializeNode(node, index, value); + Edges.initializeNode(node, edges.getOffsets(), index, value); } else { - edges.getNodeList(node, index).initialize(subIndex, value); + Edges.getNodeList(node, edges.getOffsets(), index).initialize(subIndex, value); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/TypedGraphNodeIterator.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/TypedGraphNodeIterator.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/TypedGraphNodeIterator.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,7 +33,7 @@ private int currentIdIndex; private boolean needsForward; - public TypedGraphNodeIterator(NodeClass clazz, Graph graph) { + public TypedGraphNodeIterator(NodeClass clazz, Graph graph) { this.graph = graph; ids = clazz.iterableIds(); currentIdIndex = 0; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,7 +34,7 @@ * This constructor creates a {@link VerificationError} with a message assembled via * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to * always generate the same output. - * + * * @param msg the message that will be associated with the error, in String.format syntax * @param args parameters to String.format - parameters that implement {@link Iterable} will be * expanded into a [x, x, ...] representation. diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java Mon Mar 02 19:11:22 2015 +0100 @@ -128,4 +128,22 @@ return canonical(tool, getX(), getY()); } } + + /** + * This sub-interface of {@link Canonicalizable.Binary} is for nodes with two inputs where the + * operation is commutative. It is used to improve GVN by trying to merge nodes with the same + * inputs in different order. + */ + public interface BinaryCommutative extends Binary { + + /** + * Ensure a canonical ordering of inputs for commutative nodes to improve GVN results. Order + * the inputs by increasing {@link Node#id} and call {@link Graph#findDuplicate(Node)} on + * the node if it's currently in a graph. It's assumed that if there was a constant on the + * left it's been moved to the right by other code and that ordering is left alone. + * + * @return the original node or another node with the same input ordering + */ + Node maybeCommuteInputs(); + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Simplifiable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Simplifiable.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Simplifiable.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,7 +25,7 @@ /** * This interface allows nodes to perform more complicated simplifications, in contrast to * {@link Canonicalizable}, which supports only replacing the current node. - * + * * Implementors of this interface need to be aware that they need to call * {@link SimplifierTool#addToWorkList(com.oracle.graal.graph.Node)} for each node that might be * influenced (in terms of simplification and canonicalization) by the actions performed in diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java --- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.nodes.CompressionNode.CompressionOp; @@ -154,11 +155,12 @@ @NodeInfo private static final class LoadThroughPatchNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(LoadThroughPatchNode.class); @Input protected ValueNode input; public LoadThroughPatchNode(ValueNode input) { - super(input.stamp()); + super(TYPE, input.stamp()); this.input = input; } @@ -176,13 +178,15 @@ public static native Object load(Object obj); } - private static class LoadThroughPatchOp extends LIRInstructionBase { + private static final class LoadThroughPatchOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadThroughPatchOp.class); final Constant c; final boolean compressed; @Def({REG}) AllocatableValue result; LoadThroughPatchOp(Constant c, boolean compressed, AllocatableValue result) { + super(TYPE); this.c = c; this.compressed = compressed; this.result = result; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 @@ @Opcode("DEOPT") final class AMD64DeoptimizeOp extends AMD64LIRInstruction implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64DeoptimizeOp.class); @State private LIRFrameState info; AMD64DeoptimizeOp(LIRFrameState info) { + super(TYPE); this.info = info; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon Mar 02 19:11:22 2015 +0100 @@ -163,7 +163,7 @@ disassembler = createDisassembler(runtime); } try (InitTimer rt = timer("create Suites provider")) { - suites = createSuites(runtime); + suites = createSuites(runtime, metaAccess, constantReflection, replacements); } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection); } @@ -209,8 +209,8 @@ return new HotSpotMetaAccessProvider(runtime); } - protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime) { - return new HotSpotSuitesProvider(runtime); + protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { + return new HotSpotSuitesProvider(runtime, metaAccess, constantReflection, replacements); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime) { @@ -248,15 +248,15 @@ } else { /* * System V Application Binary Interface, AMD64 Architecture Processor Supplement - * + * * Draft Version 0.96 - * + * * http://www.uclibc.org/docs/psABI-x86_64.pdf - * + * * 3.2.1 - * + * * ... - * + * * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12 * through %r15 "belong" to the calling function and the called function is required to * preserve their values. In other words, a called function must preserve these diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +30,14 @@ @Opcode("CRUNTIME_CALL_EPILOGUE") final class AMD64HotSpotCRuntimeCallEpilogueOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotCRuntimeCallEpilogueOp.class); private final int threadLastJavaSpOffset; private final int threadLastJavaFpOffset; private final Register thread; public AMD64HotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaFpOffset, Register thread) { + super(TYPE); this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaFpOffset = threadLastJavaFpOffset; this.thread = thread; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,11 +32,13 @@ @Opcode final class AMD64HotSpotCRuntimeCallPrologueOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotCRuntimeCallPrologueOp.class); private final int threadLastJavaSpOffset; private final Register thread; public AMD64HotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread) { + super(TYPE); this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.thread = thread; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableAddressOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableAddressOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableAddressOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +26,18 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.*; +import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.hotspot.HotSpotGraalRuntime; -public class AMD64HotSpotCardTableAddressOp extends AMD64LIRInstruction { +public final class AMD64HotSpotCardTableAddressOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotCardTableAddressOp.class); @Def({OperandFlag.REG}) private AllocatableValue result; public AMD64HotSpotCardTableAddressOp(AllocatableValue result) { + super(TYPE); this.result = result; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableShiftOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableShiftOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableShiftOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +26,18 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.*; +import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.hotspot.HotSpotGraalRuntime; -public class AMD64HotSpotCardTableShiftOp extends AMD64LIRInstruction { +public final class AMD64HotSpotCardTableShiftOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotCardTableShiftOp.class); @Def({OperandFlag.REG, OperandFlag.ILLEGAL}) private AllocatableValue result; public AMD64HotSpotCardTableShiftOp(AllocatableValue result) { + super(TYPE); this.result = result; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +39,14 @@ public class AMD64HotSpotCompare { @Opcode("CMP") - public static class HotSpotCompareConstantOp extends AMD64LIRInstruction { + public static final class HotSpotCompareConstantOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(HotSpotCompareConstantOp.class); @Use({REG}) protected AllocatableValue x; protected JavaConstant y; public HotSpotCompareConstantOp(AllocatableValue x, JavaConstant y) { + super(TYPE); this.x = x; this.y = y; } @@ -100,12 +102,13 @@ } @Opcode("CMP") - public static class HotSpotCompareMemoryConstantOp extends MemOp { + public static final class HotSpotCompareMemoryConstantOp extends MemOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(HotSpotCompareMemoryConstantOp.class); protected JavaConstant y; public HotSpotCompareMemoryConstantOp(Kind kind, AMD64AddressValue x, JavaConstant y, LIRFrameState state) { - super(kind, x, state); + super(TYPE, kind, x, state); this.y = y; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,6 +36,12 @@ @Opcode("DEOPT_CALLER") final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotDeoptimizeCallerOp.class); + + protected AMD64HotSpotDeoptimizeCallerOp() { + super(TYPE); + } + @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { leaveFrameAndRestoreRbp(crb, masm); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +42,7 @@ */ @Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotEnterUnpackFramesStackFrameOp.class); private final Register threadRegister; private final int threadLastJavaSpOffset; @@ -55,6 +56,7 @@ AMD64HotSpotEnterUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue senderFp, SaveRegistersOp saveRegisterOp) { + super(TYPE); this.threadRegister = threadRegister; this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,6 +38,10 @@ */ abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction { + protected AMD64HotSpotEpilogueOp(LIRInstructionClass c) { + super(c); + } + /** * The type of location (i.e., stack or register) in which RBP is saved is not known until * initial LIR generation is finished. Until then, we use a placeholder variable so that LIR diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotBackend.Options.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; @@ -61,8 +62,10 @@ register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, null, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, ANY_LOCATION)); - link(new AMD64DeoptimizationStub(providers, target, config, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64UncommonTrapStub(providers, target, config, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + if (PreferGraalStubs.getValue()) { + link(new AMD64DeoptimizationStub(providers, target, config, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64UncommonTrapStub(providers, target, config, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + } if (config.useCRC32Intrinsics) { // This stub does callee saving diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -41,6 +41,8 @@ @Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER") final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotJumpToExceptionHandlerInCallerOp.class); + @Use(REG) AllocatableValue handlerInCallerPc; @Use(REG) AllocatableValue exception; @Use(REG) AllocatableValue exceptionPc; @@ -48,6 +50,7 @@ private final int isMethodHandleReturnOffset; AMD64HotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc, int isMethodHandleReturnOffset, Register thread) { + super(TYPE); this.handlerInCallerPc = handlerInCallerPc; this.exception = exception; this.exceptionPc = exceptionPc; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -39,9 +39,12 @@ @Opcode("LEAVE_CURRENT_STACK_FRAME") final class AMD64HotSpotLeaveCurrentStackFrameOp extends AMD64HotSpotEpilogueOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotLeaveCurrentStackFrameOp.class); + private final SaveRegistersOp saveRegisterOp; public AMD64HotSpotLeaveCurrentStackFrameOp(SaveRegistersOp saveRegisterOp) { + super(TYPE); this.saveRegisterOp = saveRegisterOp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,10 +38,12 @@ @Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME") final class AMD64HotSpotLeaveDeoptimizedStackFrameOp extends AMD64HotSpotEpilogueOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotLeaveDeoptimizedStackFrameOp.class); @Use(REG) AllocatableValue frameSize; @Use(REG) AllocatableValue framePointer; public AMD64HotSpotLeaveDeoptimizedStackFrameOp(AllocatableValue frameSize, AllocatableValue initialInfo) { + super(TYPE); this.frameSize = frameSize; this.framePointer = initialInfo; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +38,7 @@ */ @Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotLeaveUnpackFramesStackFrameOp.class); private final Register threadRegister; private final int threadLastJavaSpOffset; @@ -47,6 +48,7 @@ private final SaveRegistersOp saveRegisterOp; AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, SaveRegistersOp saveRegisterOp) { + super(TYPE); this.threadRegister = threadRegister; this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +43,14 @@ public class AMD64HotSpotMove { - public static class HotSpotLoadConstantOp extends AMD64LIRInstruction implements MoveOp { + public static final class HotSpotLoadConstantOp extends AMD64LIRInstruction implements MoveOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(HotSpotLoadConstantOp.class); @Def({REG, STACK}) private AllocatableValue result; private final JavaConstant input; public HotSpotLoadConstantOp(AllocatableValue result, JavaConstant input) { + super(TYPE); this.result = result; this.input = input; } @@ -145,9 +147,10 @@ } public static class HotSpotStoreConstantOp extends StoreConstantOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(HotSpotStoreConstantOp.class); public HotSpotStoreConstantOp(Kind kind, AMD64AddressValue address, JavaConstant input, LIRFrameState state) { - super(kind, address, input, state); + super(TYPE, kind, address, input, state); } @Override @@ -181,7 +184,8 @@ } } - public static class CompressPointer extends AMD64LIRInstruction { + public static final class CompressPointer extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompressPointer.class); private final CompressEncoding encoding; private final boolean nonNull; @@ -191,6 +195,7 @@ @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister; public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) { + super(TYPE); this.result = result; this.input = input; this.baseRegister = baseRegister; @@ -218,7 +223,8 @@ } } - public static class UncompressPointer extends AMD64LIRInstruction { + public static final class UncompressPointer extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(UncompressPointer.class); private final CompressEncoding encoding; private final boolean nonNull; @@ -228,6 +234,7 @@ @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister; public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) { + super(TYPE); this.result = result; this.input = input; this.baseRegister = baseRegister; @@ -274,12 +281,14 @@ } } - public static class CompressedNullCheckOp extends AMD64LIRInstruction { + public static final class CompressedNullCheckOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompressedNullCheckOp.class); @Use({COMPOSITE}) protected AMD64AddressValue address; @State protected LIRFrameState state; public CompressedNullCheckOp(AMD64AddressValue address, LIRFrameState state) { + super(TYPE); this.address = address; this.state = state; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Mon Mar 02 19:11:22 2015 +0100 @@ -134,7 +134,7 @@ setSaveRbp(((AMD64HotSpotLIRGenerator) gen).new SaveRbp(new NoOp(gen.getCurrentBlock(), gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size()))); append(getSaveRbp().placeholder); - for (ParameterNode param : graph.getNodes(ParameterNode.class)) { + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { Value paramValue = params[param.index()]; assert paramValue.getLIRKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp())); setResult(param, gen.emitMove(paramValue)); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +37,12 @@ */ @Opcode("PATCH_RETURN") final class AMD64HotSpotPatchReturnAddressOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotPatchReturnAddressOp.class); @Use(REG) AllocatableValue address; AMD64HotSpotPatchReturnAddressOp(AllocatableValue address) { + super(TYPE); this.address = address; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -39,6 +39,7 @@ */ @Opcode("PUSH_INTERPRETER_FRAME") final class AMD64HotSpotPushInterpreterFrameOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotPushInterpreterFrameOp.class); @Alive(REG) AllocatableValue frameSize; @Alive(REG) AllocatableValue framePc; @@ -47,6 +48,7 @@ private final HotSpotVMConfig config; AMD64HotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo, HotSpotVMConfig config) { + super(TYPE); this.frameSize = frameSize; this.framePc = framePc; this.senderSp = senderSp; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,12 +38,14 @@ @Opcode("RETURN") final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotReturnOp.class); @Use({REG, ILLEGAL}) protected Value value; private final boolean isStub; private final Register scratchForSafepointOnReturn; private final HotSpotVMConfig config; AMD64HotSpotReturnOp(Value value, boolean isStub, Register scratchForSafepointOnReturn, HotSpotVMConfig config) { + super(TYPE); this.value = value; this.isStub = isStub; this.scratchForSafepointOnReturn = scratchForSafepointOnReturn; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,8 @@ * Emits a safepoint poll. */ @Opcode("SAFEPOINT") -public class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { +public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotSafepointOp.class); @State protected LIRFrameState state; @Temp({OperandFlag.REG, OperandFlag.ILLEGAL}) private AllocatableValue temp; @@ -48,6 +49,7 @@ private final HotSpotVMConfig config; public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRBuilderTool tool) { + super(TYPE); this.state = state; this.config = config; if (isPollingPageFar(config) || ImmutableCode.getValue()) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,10 +40,12 @@ */ @Opcode("UNWIND") final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotUnwindOp.class); @Use({REG}) protected RegisterValue exception; AMD64HotSpotUnwindOp(RegisterValue exception) { + super(TYPE); this.exception = exception; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,11 +36,12 @@ */ @Opcode("CALL_DIRECT") final class AMD64HotspotDirectStaticCallOp extends DirectCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotspotDirectStaticCallOp.class); private final InvokeKind invokeKind; AMD64HotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) { - super(target, result, parameters, temps, state); + super(TYPE, target, result, parameters, temps, state); assert invokeKind.isDirect(); this.invokeKind = invokeKind; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; +import com.oracle.graal.lir.amd64.AMD64Call.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; @@ -38,12 +38,13 @@ */ @Opcode("CALL_DIRECT") final class AMD64HotspotDirectVirtualCallOp extends DirectCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotspotDirectVirtualCallOp.class); private final InvokeKind invokeKind; private final HotSpotVMConfig config; AMD64HotspotDirectVirtualCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, HotSpotVMConfig config) { - super(target, result, parameters, temps, state); + super(TYPE, target, result, parameters, temps, state); this.invokeKind = invokeKind; this.config = config; assert invokeKind.isIndirect(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -43,6 +43,7 @@ */ @Opcode("CALL_INDIRECT") final class AMD64IndirectCallOp extends IndirectCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64IndirectCallOp.class); /** * Vtable stubs expect the metaspace Method in RBX. @@ -52,7 +53,7 @@ @Use({REG}) protected Value metaspaceMethod; AMD64IndirectCallOp(ResolvedJavaMethod targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) { - super(targetMethod, result, parameters, temps, targetAddress, state); + super(TYPE, targetMethod, result, parameters, temps, targetAddress, state); this.metaspaceMethod = metaspaceMethod; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +27,18 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; -public class AMD64PrefetchOp extends AMD64LIRInstruction { +public final class AMD64PrefetchOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64PrefetchOp.class); private final int instr; // AllocatePrefetchInstr @Alive({COMPOSITE}) protected AMD64AddressValue address; public AMD64PrefetchOp(AMD64AddressValue address, int instr) { + super(TYPE); this.address = address; this.instr = instr; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,12 +34,13 @@ @NodeInfo public final class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AMD64RawNativeCallNode.class); protected final JavaConstant functionPointer; @Input NodeInputList args; public AMD64RawNativeCallNode(Kind returnType, JavaConstant functionPointer, ValueNode[] args) { - super(StampFactory.forKind(returnType)); + super(TYPE, StampFactory.forKind(returnType)); this.functionPointer = functionPointer; this.args = new NodeInputList<>(this, args); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +36,14 @@ * {@link InstalledCode} instance. */ @Opcode("TAILCALL") -public class AMD64TailcallOp extends AMD64LIRInstruction { +public final class AMD64TailcallOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64TailcallOp.class); @Use protected Value target; @Alive protected Value[] parameters; public AMD64TailcallOp(Value[] parameters, Value target) { + super(TYPE); this.target = target; this.parameters = parameters; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java --- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,7 +31,7 @@ /** * A collection of java.lang.reflect proxies that communicate over a socket connection. - * + * * Calling a method sends the method name and the parameters through the socket. Afterwards this * class waits for a result. While waiting for a result three types of objects can arrive through * the socket: a method invocation, a method result or an exception. Method invocation can thus be @@ -83,7 +83,7 @@ /** * Represents one invocation of a method that is transferred via the socket connection. - * + * */ private static class Invocation implements Serializable { @@ -102,7 +102,7 @@ /** * Represents the result of an invocation that is transferred via the socket connection. - * + * */ private static class Result implements Serializable { @@ -130,7 +130,7 @@ * Each instance of this class handles remote invocations for one instance of a Remote class. It * will forward all interface methods to the other end of the socket and cache the results of * calls to certain methods. - * + * */ public class Handler implements InvocationHandler { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 @@ @Opcode("DEOPT") final class SPARCDeoptimizeOp extends SPARCLIRInstruction implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCDeoptimizeOp.class); @State private LIRFrameState info; SPARCDeoptimizeOp(LIRFrameState info) { + super(TYPE); this.info = info; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Mar 02 19:11:22 2015 +0100 @@ -269,7 +269,7 @@ } private static void resetDelayedControlTransfers(LIR lir) { - for (AbstractBlock block : lir.codeEmittingOrder()) { + for (AbstractBlockBase block : lir.codeEmittingOrder()) { for (LIRInstruction inst : lir.getLIRforBlock(block)) { if (inst instanceof SPARCDelayedControlTransfer) { ((SPARCDelayedControlTransfer) inst).resetState(); @@ -281,11 +281,11 @@ /** * Fix-up over whole LIR. * - * @see #stuffDelayedControlTransfers(LIR, AbstractBlock) + * @see #stuffDelayedControlTransfers(LIR, AbstractBlockBase) * @param l */ private static void stuffDelayedControlTransfers(LIR l) { - for (AbstractBlock b : l.codeEmittingOrder()) { + for (AbstractBlockBase b : l.codeEmittingOrder()) { stuffDelayedControlTransfers(l, b); } } @@ -295,7 +295,7 @@ * it tries to move the DelayedLIRInstruction to the DelayedControlTransfer instruction, if * possible. */ - private static void stuffDelayedControlTransfers(LIR l, AbstractBlock block) { + private static void stuffDelayedControlTransfers(LIR l, AbstractBlockBase block) { List instructions = l.getLIRforBlock(block); if (instructions.size() >= 2) { LIRDependencyAccumulator acc = new LIRDependencyAccumulator(); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Mar 02 19:11:22 2015 +0100 @@ -64,7 +64,7 @@ HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime); HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), target); HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime); - HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime); + HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime, metaAccess, constantReflection, replacements); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection); return new SPARCHotSpotBackend(runtime, providers); @@ -93,10 +93,14 @@ @SuppressWarnings("unused") private static Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) { - CalleeSaveLayout csl = regConfig.getCalleeSaveLayout(); - Value[] nativeABICallerSaveRegisters = new Value[csl.registers.length]; - for (int i = 0; i < csl.registers.length; i++) { - nativeABICallerSaveRegisters[i] = csl.registers[i].asValue(); + Set callerSavedRegisters = new HashSet<>(); + Collections.addAll(callerSavedRegisters, regConfig.getCalleeSaveLayout().registers); + Collections.addAll(callerSavedRegisters, SPARC.fpuRegisters); + Value[] nativeABICallerSaveRegisters = new Value[callerSavedRegisters.size()]; + int i = 0; + for (Register reg : callerSavedRegisters) { + nativeABICallerSaveRegisters[i] = reg.asValue(); + i++; } return nativeABICallerSaveRegisters; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +34,7 @@ @Opcode("CRUNTIME_CALL_EPILOGUE") final class SPARCHotSpotCRuntimeCallEpilogueOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotCRuntimeCallEpilogueOp.class); private final int threadLastJavaSpOffset; private final int threadLastJavaPcOffset; @@ -42,6 +43,7 @@ @Use({REG, STACK}) protected Value threadTemp; public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread, Value threadTemp) { + super(TYPE); this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,6 +34,7 @@ @Opcode("CRUNTIME_CALL_PROLOGUE") final class SPARCHotSpotCRuntimeCallPrologueOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotCRuntimeCallPrologueOp.class); private final int threadLastJavaSpOffset; private final Register thread; @@ -41,6 +42,7 @@ @Def({REG, STACK}) protected Value threadTemp; public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer, Value threadTemp) { + super(TYPE); this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.thread = thread; this.stackPointer = stackPointer; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,6 +36,11 @@ */ @Opcode("DEOPT_CALLER") final class SPARCHotSpotDeoptimizeCallerOp extends SPARCHotSpotEpilogueOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotDeoptimizeCallerOp.class); + + protected SPARCHotSpotDeoptimizeCallerOp() { + super(TYPE); + } @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ */ @Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotEnterUnpackFramesStackFrameOp.class); private final Register thread; private final int threadLastJavaSpOffset; @@ -49,6 +50,7 @@ @Temp(REG) AllocatableValue scratch; SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch) { + super(TYPE); this.thread = thread; this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ */ package com.oracle.graal.hotspot.sparc; +import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; @@ -30,6 +31,11 @@ * Superclass for operations that leave a method's frame. */ abstract class SPARCHotSpotEpilogueOp extends SPARCLIRInstruction implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotEpilogueOp.class); + + protected SPARCHotSpotEpilogueOp(LIRInstructionClass c) { + super(c); + } protected void leaveFrame(CompilationResultBuilder crb) { crb.frameContext.leave(crb); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,8 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.api.meta.Value.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotBackend.Options.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; @@ -61,8 +63,10 @@ register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); - link(new SPARCDeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + if (PreferGraalStubs.getValue()) { + link(new SPARCDeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + } super.initialize(providers, config); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +42,8 @@ @Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER") final class SPARCHotSpotJumpToExceptionHandlerInCallerOp extends SPARCHotSpotEpilogueOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotJumpToExceptionHandlerInCallerOp.class); + @Use(REG) AllocatableValue handlerInCallerPc; @Use(REG) AllocatableValue exception; @Use(REG) AllocatableValue exceptionPc; @@ -49,6 +51,7 @@ private final int isMethodHandleReturnOffset; SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc, int isMethodHandleReturnOffset, Register thread) { + super(TYPE); this.handlerInCallerPc = handlerInCallerPc; this.exception = exception; this.exceptionPc = exceptionPc; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +34,10 @@ */ @Opcode("LEAVE_CURRENT_STACK_FRAME") final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotLeaveCurrentStackFrameOp.class); public SPARCHotSpotLeaveCurrentStackFrameOp() { + super(TYPE); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +35,12 @@ @Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME") final class SPARCHotSpotLeaveDeoptimizedStackFrameOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotLeaveDeoptimizedStackFrameOp.class); + + protected SPARCHotSpotLeaveDeoptimizedStackFrameOp() { + super(TYPE); + } + @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { // Save O registers over restore. diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +37,7 @@ */ @Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") final class SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotLeaveUnpackFramesStackFrameOp.class); private final Register thread; private final int threadLastJavaSpOffset; @@ -44,6 +45,7 @@ private final int threadJavaFrameAnchorFlagsOffset; SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) { + super(TYPE); this.thread = thread; this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +38,12 @@ */ @Opcode("PATCH_RETURN") final class SPARCHotSpotPatchReturnAddressOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotPatchReturnAddressOp.class); @Use(REG) AllocatableValue address; SPARCHotSpotPatchReturnAddressOp(AllocatableValue address) { + super(TYPE); this.address = address; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +38,7 @@ */ @Opcode("PUSH_INTERPRETER_FRAME") final class SPARCHotSpotPushInterpreterFrameOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotPushInterpreterFrameOp.class); @Alive(REG) AllocatableValue frameSize; @Alive(REG) AllocatableValue framePc; @@ -45,6 +46,7 @@ @Alive(REG) AllocatableValue initialInfo; SPARCHotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo) { + super(TYPE); this.frameSize = frameSize; this.framePc = framePc; this.senderSp = senderSp; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Mar 02 19:11:22 2015 +0100 @@ -92,7 +92,8 @@ private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7}; // @formatter:off private final Register[] callerSaveRegisters = - {g1, g3, g4, g5, o0, o1, o2, o3, o4, o5, o7, + {g1, g2, g3, g4, g5, g6, g7, + o0, o1, o2, o3, o4, o5, o7, f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +37,14 @@ */ @Opcode("RETURN") final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotReturnOp.class); @Use({REG, ILLEGAL}) protected Value value; private final boolean isStub; private final HotSpotVMConfig config; SPARCHotSpotReturnOp(Value value, boolean isStub, HotSpotVMConfig config) { + super(TYPE); this.value = value; this.isStub = isStub; this.config = config; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +42,7 @@ */ @Opcode("SAFEPOINT") public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotSafepointOp.class); @State protected LIRFrameState state; @SuppressFBWarnings(value = "BC_IMPOSSIBLE_CAST", justification = "changed by the register allocator") @Temp({OperandFlag.REG}) private AllocatableValue temp; @@ -49,9 +50,10 @@ private final HotSpotVMConfig config; public SPARCHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { + super(TYPE); this.state = state; this.config = config; - temp = tool.newVariable(LIRKind.value(tool.target().wordKind)); + this.temp = tool.newVariable(LIRKind.value(tool.target().wordKind)); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +39,12 @@ */ @Opcode("UNWIND") final class SPARCHotSpotUnwindOp extends SPARCHotSpotEpilogueOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotUnwindOp.class); @Use({REG}) protected RegisterValue exception; SPARCHotSpotUnwindOp(RegisterValue exception) { + super(TYPE); this.exception = exception; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,11 +36,12 @@ */ @Opcode("CALL_DIRECT") final class SPARCHotspotDirectStaticCallOp extends DirectCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotspotDirectStaticCallOp.class); private final InvokeKind invokeKind; SPARCHotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) { - super(target, result, parameters, temps, state); + super(TYPE, target, result, parameters, temps, state); assert invokeKind.isDirect(); this.invokeKind = invokeKind; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +41,13 @@ */ @Opcode("CALL_DIRECT") final class SPARCHotspotDirectVirtualCallOp extends DirectCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotspotDirectVirtualCallOp.class); private final InvokeKind invokeKind; private final HotSpotVMConfig config; SPARCHotspotDirectVirtualCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, HotSpotVMConfig config) { - super(target, result, parameters, temps, state); + super(TYPE, target, result, parameters, temps, state); this.invokeKind = invokeKind; this.config = config; assert invokeKind.isIndirect(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -43,6 +43,7 @@ */ @Opcode("CALL_INDIRECT") final class SPARCIndirectCallOp extends IndirectCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCIndirectCallOp.class); /** * Vtable stubs expect the metaspace Method in g5. @@ -52,7 +53,7 @@ @Use({REG}) protected Value metaspaceMethod; SPARCIndirectCallOp(ResolvedJavaMethod targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) { - super(targetMethod, result, parameters, temps, targetAddress, state); + super(TYPE, targetMethod, result, parameters, temps, targetAddress, state); this.metaspaceMethod = metaspaceMethod; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +26,18 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; -public class SPARCPrefetchOp extends SPARCLIRInstruction { +public final class SPARCPrefetchOp extends SPARCLIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCPrefetchOp.class); private final int instr; // AllocatePrefetchInstr @Alive({COMPOSITE}) protected SPARCAddressValue address; public SPARCPrefetchOp(SPARCAddressValue address, int instr) { + super(TYPE); this.address = address; this.instr = instr; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -184,7 +184,7 @@ StructuredGraph result = compile("getBoxedBoolean", true); assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(1, result.getNodes(PiNode.class).count()); + assertDeepEquals(1, result.getNodes(PiNode.TYPE).count()); assertDeepEquals(1, getConstantNodes(result).count()); ConstantNode constant = getConstantNodes(result).first(); assertDeepEquals(Kind.Long, constant.getKind()); @@ -195,7 +195,7 @@ public void testBoxedBoolean() { StructuredGraph result = compile("getBoxedBoolean", false); assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes(PiNode.class).count()); + assertDeepEquals(0, result.getNodes(PiNode.TYPE).count()); assertDeepEquals(1, getConstantNodes(result).count()); ConstantNode constant = getConstantNodes(result).first(); assertDeepEquals(Kind.Object, constant.getKind()); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java Mon Mar 02 19:11:22 2015 +0100 @@ -181,8 +181,8 @@ private void testConstantReturn(String name, Object value) { StructuredGraph result = test(name); - ReturnNode ret = result.getNodes(ReturnNode.class).first(); - assertDeepEquals(1, result.getNodes(ReturnNode.class).count()); + ReturnNode ret = result.getNodes(ReturnNode.TYPE).first(); + assertDeepEquals(1, result.getNodes(ReturnNode.TYPE).count()); assertDeepEquals(true, ret.result().isConstant()); assertDeepEquals(value, ret.result().asJavaConstant().asBoxedPrimitive()); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.nodes.CompressionNode.CompressionOp; @@ -94,10 +95,11 @@ @NodeInfo private static final class ConstantFoldBarrier extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(ConstantFoldBarrier.class); @Input protected ValueNode input; public ConstantFoldBarrier(ValueNode input) { - super(input.stamp()); + super(TYPE, input.stamp()); this.input = input; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,7 +35,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.hotspot.meta.*; public class HotSpotMonitorValueTest extends GraalCompilerTest { @@ -53,14 +52,14 @@ assertNull(caller.caller()); assertDeepEquals(2, frame.numLocks); assertDeepEquals(2, caller.numLocks); - HotSpotMonitorValue lock1 = (HotSpotMonitorValue) frame.getLockValue(0); - HotSpotMonitorValue lock2 = (HotSpotMonitorValue) frame.getLockValue(1); - HotSpotMonitorValue lock3 = (HotSpotMonitorValue) caller.getLockValue(0); - HotSpotMonitorValue lock4 = (HotSpotMonitorValue) caller.getLockValue(1); + StackLockValue lock1 = (StackLockValue) frame.getLockValue(0); + StackLockValue lock2 = (StackLockValue) frame.getLockValue(1); + StackLockValue lock3 = (StackLockValue) caller.getLockValue(0); + StackLockValue lock4 = (StackLockValue) caller.getLockValue(1); - List locks = Arrays.asList(lock1, lock2, lock3, lock4); - for (HotSpotMonitorValue lock : locks) { - for (HotSpotMonitorValue other : locks) { + List locks = Arrays.asList(lock1, lock2, lock3, lock4); + for (StackLockValue lock : locks) { + for (StackLockValue other : locks) { if (other != lock) { // Every lock must have a different stack slot assertThat(lock.getSlot(), not(other.getSlot())); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeClassSubstitutionsTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeClassSubstitutionsTest.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * 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.hotspot.test; - -import org.junit.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.test.*; - -/** - * Tests HotSpot specific substitutions for {@link NodeClass}. - */ -public class HotSpotNodeClassSubstitutionsTest extends MethodSubstitutionTest { - - @Test - public void test() { - test("get", ValueNode.class); - } - - public static NodeClass get(Class c) { - return NodeClass.get(c); - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,7 +40,7 @@ test("getNodeClass", ConstantNode.forInt(42, graph)); } - public static NodeClass getNodeClass(Node n) { + public static NodeClass getNodeClass(Node n) { return n.getNodeClass(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Mar 02 19:11:22 2015 +0100 @@ -42,6 +42,7 @@ import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.word.*; @@ -50,6 +51,13 @@ */ public abstract class HotSpotBackend extends Backend { + public static class Options { + // @formatter:off + @Option(help = "Use Graal stubs instead of HotSpot stubs where possible") + public static final OptionValue PreferGraalStubs = new OptionValue<>(false); + // @formatter:on + } + /** * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the * {@linkplain HotSpotVMConfig#codeInstallerMarkIdExceptionHandlerEntry exception handler} in a @@ -164,7 +172,7 @@ } } }; - for (AbstractBlock block : lir.codeEmittingOrder()) { + for (AbstractBlockBase block : lir.codeEmittingOrder()) { for (LIRInstruction op : lir.getLIRforBlock(block)) { if (op instanceof LabelOp) { // Don't consider this as a definition diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,6 +25,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.meta.*; +import edu.umd.cs.findbugs.annotations.*; + /** * {@link HotSpotCompiledCode} destined for installation as an nmethod. */ @@ -36,6 +38,12 @@ public final int id; public final long graalEnv; + /** + * May be set by VM if code installation fails. It will describe in more detail why installation + * failed (e.g., exactly which dependency failed). + */ + @SuppressFBWarnings("UWF_UNWRITTEN_FIELD") private String installationFailureMessage; + public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) { this(method, compResult, 0L); } @@ -52,4 +60,8 @@ public String toString() { return getClass().getSimpleName() + "[" + id + ":" + method.format("%H.%n(%p)%r@") + entryBCI + "]"; } + + public String getInstallationFailureMessage() { + return installationFailureMessage; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; @@ -57,7 +56,7 @@ JavaValue object = toValue(lock); boolean eliminated = object instanceof VirtualObject && state.monitorIdAt(lockIndex) != null; assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth; - return new HotSpotMonitorValue(object, slot, eliminated); + return new StackLockValue(object, slot, eliminated); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.*; /** * Common functionality of HotSpot host backends. @@ -40,12 +41,16 @@ public abstract class HotSpotHostBackend extends HotSpotBackend { /** - * Descriptor for {@link DeoptimizationStub#deoptimizationHandler}. + * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()} or + * {@link DeoptimizationStub#deoptimizationHandler} depending on + * {@link HotSpotBackend.Options#PreferGraalStubs}. */ - public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptimizationHandler", void.class); + public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptHandler", void.class); /** - * Descriptor for {@link UncommonTrapStub#uncommonTrapHandler}. + * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()} or + * {@link UncommonTrapStub#uncommonTrapHandler} depending on + * {@link HotSpotBackend.Options#PreferGraalStubs}. */ public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class); @@ -68,8 +73,8 @@ try (InitTimer st = timer("graphBuilderPlugins.initialize")) { GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); - GraphBuilderPlugins plugins = phase.getGraphBuilderPlugins(); - registerGraphBuilderPlugins(providers.getMetaAccess(), plugins); + InvocationPlugins plugins = phase.getGraphBuilderConfig().getInvocationPlugins(); + registerInvocationPlugins(providers, plugins); } try (InitTimer st = timer("foreignCalls.initialize")) { @@ -101,8 +106,8 @@ } } - protected void registerGraphBuilderPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - StandardGraphBuilderPlugins.registerPlugins(metaAccess, plugins); - HotSpotGraphBuilderPlugins.registerPlugins(metaAccess, plugins); + protected void registerInvocationPlugins(HotSpotProviders providers, InvocationPlugins plugins) { + StandardGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), plugins); + HotSpotGraphBuilderPlugins.registerInvocationPlugins(providers, plugins); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,12 +26,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandMode; /** - * Extends {@link LIRFrameState} to handle {@link HotSpotMonitorValue}s correctly. + * Extends {@link LIRFrameState} to handle {@link StackLockValue}s correctly. */ class HotSpotLIRFrameState extends LIRFrameState { @@ -41,8 +40,8 @@ @Override protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) { - if (value instanceof HotSpotMonitorValue) { - HotSpotMonitorValue monitor = (HotSpotMonitorValue) value; + if (value instanceof StackLockValue) { + StackLockValue monitor = (StackLockValue) value; if (monitor.getOwner() instanceof Value) { Value owner = (Value) monitor.getOwner(); if (processed(owner)) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Mar 02 19:11:22 2015 +0100 @@ -898,7 +898,6 @@ @HotSpotVMField(name = "Array::_length", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayLengthOffset; @HotSpotVMField(name = "Array::_data[0]", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int metaspaceArrayBaseOffset; - @HotSpotVMField(name = "InstanceKlass::_graal_node_class", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassNodeClassOffset; @HotSpotVMField(name = "InstanceKlass::_source_file_name_index", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassSourceFileNameIndexOffset; @HotSpotVMField(name = "InstanceKlass::_init_state", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassInitStateOffset; @HotSpotVMField(name = "InstanceKlass::_constants", type = "ConstantPool*", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassConstantsOffset; @@ -1346,6 +1345,9 @@ @HotSpotVMField(name = "CodeBlob::_code_offset", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable private int codeBlobCodeOffsetOffset; @HotSpotVMField(name = "SharedRuntime::_ic_miss_blob", type = "RuntimeStub*", get = HotSpotVMField.Type.VALUE) @Stable private long inlineCacheMissBlob; + @HotSpotVMValue(expression = "SharedRuntime::deopt_blob()->unpack()", get = HotSpotVMValue.Type.ADDRESS) @Stable public long handleDeoptStub; + @HotSpotVMValue(expression = "SharedRuntime::deopt_blob()->uncommon_trap()", get = HotSpotVMValue.Type.ADDRESS) @Stable public long uncommonTrapStub; + private final long inlineCacheMissStub; public long inlineCacheMissStub() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; @@ -387,13 +388,14 @@ private static final LocationIdentity COUNTER_LOCATION = NamedLocationIdentity.mutable("COUNTER_LOCATION"); @NodeInfo(nameTemplate = "CounterIndex") - private static class CounterIndexNode extends FloatingNode implements LIRLowerable { + private static final class CounterIndexNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CounterIndexNode.class); protected final Object counter; protected final int countersSize; protected CounterIndexNode(Stamp stamp, DynamicCounterNode counter, int countersSize) { - super(stamp); + super(TYPE, stamp); this.countersSize = countersSize; this.counter = counter; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -356,7 +356,7 @@ // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) int localsOffset = (graph.method().getMaxLocals() - 1) * 8; - for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) { + for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.TYPE)) { int size = osrLocal.getKind().getSlotCount(); int offset = localsOffset - (osrLocal.index() + size - 1) * 8; IndexedLocationNode location = graph.unique(new IndexedLocationNode(ANY_LOCATION, offset, ConstantNode.forLong(0, graph), 1)); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -169,14 +169,14 @@ } public static String tryDisassemble(String hcfEmbeddedString) { -// if (processMethod != null) { -// try { -// return (String) processMethod.invoke(null, hcfEmbeddedString); -// } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { -// // If the tool is available, for now let's be noisy when it fails -// throw new GraalInternalError(e); -// } -// } + if (processMethod != null) { + try { + return (String) processMethod.invoke(null, hcfEmbeddedString); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + // If the tool is available, for now let's be noisy when it fails + throw new GraalInternalError(e); + } + } return hcfEmbeddedString; } } @@ -259,8 +259,13 @@ HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false); installedCode = code; } - CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(hotspotMethod, compResult), installedCode, log); + HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult); + CodeInstallResult result = runtime.getCompilerToVM().installCode(compiledCode, installedCode, log); if (result != CodeInstallResult.OK) { + String msg = compiledCode.getInstallationFailureMessage(); + if (msg != null) { + throw new BailoutException(result != CodeInstallResult.DEPENDENCIES_FAILED, "Code installation failed: %s%n%s", result, msg); + } throw new BailoutException(result != CodeInstallResult.DEPENDENCIES_FAILED, "Code installation failed: %s", result); } return logOrDump(installedCode, compResult); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Mon Mar 02 19:11:22 2015 +0100 @@ -119,9 +119,13 @@ * Reference to the C++ ConstantPool object. */ private final long metaspaceConstantPool; + private final Object[] cache; + private ResolvedJavaType lastType; + private int lastTypeCpi = Integer.MIN_VALUE; public HotSpotConstantPool(long metaspaceConstantPool) { this.metaspaceConstantPool = metaspaceConstantPool; + cache = new Object[length()]; } /** @@ -453,10 +457,20 @@ @Override public JavaMethod lookupMethod(int cpi, int opcode) { + if (opcode != Bytecodes.INVOKEDYNAMIC) { + Object result = cache[cpi]; + if (result != null) { + return (ResolvedJavaMethod) result; + } + } final int index = toConstantPoolIndex(cpi, opcode); final long metaspaceMethod = runtime().getCompilerToVM().lookupMethodInPool(metaspaceConstantPool, index, (byte) opcode); if (metaspaceMethod != 0L) { - return HotSpotResolvedJavaMethodImpl.fromMetaspace(metaspaceMethod); + HotSpotResolvedJavaMethod result = HotSpotResolvedJavaMethodImpl.fromMetaspace(metaspaceMethod); + if (opcode != Bytecodes.INVOKEDYNAMIC) { + cache[cpi] = result; + } + return result; } else { // Get the method's name and signature. String name = getNameRefAt(index); @@ -475,12 +489,24 @@ @Override public JavaType lookupType(int cpi, int opcode) { + if (cpi == this.lastTypeCpi) { + return this.lastType; + } final long metaspacePointer = runtime().getCompilerToVM().lookupKlassInPool(metaspaceConstantPool, cpi); - return getJavaType(metaspacePointer); + JavaType result = getJavaType(metaspacePointer); + if (result instanceof ResolvedJavaType) { + this.lastType = (ResolvedJavaType) result; + this.lastTypeCpi = cpi; + } + return result; } @Override public JavaField lookupField(int cpi, int opcode) { + Object resolvedJavaField = cache[cpi]; + if (resolvedJavaField != null) { + return (ResolvedJavaField) resolvedJavaField; + } final int index = toConstantPoolIndex(cpi, opcode); final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index); final int nameIndex = getNameRefIndexAt(nameAndTypeIndex); @@ -507,7 +533,11 @@ HotSpotResolvedObjectTypeImpl resolvedHolder = HotSpotResolvedObjectTypeImpl.fromMetaspaceKlass(metaspaceKlass); final int flags = (int) info[0]; final long offset = info[1]; - return resolvedHolder.createField(name, type, offset, flags); + HotSpotResolvedJavaField result = resolvedHolder.createField(name, type, offset, flags); + if (type instanceof ResolvedJavaType) { + cache[cpi] = result; + } + return result; } else { return new HotSpotUnresolvedField(holder, name, type); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,28 +22,46 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.java.GraphBuilderContext.*; +import static java.lang.Character.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.hotspot.word.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.InvocationPlugins.Registration; +import com.oracle.graal.java.InvocationPlugins.Registration.Receiver; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.nodes.*; /** - * Provider of HotSpot specific {@link GraphBuilderPlugin}s. + * Provides HotSpot specific {@link InvocationPlugin}s. */ public class HotSpotGraphBuilderPlugins { - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - // Object.class + public static void registerInvocationPlugins(HotSpotProviders providers, InvocationPlugins plugins) { + MetaAccessProvider metaAccess = providers.getMetaAccess(); + SnippetReflectionProvider snippetReflection = providers.getSnippetReflection(); + Kind wordKind = providers.getCodeCache().getTarget().wordKind; + + registerObjectPlugins(plugins, metaAccess); + registerClassPlugins(plugins, metaAccess); + registerStableOptionPlugins(plugins, metaAccess); + registerMetaspacePointerPlugins(plugins, metaAccess, snippetReflection, wordKind); + } + + private static void registerObjectPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess) { Registration r = new Registration(plugins, metaAccess, Object.class); r.register1("getClass", Receiver.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { @@ -60,9 +78,10 @@ return true; } }); + } - // Class.class - r = new Registration(plugins, metaAccess, Class.class); + private static void registerClassPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess) { + Registration r = new Registration(plugins, metaAccess, Class.class); r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode rcvr, ValueNode object) { if (rcvr.isConstant() && !rcvr.isNullConstant()) { @@ -88,9 +107,10 @@ return false; } }); + } - // StableOptionValue.class - r = new Registration(plugins, metaAccess, StableOptionValue.class); + private static void registerStableOptionPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess) { + Registration r = new Registration(plugins, metaAccess, StableOptionValue.class); r.register1("getValue", Receiver.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { if (rcvr.isConstant() && !rcvr.isNullConstant()) { @@ -104,4 +124,130 @@ } }); } + + private static void registerMetaspacePointerPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, Kind wordKind) { + Registration r = new Registration(plugins, metaAccess, MetaspacePointer.class); + r.register1("isNull", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode pointer) { + assert pointer.stamp() instanceof MetaspacePointerStamp; + IsNullNode isNull = builder.append(new IsNullNode(pointer)); + ConstantNode trueValue = builder.append(ConstantNode.forBoolean(true)); + ConstantNode falseValue = builder.append(ConstantNode.forBoolean(false)); + builder.push(Kind.Boolean.getStackKind(), builder.append(new ConditionalNode(isNull, trueValue, falseValue))); + return true; + } + }); + r.register1("asWord", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode pointer) { + builder.append(new PointerCastNode(StampFactory.forKind(wordKind), pointer)); + return true; + } + }); + r.register2("readObject", Receiver.class, int.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, int.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, int.class, BarrierType.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register2("readObject", Receiver.class, WordBase.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, WordBase.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + r.register3("readObject", Receiver.class, WordBase.class, BarrierType.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); + + registerWordOpPlugins(r, snippetReflection, wordKind, Kind.Byte, Kind.Short, Kind.Char, Kind.Int, Kind.Float, Kind.Long, Kind.Double); + } + + private static void registerWordOpPlugins(Registration r, SnippetReflectionProvider snippetReflection, Kind wordKind, Kind... kinds) { + for (Kind kind : kinds) { + String kindName = kind.getJavaName(); + kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); + String getName = "read" + kindName; + // String putName = "write" + kindName; + r.register2(getName, Receiver.class, int.class, new ReadOp(snippetReflection, wordKind, kind)); + r.register3(getName, Receiver.class, int.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, kind)); + } + } + + static class ReadOp implements InvocationPlugin { + final SnippetReflectionProvider snippetReflection; + final Kind wordKind; + final Kind resultKind; + final BarrierType barrierType; + final boolean compressible; + + public ReadOp(SnippetReflectionProvider snippetReflection, Kind wordKind, Kind resultKind, BarrierType barrierType, boolean compressible) { + this.snippetReflection = snippetReflection; + this.wordKind = wordKind; + this.resultKind = resultKind; + this.barrierType = barrierType; + this.compressible = compressible; + } + + public ReadOp(SnippetReflectionProvider snippetReflection, Kind wordKind, Kind resultKind) { + this(snippetReflection, wordKind, resultKind, BarrierType.NONE, false); + } + + public boolean apply(GraphBuilderContext builder, ValueNode pointer, ValueNode offset) { + LocationNode location = makeLocation(builder, offset, ANY_LOCATION, wordKind); + builder.push(resultKind, builder.append(readOp(builder, resultKind, pointer, location, barrierType, compressible))); + return true; + } + + public boolean apply(GraphBuilderContext builder, ValueNode pointer, ValueNode offset, ValueNode locationIdentityArg) { + assert locationIdentityArg.isConstant(); + LocationIdentity locationIdentity = snippetReflection.asObject(LocationIdentity.class, locationIdentityArg.asJavaConstant()); + LocationNode location = makeLocation(builder, offset, locationIdentity, wordKind); + builder.push(resultKind, builder.append(readOp(builder, resultKind, pointer, location, barrierType, compressible))); + return true; + } + } + + public static ValueNode readOp(GraphBuilderContext builder, Kind readKind, ValueNode base, LocationNode location, BarrierType barrierType, boolean compressible) { + JavaReadNode read = builder.append(new JavaReadNode(readKind, base, location, barrierType, compressible)); + /* + * The read must not float outside its block otherwise it may float above an explicit zero + * check on its base address. + */ + read.setGuard(builder.getCurrentBlockGuard()); + return read; + } + + public static LocationNode makeLocation(GraphBuilderContext builder, ValueNode offset, LocationIdentity locationIdentity, Kind wordKind) { + return builder.append(new IndexedLocationNode(locationIdentity, 0, fromSigned(builder, offset, wordKind), 1)); + } + + public static LocationNode makeLocation(GraphBuilderContext builder, ValueNode offset, ValueNode locationIdentity, Kind wordKind) { + if (locationIdentity.isConstant()) { + return makeLocation(builder, offset, builder.getSnippetReflection().asObject(LocationIdentity.class, locationIdentity.asJavaConstant()), wordKind); + } + return builder.append(new SnippetLocationNode(builder.getSnippetReflection(), locationIdentity, builder.append(ConstantNode.forLong(0)), fromSigned(builder, offset, wordKind), + builder.append(ConstantNode.forInt(1)))); + } + + public static ValueNode fromUnsigned(GraphBuilderContext builder, ValueNode value, Kind wordKind) { + return convert(builder, value, wordKind, true); + } + + public static ValueNode fromSigned(GraphBuilderContext builder, ValueNode value, Kind wordKind) { + return convert(builder, value, wordKind, false); + } + + public static ValueNode toUnsigned(GraphBuilderContext builder, ValueNode value, Kind toKind) { + return convert(builder, value, toKind, true); + } + + public static ValueNode convert(GraphBuilderContext builder, ValueNode value, Kind toKind, boolean unsigned) { + if (value.getKind() == toKind) { + return value; + } + + if (toKind == Kind.Int) { + assert value.getKind() == Kind.Long; + return builder.append(new NarrowNode(value, 32)); + } else { + assert toKind == Kind.Long; + assert value.getKind().getStackKind() == Kind.Int; + if (unsigned) { + return builder.append(new ZeroExtendNode(value, 64)); + } else { + return builder.append(new SignExtendNode(value, 64)); + } + } + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,8 +25,10 @@ import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotBackend.Options.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; +import static com.oracle.graal.hotspot.HotSpotHostBackend.*; 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.*; @@ -138,6 +140,10 @@ public void initialize(HotSpotProviders providers, HotSpotVMConfig c) { TargetDescription target = providers.getCodeCache().getTarget(); + if (!PreferGraalStubs.getValue()) { + registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + } registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub(), NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMemoryAccessProviderImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMemoryAccessProviderImpl.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMemoryAccessProviderImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; @@ -107,8 +106,6 @@ assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror(); } else if (displacement == runtime.getConfig().arrayKlassComponentMirrorOffset) { assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror().getComponentType(); - } else if (displacement == runtime.getConfig().instanceKlassNodeClassOffset) { - assert expected == NodeClass.get(((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror()); } } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; /** @@ -70,12 +69,9 @@ } public static Tag getEnum(int value) { - for (Tag e : values()) { - if (e.value == value) { - return e; - } - } - throw GraalInternalError.shouldNotReachHere("unknown enum value " + value); + Tag result = values()[value]; + assert value == result.value; + return result; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * 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.hotspot.meta; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; - -/** - * Represents lock information in the debug information. - */ -public final class HotSpotMonitorValue extends AbstractValue implements JavaValue { - - private static final long serialVersionUID = 8241681800464483691L; - - private JavaValue owner; - private StackSlotValue slot; - private final boolean eliminated; - - public HotSpotMonitorValue(JavaValue owner, StackSlotValue slot, boolean eliminated) { - super(LIRKind.Illegal); - this.owner = owner; - this.slot = slot; - this.eliminated = eliminated; - } - - public JavaValue getOwner() { - return owner; - } - - public void setOwner(JavaValue newOwner) { - this.owner = newOwner; - } - - public Value getSlot() { - return slot; - } - - public boolean isEliminated() { - return eliminated; - } - - @Override - public String toString() { - return "monitor[" + owner + (slot != null ? ", " + slot : "") + (eliminated ? ", eliminated" : "") + "]"; - } - - @Override - public int hashCode() { - final int prime = 43; - int result = super.hashCode(); - result = prime * result + (eliminated ? 1231 : 1237); - result = prime * result + owner.hashCode(); - result = prime * result + slot.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof HotSpotMonitorValue) { - HotSpotMonitorValue other = (HotSpotMonitorValue) obj; - return super.equals(obj) && eliminated == other.eliminated && owner.equals(other.owner) && slot.equals(other.slot); - } - return false; - } - - public void setSlot(StackSlotValue stackSlot) { - assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot); - slot = stackSlot; - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; /** @@ -62,14 +61,6 @@ int getIdentityHashCode(); /** - * Gets the result of {@link NodeClass#get(Class)} for the {@link Class} object represented by - * this constant. - * - * @return {@code null} if this constant does not represent a {@link Class} object - */ - JavaConstant getNodeClass(); - - /** * Gets the result of {@link Class#getComponentType()} for the {@link Class} object represented * by this constant. * @@ -96,7 +87,7 @@ JavaConstant getCallSiteTarget(Assumptions assumptions); /** - * Gets the result of {@link CompositeValueClass#get(Class)} for the {@link Class} object + * Gets the result of {@link CompositeValueClass#create(Class)} for the {@link Class} object * represented by this constant. * * @return {@code null} if this constant does not represent a {@link Class} object diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; @@ -157,13 +156,6 @@ return System.identityHashCode(object); } - public JavaConstant getNodeClass() { - if (object instanceof Class) { - return HotSpotObjectConstantImpl.forObject(NodeClass.get((Class) object)); - } - return null; - } - public JavaConstant getComponentType() { if (object instanceof Class) { return HotSpotObjectConstantImpl.forObject(((Class) object).getComponentType()); @@ -198,7 +190,7 @@ if (object instanceof Class) { Class c = (Class) object; assert CompositeValue.class.isAssignableFrom(c) : c; - return HotSpotObjectConstantImpl.forObject(CompositeValueClass.get(c)); + return HotSpotObjectConstantImpl.forObject(CompositeValueClass.create(c)); } return null; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -511,7 +511,9 @@ int count = sig.getParameterCount(false); Class[] result = new Class[count]; for (int i = 0; i < result.length; ++i) { - result[i] = ((HotSpotResolvedJavaType) sig.getParameterType(i, holder).resolve(holder)).mirror(); + JavaType parameterType = sig.getParameterType(i, holder); + HotSpotResolvedJavaType resolvedParameterType = (HotSpotResolvedJavaType) parameterType.resolve(holder); + result[i] = resolvedParameterType.mirror(); } return result; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Mon Mar 02 19:11:22 2015 +0100 @@ -118,13 +118,11 @@ return Kind.fromTypeString(parameters.get(index)); } - private static boolean checkValidCache(JavaType type, ResolvedJavaType accessingClass) { + private static boolean checkValidCache(ResolvedJavaType type, ResolvedJavaType accessingClass) { assert accessingClass != null; - if (!(type instanceof ResolvedJavaType)) { + if (type == null) { return false; - } - - if (type instanceof HotSpotResolvedObjectTypeImpl) { + } else if (type instanceof HotSpotResolvedObjectTypeImpl) { return ((HotSpotResolvedObjectTypeImpl) type).isDefinitelyResolvedWithRespectTo(accessingClass); } return true; @@ -151,8 +149,13 @@ ResolvedJavaType type = parameterTypes[index]; if (!checkValidCache(type, accessingClass)) { - type = (ResolvedJavaType) runtime.lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, false); - parameterTypes[index] = type; + JavaType result = runtime.lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, false); + if (result instanceof ResolvedJavaType) { + type = (ResolvedJavaType) result; + parameterTypes[index] = type; + } else { + return result; + } } return type; } @@ -176,7 +179,12 @@ return getUnresolvedOrPrimitiveType(runtime, returnType); } if (!checkValidCache(returnTypeCache, accessingClass)) { - returnTypeCache = (ResolvedJavaType) runtime.lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, false); + JavaType result = runtime.lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, false); + if (result instanceof ResolvedJavaType) { + returnTypeCache = (ResolvedJavaType) result; + } else { + return result; + } } return returnTypeCache; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,21 +22,31 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.replacements.NodeIntrinsificationPhase.*; + +import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; -import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.AnnotatedInvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; import com.oracle.graal.lir.phases.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.options.DerivedOptionValue.OptionSupplier; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.replacements.*; /** * HotSpot implementation of {@link SuitesProvider}. @@ -68,9 +78,9 @@ } - public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime) { + public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { this.runtime = runtime; - this.defaultGraphBuilderSuite = createGraphBuilderSuite(); + this.defaultGraphBuilderSuite = createGraphBuilderSuite(metaAccess, constantReflection, replacements); this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); } @@ -102,15 +112,95 @@ return ret; } - protected PhaseSuite createGraphBuilderSuite() { + NodeIntrinsificationPhase intrinsifier; + + NodeIntrinsificationPhase getIntrinsifier() { + if (intrinsifier == null) { + HotSpotProviders providers = runtime.getHostProviders(); + intrinsifier = new NodeIntrinsificationPhase(providers, providers.getSnippetReflection()); + } + return intrinsifier; + } + + MetaAccessProvider getMetaAccess() { + return runtime.getHostProviders().getMetaAccess(); + } + + protected PhaseSuite createGraphBuilderSuite(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { PhaseSuite suite = new PhaseSuite<>(); GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); - config.setInlineInvokePlugin(new InlineInvokePlugin() { - public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) { - return GraalOptions.InlineDuringParsing.getValue() && method.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && - depth < GraalOptions.InlineDuringParsingMaxDepth.getValue(); - } - }); + if (InlineDuringParsing.getValue()) { + config.setLoadFieldPlugin(new LoadFieldPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { + if (receiver.isConstant()) { + JavaConstant asJavaConstant = receiver.asJavaConstant(); + return tryConstantFold(builder, metaAccess, constantReflection, field, asJavaConstant); + } + return false; + } + + public boolean apply(GraphBuilderContext builder, ResolvedJavaField staticField) { + return tryConstantFold(builder, metaAccess, constantReflection, staticField, null); + } + }); + config.setInlineInvokePlugin(new InlineInvokePlugin() { + public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType, int depth) { + ResolvedJavaMethod subst = replacements.getMethodSubstitutionMethod(method); + if (subst != null) { + return subst; + } + if (builder.parsingReplacement() && method.getAnnotation(NodeIntrinsic.class) == null) { + return method; + } + if (method.hasBytecodes() && method.getCode().length <= TrivialInliningSize.getValue() && depth < InlineDuringParsingMaxDepth.getValue()) { + return method; + } + return null; + } + }); + config.setAnnotatedInvocationPlugin(new AnnotatedInvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args) { + if (builder.parsingReplacement()) { + @SuppressWarnings("hiding") + NodeIntrinsificationPhase intrinsifier = getIntrinsifier(); + NodeIntrinsic intrinsic = intrinsifier.getIntrinsic(method); + if (intrinsic != null) { + Signature sig = method.getSignature(); + Kind returnKind = sig.getReturnKind(); + Stamp stamp = StampFactory.forKind(returnKind); + if (returnKind == Kind.Object) { + JavaType returnType = sig.getReturnType(method.getDeclaringClass()); + if (returnType instanceof ResolvedJavaType) { + stamp = StampFactory.declared((ResolvedJavaType) returnType); + } + } + + ValueNode res = intrinsifier.createIntrinsicNode(Arrays.asList(args), stamp, method, builder.getGraph(), intrinsic); + res = builder.append(res); + if (res.getKind().getStackKind() != Kind.Void) { + builder.push(returnKind.getStackKind(), res); + } + return true; + } else if (intrinsifier.isFoldable(method)) { + ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); + JavaConstant constant = intrinsifier.tryFold(Arrays.asList(args), parameterTypes, method); + if (!COULD_NOT_FOLD.equals(constant)) { + if (constant != null) { + // Replace the invoke with the result of the call + ConstantNode res = builder.append(ConstantNode.forConstant(constant, getMetaAccess())); + builder.push(res.getKind().getStackKind(), builder.append(res)); + } else { + // This must be a void invoke + assert method.getSignature().getReturnKind() == Kind.Void; + } + return true; + } + } + } + return false; + } + }); + } suite.appendPhase(new GraphBuilderPhase(config)); return suite; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -38,6 +39,7 @@ @NodeInfo public final class AllocaNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AllocaNode.class); /** * The number of slots in block. */ @@ -51,7 +53,7 @@ protected final BitSet objects; public AllocaNode(int slots, Kind wordKind, BitSet objects) { - super(StampFactory.forKind(wordKind)); + super(TYPE, StampFactory.forKind(wordKind)); this.slots = slots; this.objects = objects; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,17 +22,19 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo public abstract class ArrayRangeWriteBarrier extends WriteBarrier { + public static final NodeClass TYPE = NodeClass.create(ArrayRangeWriteBarrier.class); @Input ValueNode startIndex; @Input ValueNode length; - public ArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, null, null, true); + protected ArrayRangeWriteBarrier(NodeClass c, ValueNode object, ValueNode startIndex, ValueNode length) { + super(c, object, null, null, true); this.startIndex = startIndex; this.length = length; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -40,10 +41,11 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(BeginLockScopeNode.class); protected int lockDepth; public BeginLockScopeNode(int lockDepth) { - super(null); + super(TYPE, null); this.lockDepth = lockDepth; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -34,10 +35,11 @@ @NodeInfo public final class CStringNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CStringNode.class); protected final String string; public CStringNode(String string) { - super(null); + super(TYPE, null); this.string = string; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodeinfo.*; @@ -38,8 +39,10 @@ @NodeInfo public final class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary { + public static final NodeClass TYPE = NodeClass.create(ClassCastNode.class); + public ClassCastNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,8 +40,10 @@ @NodeInfo public final class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(ClassGetClassLoader0Node.class); + public ClassGetClassLoader0Node(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +39,10 @@ @NodeInfo public final class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(ClassGetComponentTypeNode.class); + public ClassGetComponentTypeNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,9 +37,10 @@ */ @NodeInfo public final class ClassGetModifiersNode extends MacroNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(ClassGetModifiersNode.class); public ClassGetModifiersNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +39,10 @@ @NodeInfo public final class ClassGetSuperclassNode extends MacroNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(ClassGetSuperclassNode.class); + public ClassGetSuperclassNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +38,10 @@ @NodeInfo public final class ClassIsArrayNode extends MacroNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(ClassIsArrayNode.class); + public ClassIsArrayNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +38,10 @@ @NodeInfo public final class ClassIsInterfaceNode extends MacroNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(ClassIsInterfaceNode.class); + public ClassIsInterfaceNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +38,10 @@ @NodeInfo public final class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(ClassIsPrimitiveNode.class); + public ClassIsPrimitiveNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getJavaClass() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; @@ -42,6 +43,8 @@ @NodeInfo(nameTemplate = "{p#op/s}") public final class CompressionNode extends UnaryNode implements ConvertNode, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CompressionNode.class); + public enum CompressionOp { Compress, Uncompress @@ -51,7 +54,7 @@ protected final CompressEncoding encoding; public CompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) { - super(mkStamp(op, input.stamp(), encoding), input); + super(TYPE, mkStamp(op, input.stamp(), encoding), input); this.op = op; this.encoding = encoding; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,6 +28,7 @@ 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.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; @@ -39,11 +40,12 @@ */ @NodeInfo public final class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CurrentJavaThreadNode.class); protected LIRKind wordKind; public CurrentJavaThreadNode(Kind kind) { - super(StampFactory.forKind(kind)); + super(TYPE, StampFactory.forKind(kind)); this.wordKind = LIRKind.value(kind); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -35,11 +36,12 @@ */ @NodeInfo public final class CurrentLockNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CurrentLockNode.class); protected int lockDepth; public CurrentLockNode(int lockDepth) { - super(null); + super(TYPE, null); this.lockDepth = lockDepth; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ 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.hotspot.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodeinfo.*; @@ -41,11 +42,12 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public final class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { + public static final NodeClass TYPE = NodeClass.create(DeoptimizationFetchUnrollInfoCallNode.class); @Input SaveAllRegistersNode registerSaver; protected final ForeignCallsProvider foreignCalls; public DeoptimizationFetchUnrollInfoCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver) { - super(StampFactory.forKind(Kind.fromJavaClass(FETCH_UNROLL_INFO.getResultType()))); + super(TYPE, StampFactory.forKind(Kind.fromJavaClass(FETCH_UNROLL_INFO.getResultType()))); this.registerSaver = (SaveAllRegistersNode) registerSaver; this.foreignCalls = foreignCalls; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -35,11 +36,12 @@ @NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}") public final class DeoptimizeCallerNode extends ControlSinkNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(DeoptimizeCallerNode.class); protected final DeoptimizationAction action; protected final DeoptimizationReason reason; public DeoptimizeCallerNode(DeoptimizationAction action, DeoptimizationReason reason) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.action = action; this.reason = reason; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,14 +23,17 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo -public class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode { +public abstract class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode { - public DeoptimizingStubCall(Stamp stamp) { - super(stamp); + public static final NodeClass TYPE = NodeClass.create(DeoptimizingStubCall.class); + + public DeoptimizingStubCall(NodeClass c, Stamp stamp) { + super(c, stamp); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -41,10 +42,11 @@ @NodeInfo public final class DimensionsNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(DimensionsNode.class); protected final int rank; public DimensionsNode(int rank) { - super(null); + super(TYPE, null); this.rank = rank; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -40,6 +41,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public final class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(DirectCompareAndSwapNode.class); @Input ValueNode object; @Input ValueNode offset; @Input ValueNode expectedValue; @@ -48,7 +50,7 @@ protected final LocationIdentity locationIdentity; public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) { - super(expected.stamp()); + super(TYPE, expected.stamp()); this.object = object; this.offset = offset; this.expectedValue = expected; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -34,10 +35,11 @@ * object. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single { +public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(EndLockScopeNode.class); public EndLockScopeNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodeinfo.*; @@ -36,7 +37,8 @@ * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. */ @NodeInfo -public class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { +public final class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(EnterUnpackFramesStackFrameNode.class); @Input ValueNode framePc; @Input ValueNode senderSp; @@ -44,7 +46,7 @@ @Input SaveAllRegistersNode registerSaver; public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.framePc = framePc; this.senderSp = senderSp; this.senderFp = senderFp; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,14 +22,16 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { + public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePostWriteBarrier.class); public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, startIndex, length); + super(TYPE, object, startIndex, length); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,14 +22,16 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { + public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePreWriteBarrier.class); public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, startIndex, length); + super(TYPE, object, startIndex, length); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -29,10 +30,15 @@ @NodeInfo public class G1PostWriteBarrier extends WriteBarrier { + public static final NodeClass TYPE = NodeClass.create(G1PostWriteBarrier.class); protected final boolean alwaysNull; public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) { - super(object, value, location, precise); + this(TYPE, object, value, location, precise, alwaysNull); + } + + protected G1PostWriteBarrier(NodeClass c, ValueNode object, ValueNode value, LocationNode location, boolean precise, boolean alwaysNull) { + super(c, object, value, location, precise); this.alwaysNull = alwaysNull; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -29,12 +30,14 @@ @NodeInfo public final class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore { + public static final NodeClass TYPE = NodeClass.create(G1PreWriteBarrier.class); + @OptionalInput(InputType.State) FrameState stateBefore; protected final boolean nullCheck; protected final boolean doLoad; public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { - super(object, expectedObject, location, true); + super(TYPE, object, expectedObject, location, true); this.doLoad = doLoad; this.nullCheck = nullCheck; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -34,11 +35,12 @@ */ @NodeInfo public final class G1ReferentFieldReadBarrier extends WriteBarrier { + public static final NodeClass TYPE = NodeClass.create(G1ReferentFieldReadBarrier.class); protected final boolean doLoad; public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) { - super(object, expectedObject, location, true); + super(TYPE, object, expectedObject, location, true); this.doLoad = doLoad; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,11 +36,12 @@ */ @NodeInfo public final class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(GetObjectAddressNode.class); @Input ValueNode object; public GetObjectAddressNode(ValueNode obj) { - super(StampFactory.forKind(Kind.Long)); + super(TYPE, StampFactory.forKind(Kind.Long)); this.object = obj; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,13 +27,16 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo -public class HotSpotDirectCallTargetNode extends DirectCallTargetNode { +public final class HotSpotDirectCallTargetNode extends DirectCallTargetNode { + public static final NodeClass TYPE = NodeClass.create(HotSpotDirectCallTargetNode.class); + public HotSpotDirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { - super(arguments, returnStamp, signature, target, callType, invokeKind); + super(TYPE, arguments, returnStamp, signature, target, callType, invokeKind); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,17 +27,19 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo public final class HotSpotIndirectCallTargetNode extends IndirectCallTargetNode { + public static final NodeClass TYPE = NodeClass.create(HotSpotIndirectCallTargetNode.class); @Input ValueNode metaspaceMethod; public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { - super(computedAddress, arguments, returnStamp, signature, target, callType, invokeKind); + super(TYPE, computedAddress, arguments, returnStamp, signature, target, callType, invokeKind); this.metaspaceMethod = metaspaceMethod; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,14 +35,15 @@ * exception handler in the caller's frame, removes the current frame and jumps to said handler. */ @NodeInfo -public class JumpToExceptionHandlerInCallerNode extends ControlSinkNode implements LIRLowerable { +public final class JumpToExceptionHandlerInCallerNode extends ControlSinkNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(JumpToExceptionHandlerInCallerNode.class); @Input ValueNode handlerInCallerPc; @Input ValueNode exception; @Input ValueNode exceptionPc; public JumpToExceptionHandlerInCallerNode(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.handlerInCallerPc = handlerInCallerPc; this.exception = exception; this.exceptionPc = exceptionPc; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodeinfo.*; @@ -34,12 +35,13 @@ * return address if its location is on the stack. */ @NodeInfo -public class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { +public final class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(LeaveCurrentStackFrameNode.class); @Input SaveAllRegistersNode registerSaver; public LeaveCurrentStackFrameNode(ValueNode registerSaver) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.registerSaver = (SaveAllRegistersNode) registerSaver; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodeinfo.*; @@ -36,13 +37,14 @@ * is only used in {@link DeoptimizationStub}. */ @NodeInfo -public class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { +public final class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(LeaveDeoptimizedStackFrameNode.class); @Input ValueNode frameSize; @Input ValueNode initialInfo; public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.frameSize = frameSize; this.initialInfo = initialInfo; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodeinfo.*; @@ -34,12 +35,13 @@ * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. */ @NodeInfo -public class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { +public final class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(LeaveUnpackFramesStackFrameNode.class); @Input SaveAllRegistersNode registerSaver; public LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.registerSaver = (SaveAllRegistersNode) registerSaver; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadIndexedPointerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadIndexedPointerNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadIndexedPointerNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -31,8 +32,10 @@ @NodeInfo public final class LoadIndexedPointerNode extends LoadIndexedNode { + public static final NodeClass TYPE = NodeClass.create(LoadIndexedPointerNode.class); + public LoadIndexedPointerNode(Stamp stamp, ValueNode array, ValueNode index) { - super(stamp, array, index, Kind.Illegal); + super(TYPE, stamp, array, index, Kind.Illegal); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -36,9 +37,10 @@ */ @NodeInfo public final class MonitorCounterNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(MonitorCounterNode.class); public MonitorCounterNode() { - super(null); + super(TYPE, null); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.hotspot.word.*; @@ -40,13 +41,14 @@ @NodeInfo public final class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(NewArrayStubCall.class); private static final Stamp defaultStamp = StampFactory.objectNonNull(); @Input ValueNode hub; @Input ValueNode length; public NewArrayStubCall(ValueNode hub, ValueNode length) { - super(defaultStamp); + super(TYPE, defaultStamp); this.hub = hub; this.length = length; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +27,7 @@ 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.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.hotspot.word.*; @@ -40,12 +41,13 @@ @NodeInfo public final class NewInstanceStubCall extends DeoptimizingStubCall implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(NewInstanceStubCall.class); private static final Stamp defaultStamp = StampFactory.objectNonNull(); @Input ValueNode hub; public NewInstanceStubCall(ValueNode hub) { - super(defaultStamp); + super(TYPE, defaultStamp); this.hub = hub; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +27,7 @@ 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.hotspot.meta.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -40,6 +41,7 @@ @NodeInfo public final class NewMultiArrayStubCall extends ForeignCallNode { + public static final NodeClass TYPE = NodeClass.create(NewMultiArrayStubCall.class); private static final Stamp defaultStamp = StampFactory.objectNonNull(); @Input ValueNode hub; @@ -47,7 +49,7 @@ protected final int rank; public NewMultiArrayStubCall(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) { - super(foreignCalls, NEW_MULTI_ARRAY, defaultStamp); + super(TYPE, foreignCalls, NEW_MULTI_ARRAY, defaultStamp); this.hub = hub; this.rank = rank; this.dims = dims; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -33,12 +34,13 @@ * Modifies the return address of the current frame. */ @NodeInfo -public class PatchReturnAddressNode extends FixedWithNextNode implements LIRLowerable { +public final class PatchReturnAddressNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(PatchReturnAddressNode.class); @Input ValueNode address; public PatchReturnAddressNode(ValueNode address) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.address = address; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -31,13 +32,14 @@ import com.oracle.graal.word.*; @NodeInfo -public class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable { +public final class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(PrefetchAllocateNode.class); @Input ValueNode distance; @Input ValueNode address; public PrefetchAllocateNode(ValueNode address, ValueNode distance) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.address = address; this.distance = distance; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,15 +35,16 @@ * A call to the runtime code implementing the uncommon trap logic. */ @NodeInfo -public class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { +public final class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(PushInterpreterFrameNode.class); @Input ValueNode framePc; @Input ValueNode frameSize; @Input ValueNode senderSp; @Input ValueNode initialInfo; public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.frameSize = frameSize; this.framePc = framePc; this.senderSp = senderSp; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodeinfo.*; @@ -35,12 +36,13 @@ * Saves all allocatable registers. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { +public final class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(SaveAllRegistersNode.class); protected SaveRegistersOp saveRegistersOp; public SaveAllRegistersNode() { - super(StampFactory.forKind(Kind.Long)); + super(TYPE, StampFactory.forKind(Kind.Long)); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,14 +22,17 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo -public class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { +public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { + + public static final NodeClass TYPE = NodeClass.create(SerialArrayRangeWriteBarrier.class); public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, startIndex, length); + super(TYPE, object, startIndex, length); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -29,10 +30,15 @@ @NodeInfo public class SerialWriteBarrier extends WriteBarrier { + public static final NodeClass TYPE = NodeClass.create(SerialWriteBarrier.class); protected final boolean alwaysNull; public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) { - super(object, null, location, precise); + this(TYPE, object, location, precise, alwaysNull); + } + + protected SerialWriteBarrier(NodeClass c, ValueNode object, LocationNode location, boolean precise, boolean alwaysNull) { + super(c, object, null, location, precise); this.alwaysNull = alwaysNull; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +23,18 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Anchor, InputType.Guard}) -public class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode { +public final class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(SnippetAnchorNode.class); public SnippetAnchorNode() { - super(StampFactory.object()); + super(TYPE, StampFactory.object()); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +31,13 @@ import com.oracle.graal.nodes.extended.*; @NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value}) -public class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable { +public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(SnippetLocationProxyNode.class); @Input(InputType.Unchecked) ValueNode location; public SnippetLocationProxyNode(ValueNode location) { - super(StampFactory.object()); + super(TYPE, StampFactory.object()); this.location = location; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,15 +38,16 @@ * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub. */ @NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}", allowedUsageTypes = {InputType.Memory}) -public class StubForeignCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { +public final class StubForeignCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { + public static final NodeClass TYPE = NodeClass.create(StubForeignCallNode.class); @Input NodeInputList arguments; protected final ForeignCallsProvider foreignCalls; protected final ForeignCallDescriptor descriptor; public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { - super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); + super(TYPE, StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -30,11 +31,13 @@ * Start node for a {@link Stub}'s graph. */ @NodeInfo -public class StubStartNode extends StartNode { +public final class StubStartNode extends StartNode { + public static final NodeClass TYPE = NodeClass.create(StubStartNode.class); protected final Stub stub; public StubStartNode(Stub stub) { + super(TYPE); this.stub = stub; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ 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.hotspot.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodeinfo.*; @@ -39,14 +40,15 @@ * A call to the runtime code implementing the uncommon trap logic. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { +public final class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { + public static final NodeClass TYPE = NodeClass.create(UncommonTrapCallNode.class); @Input ValueNode trapRequest; @Input SaveAllRegistersNode registerSaver; protected final ForeignCallsProvider foreignCalls; public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) { - super(StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); + super(TYPE, StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); this.trapRequest = trapRequest; this.registerSaver = (SaveAllRegistersNode) registerSaver; this.foreignCalls = foreignCalls; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +28,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -38,13 +39,14 @@ * {@linkplain Log#printf(String, long) formatted} error message specified. */ @NodeInfo -public class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable { +public final class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(VMErrorNode.class); protected final String format; @Input ValueNode value; public VMErrorNode(String format, ValueNode value) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.format = format; this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -31,13 +32,14 @@ @NodeInfo public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(WriteBarrier.class); @Input protected ValueNode object; @OptionalInput protected ValueNode value; @OptionalInput(InputType.Association) protected LocationNode location; protected final boolean precise; - public WriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { - super(StampFactory.forVoid()); + protected WriteBarrier(NodeClass c, ValueNode object, ValueNode value, LocationNode location, boolean precise) { + super(c, StampFactory.forVoid()); this.object = object; this.value = value; this.location = location; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -49,7 +49,7 @@ Debug.dump(graph, "OnStackReplacement initial"); EntryMarkerNode osr; do { - NodeIterable osrNodes = graph.getNodes(EntryMarkerNode.class); + NodeIterable osrNodes = graph.getNodes(EntryMarkerNode.TYPE); osr = osrNodes.first(); if (osr == null) { throw new BailoutException("No OnStackReplacementNode generated"); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,8 +34,10 @@ @NodeInfo public final class CallSiteTargetNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { + public static final NodeClass TYPE = NodeClass.create(CallSiteTargetNode.class); + public CallSiteTargetNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private ValueNode getCallSite() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableAddressNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableAddressNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableAddressNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.calc.*; @@ -31,9 +32,10 @@ @NodeInfo public final class CardTableAddressNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CardTableAddressNode.class); public CardTableAddressNode() { - super(StampFactory.forKind(Kind.Long)); + super(TYPE, StampFactory.forKind(Kind.Long)); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableShiftNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableShiftNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableShiftNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.calc.*; @@ -31,9 +32,10 @@ @NodeInfo public final class CardTableShiftNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CardTableShiftNode.class); public CardTableShiftNode() { - super(StampFactory.intValue()); + super(TYPE, StampFactory.intValue()); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -43,6 +43,7 @@ */ @NodeInfo public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { + public static final NodeClass TYPE = NodeClass.create(ClassGetHubNode.class); @Input protected ValueNode clazz; public ClassGetHubNode(ValueNode clazz) { @@ -50,7 +51,7 @@ } public ClassGetHubNode(ValueNode clazz, ValueNode guard) { - super(KlassPointerStamp.klass(), (GuardingNode) guard); + super(TYPE, KlassPointerStamp.klass(), (GuardingNode) guard); this.clazz = clazz; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * 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.hotspot.replacements; - -import static com.oracle.graal.compiler.common.GraalOptions.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * Substitutions for improving the performance of {@link CompositeValueClass#getClass()}. - */ -@ClassSubstitution(CompositeValueClass.class) -public class CompositeValueClassSubstitutions { - - /** - * A macro node for calls to {@link CompositeValueClass#get(Class)}. It can use the compiler's - * knowledge about node classes to replace itself with a constant value for a constant - * {@link Class} parameter. - */ - @NodeInfo - public static final class CompositeValueClassGetNode extends PureFunctionMacroNode { - - public CompositeValueClassGetNode(Invoke invoke) { - super(invoke); - } - - @Override - protected JavaConstant evaluate(JavaConstant param, MetaAccessProvider metaAccess) { - if (param.isNull() || ImmutableCode.getValue()) { - return null; - } - HotSpotObjectConstant c = (HotSpotObjectConstant) param; - return c.getCompositeValueClass(); - } - } - - @MacroSubstitution(isStatic = true, forced = true, macro = CompositeValueClassGetNode.class) - private static native CompositeValueClass get(Class c); -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * 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.hotspot.replacements; - -import static com.oracle.graal.compiler.common.GraalOptions.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * Substitutions for improving the performance of {@link NodeClass#get}. - */ -@ClassSubstitution(NodeClass.class) -public class HotSpotNodeClassSubstitutions { - - /** - * A macro node for calls to {@link NodeClass#get(Class)}. It can use the compiler's knowledge - * about node classes to replace itself with a constant value for a constant {@link Class} - * parameter. - */ - @NodeInfo - public static class NodeClassGetNode extends PureFunctionMacroNode { - - public NodeClassGetNode(Invoke invoke) { - super(invoke); - } - - @Override - protected JavaConstant evaluate(JavaConstant param, MetaAccessProvider metaAccess) { - if (param.isNull() || ImmutableCode.getValue()) { - return null; - } - HotSpotObjectConstant c = (HotSpotObjectConstant) param; - return c.getNodeClass(); - } - } - - /** - * NOTE: A {@link MethodSubstitution} similar to - * {@link HotSpotNodeSubstitutions#getNodeClass(Node)} is not possible here because there is no - * guarantee that {@code c} is initialized (accessing a Class literal in Java is not a class - * initialization barrier). - */ - @MacroSubstitution(isStatic = true, forced = true, macro = NodeClassGetNode.class) - public static native NodeClass get(Class c); -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * 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.hotspot.replacements; - -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.PiNode.*; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.word.*; -import com.oracle.graal.word.*; - -@ClassSubstitution(Node.class) -public class HotSpotNodeSubstitutions { - - /** - * Gets the value of the {@code InstanceKlass::_graal_node_class} field from the InstanceKlass - * pointed to by {@code node}'s header. - */ - @MethodSubstitution(isStatic = false) - public static NodeClass getNodeClass(final Node node) { - // HotSpot creates the NodeClass for each Node subclass while initializing it - // so we are guaranteed to read a non-null value here. As long as NodeClass - // is final, the stamp of the PiNode below will automatically be exact. - KlassPointer klass = loadHub(node); - return piCastNonNull(klass.readObject(Word.signed(instanceKlassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Mar 02 19:11:22 2015 +0100 @@ -661,13 +661,6 @@ return config().arrayKlassOffset; } - public static final LocationIdentity KLASS_NODE_CLASS = NamedLocationIdentity.immutable("KlassNodeClass"); - - @Fold - public static int instanceKlassNodeClassOffset() { - return config().instanceKlassNodeClassOffset; - } - public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror"); @Fold diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,9 +32,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.bridge.*; -import com.oracle.graal.lir.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -63,9 +61,6 @@ replacements.registerSubstitutions(Class.class, HotSpotClassSubstitutions.class); replacements.registerSubstitutions(CRC32.class, CRC32Substitutions.class); replacements.registerSubstitutions(Reflection.class, ReflectionSubstitutions.class); - replacements.registerSubstitutions(NodeClass.class, HotSpotNodeClassSubstitutions.class); - replacements.registerSubstitutions(Node.class, HotSpotNodeSubstitutions.class); - replacements.registerSubstitutions(CompositeValueClass.class, CompositeValueClassSubstitutions.class); replacements.registerSubstitutions(CompilerToVMImpl.class, CompilerToVMImplSubstitutions.class); replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.AESCrypt"), AESCryptSubstitutions.class); replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.CipherBlockChaining"), CipherBlockChainingSubstitutions.class); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,11 +38,12 @@ * also used by {@link ClassGetHubNode} to eliminate chains of {@code klass._java_mirror._klass}. */ @NodeInfo -public class HubGetClassNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { +public final class HubGetClassNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { + public static final NodeClass TYPE = NodeClass.create(HubGetClassNode.class); @Input protected ValueNode hub; public HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { - super(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Class.class)), null); + super(TYPE, StampFactory.declaredNonNull(metaAccess.lookupJavaType(Class.class)), null); this.hub = hub; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Mar 02 19:11:22 2015 +0100 @@ -61,17 +61,26 @@ */ public class InstanceOfSnippets implements Snippets { + private static final double COMPILED_VS_INTERPRETER_SPEEDUP = 50; + private static final double INSTANCEOF_DEOPT_SPEEDUP = 1.01; // generous 1% speedup + + private static final int DEOPT_THRESHOLD_FACTOR = (int) (COMPILED_VS_INTERPRETER_SPEEDUP / (INSTANCEOF_DEOPT_SPEEDUP - 1.0)); + /** * Gets the minimum required probability of a profiled instanceof hitting one the profiled types * for use of the {@linkplain #instanceofWithProfile deoptimizing} snippet. The value is - * computed to be an order of magnitude greater than the configured compilation threshold. For - * example, if a method is compiled after being interpreted 10000 times, the deoptimizing - * snippet will only be used for an instanceof if its profile indicates that less than 1 in - * 100000 executions are for an object whose type is not one of the top N profiled types (where - * {@code N == } {@link Options#TypeCheckMaxHints}). + * computed to be an order of greater than the configured compilation threshold by a + * {@linkplain #DEOPT_THRESHOLD_FACTOR factor}. + * + *

    + * This factor is such that the additional executions we get from using the deoptimizing snippet + * (({@linkplain #INSTANCEOF_DEOPT_SPEEDUP speedup} - 1) / probability threshold) is greater + * than the time lost during re-interpretation ({@linkplain #COMPILED_VS_INTERPRETER_SPEEDUP + * compiled code speedup} × compilation threshold). + *

    */ public static double hintHitProbabilityThresholdForDeoptimizingSnippet(long compilationThreshold) { - return 1.0D - (1.0D / (compilationThreshold * 10)); + return 1.0D - (1.0D / (compilationThreshold * DEOPT_THRESHOLD_FACTOR)); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +38,9 @@ * information in {@code klass}. */ @NodeInfo -public class KlassLayoutHelperNode extends FloatingGuardedNode implements Canonicalizable, Lowerable { +public final class KlassLayoutHelperNode extends FloatingGuardedNode implements Canonicalizable, Lowerable { + public static final NodeClass TYPE = NodeClass.create(KlassLayoutHelperNode.class); @Input protected ValueNode klass; protected final HotSpotVMConfig config; @@ -48,7 +49,7 @@ } public KlassLayoutHelperNode(@InjectedNodeParameter HotSpotVMConfig config, ValueNode klass, ValueNode guard) { - super(StampFactory.forKind(Kind.Int), (GuardingNode) guard); + super(TYPE, StampFactory.forKind(Kind.Int), (GuardingNode) guard); this.klass = klass; this.config = config; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +44,7 @@ */ @NodeInfo public final class MethodHandleNode extends MacroStateSplitNode implements Simplifiable { + public static final NodeClass TYPE = NodeClass.create(MethodHandleNode.class); // Replacement method data protected ResolvedJavaMethod replacementTargetMethod; @@ -51,7 +52,7 @@ @Input NodeInputList replacementArguments; public MethodHandleNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); // See if we need to save some replacement method data. if (callTarget instanceof SelfReplacingMethodCallTargetNode) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Mar 02 19:11:22 2015 +0100 @@ -504,7 +504,7 @@ StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false, null); - List rets = graph.getNodes(ReturnNode.class).snapshot(); + List rets = graph.getNodes(ReturnNode.TYPE).snapshot(); for (ReturnNode ret : rets) { returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass()); String msg = "unbalanced monitors in " + graph.method().format("%H.%n(%p)") + ", count = %d"; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Mar 02 19:11:22 2015 +0100 @@ -251,7 +251,7 @@ /** * Computes the size of the memory chunk allocated for an array. This size accounts for the - * array header size, boy size and any padding after the last element to satisfy object + * array header size, body size and any padding after the last element to satisfy object * alignment requirements. * * @param length the number of elements in the array diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; @@ -39,10 +40,12 @@ import com.oracle.graal.replacements.nodes.*; @NodeInfo -public class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider { +public final class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider { + + public static final NodeClass TYPE = NodeClass.create(ObjectCloneNode.class); public ObjectCloneNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +35,12 @@ import com.oracle.graal.replacements.nodes.*; @NodeInfo -public class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { +public final class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { + + public static final NodeClass TYPE = NodeClass.create(ReflectionGetCallerClassNode.class); public ReflectionGetCallerClassNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,19 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; @NodeInfo -public class SystemIdentityHashCodeNode extends PureFunctionMacroNode { +public final class SystemIdentityHashCodeNode extends PureFunctionMacroNode { + + public static final NodeClass TYPE = NodeClass.create(SystemIdentityHashCodeNode.class); public SystemIdentityHashCodeNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -41,6 +42,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public final class ArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(ArrayCopyCallNode.class); @Input ValueNode src; @Input ValueNode srcPos; @Input ValueNode dest; @@ -70,7 +72,7 @@ protected ArrayCopyCallNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, Kind elementKind, boolean aligned, boolean disjoint, boolean uninitialized, HotSpotGraalRuntimeProvider runtime) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); assert elementKind != null; this.src = src; this.srcPos = srcPos; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +28,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -40,8 +41,10 @@ @NodeInfo public final class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable { + public static final NodeClass TYPE = NodeClass.create(ArrayCopyNode.class); + public ArrayCopyNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -40,6 +41,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory, InputType.Value}) public final class CheckcastArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(CheckcastArrayCopyCallNode.class); @Input ValueNode src; @Input ValueNode srcPos; @Input ValueNode dest; @@ -54,7 +56,7 @@ protected CheckcastArrayCopyCallNode(@InjectedNodeParameter HotSpotGraalRuntimeProvider runtime, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode superCheckOffset, ValueNode destElemKlass, boolean uninit) { - super(StampFactory.forKind(Kind.Int)); + super(TYPE, StampFactory.forKind(Kind.Int)); this.src = src; this.srcPos = srcPos; this.dest = dest; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -33,8 +34,9 @@ import com.oracle.graal.replacements.SnippetTemplate.Arguments; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single { +public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(UnsafeArrayCopyNode.class); @Input ValueNode src; @Input ValueNode srcPos; @Input ValueNode dest; @@ -45,7 +47,7 @@ protected Kind elementKind; public UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, Kind elementKind) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); assert layoutHelper == null || elementKind == null; this.src = src; this.srcPos = srcPos; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,8 +23,10 @@ package com.oracle.graal.hotspot.stubs; import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotBackend.Options.*; import static com.oracle.graal.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.stubs.UncommonTrapStub.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -84,6 +86,7 @@ public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { super(DeoptimizationStub.class, "deoptimizationHandler", providers, target, linkage); this.target = target; + assert PreferGraalStubs.getValue(); } @Override @@ -135,7 +138,7 @@ * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for * total size of the interpreter frames plus shadow page size. Bang one page at a time * because large sizes can bang beyond yellow and red zones. - * + * * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. */ final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); @@ -143,7 +146,7 @@ Word stackPointer = readRegister(stackPointerRegister); for (int i = 1; i < bangPages; i++) { - stackPointer.writeInt((-i * pageSize()) + stackBias(), 0, UncommonTrapStub.STACK_BANG_LOCATION); + stackPointer.writeInt((-i * pageSize()) + stackBias(), 0, STACK_BANG_LOCATION); } // Load number of interpreter frames. diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,8 +22,9 @@ */ package com.oracle.graal.hotspot.stubs; +import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotBackend.Options.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.hotspot.stubs.StubUtil.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -85,6 +86,7 @@ public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { super(UncommonTrapStub.class, "uncommonTrapHandler", providers, target, linkage); this.target = target; + assert PreferGraalStubs.getValue(); } @Override @@ -147,7 +149,7 @@ * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for * total size of the interpreter frames plus shadow page size. Bang one page at a time * because large sizes can bang beyond yellow and red zones. - * + * * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. */ final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); @@ -284,8 +286,6 @@ return config().deoptimizationUnpackUncommonTrap; } - public static final ForeignCallDescriptor UNPACK_FRAMES = newDescriptor(UncommonTrapStub.class, "unpackFrames", int.class, Word.class, int.class); - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/PointerCastNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/PointerCastNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/PointerCastNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -34,12 +35,13 @@ * {@link HotSpotWordTypeRewriterPhase}. */ @NodeInfo -public class PointerCastNode extends FloatingNode implements LIRLowerable { +public final class PointerCastNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(PointerCastNode.class); @Input ValueNode input; public PointerCastNode(Stamp stamp, ValueNode input) { - super(stamp); + super(TYPE, stamp); this.input = input; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,11 +37,12 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.debug.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; -public abstract class AbstractBytecodeParser> { +public abstract class AbstractBytecodeParser { static class Options { // @formatter:off @@ -62,7 +63,7 @@ */ public static final int TRACELEVEL_STATE = 2; - protected F frameState; + protected HIRFrameStateBuilder frameState; protected BciBlock currentBlock; protected final BytecodeStream stream; @@ -74,22 +75,29 @@ protected final MetaAccessProvider metaAccess; /** + * Specifies if the {@linkplain #getMethod() method} being parsed implements the semantics of + * another method (i.e., an intrinsic) or bytecode instruction (i.e., a snippet). substitution. + */ + protected final boolean parsingReplacement; + + /** * Meters the number of actual bytecodes parsed. */ public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed"); - public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { + public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, boolean isReplacement) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; this.stream = new BytecodeStream(method.getCode()); - this.profilingInfo = method.getProfilingInfo(); + this.profilingInfo = (graphBuilderConfig.getUseProfiling() ? method.getProfilingInfo() : null); this.constantPool = method.getConstantPool(); this.method = method; + this.parsingReplacement = isReplacement; assert metaAccess != null; } - public void setCurrentFrameState(F frameState) { + public void setCurrentFrameState(HIRFrameStateBuilder frameState) { this.frameState = frameState; } @@ -106,11 +114,11 @@ } public void storeLocal(Kind kind, int index) { - T value; + ValueNode value; if (kind == Kind.Object) { value = frameState.xpop(); // astore and astore_ may be used to store a returnAddress (jsr) - assert value.getKind() == Kind.Object || value.getKind() == Kind.Int; + assert parsingReplacement || (value.getKind() == Kind.Object || value.getKind() == Kind.Int) : value + ":" + value.getKind(); } else { value = frameState.pop(kind); } @@ -126,13 +134,13 @@ * @param type the unresolved type of the type check * @param object the object value whose type is being checked against {@code type} */ - protected abstract void handleUnresolvedCheckCast(JavaType type, T object); + protected abstract void handleUnresolvedCheckCast(JavaType type, ValueNode object); /** * @param type the unresolved type of the type check * @param object the object value whose type is being checked against {@code type} */ - protected abstract void handleUnresolvedInstanceOf(JavaType type, T object); + protected abstract void handleUnresolvedInstanceOf(JavaType type, ValueNode object); /** * @param type the type being instantiated @@ -143,26 +151,26 @@ * @param type the type of the array being instantiated * @param length the length of the array */ - protected abstract void handleUnresolvedNewObjectArray(JavaType type, T length); + protected abstract void handleUnresolvedNewObjectArray(JavaType type, ValueNode length); /** * @param type the type being instantiated * @param dims the dimensions for the multi-array */ - protected abstract void handleUnresolvedNewMultiArray(JavaType type, List dims); + protected abstract void handleUnresolvedNewMultiArray(JavaType type, List dims); /** * @param field the unresolved field * @param receiver the object containing the field or {@code null} if {@code field} is static */ - protected abstract void handleUnresolvedLoadField(JavaField field, T receiver); + protected abstract void handleUnresolvedLoadField(JavaField field, ValueNode receiver); /** * @param field the unresolved field * @param value the value being stored to the field * @param receiver the object containing the field or {@code null} if {@code field} is static */ - protected abstract void handleUnresolvedStoreField(JavaField field, T value, T receiver); + protected abstract void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver); /** * @param type @@ -171,7 +179,7 @@ // protected abstract void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind); - // protected abstract DispatchBeginNode handleException(T exceptionObject, int bci); + // protected abstract DispatchBeginNode handleException(ValueNode exceptionObject, int bci); private void genLoadConstant(int cpi, int opcode) { Object con = lookupConstant(cpi, opcode); @@ -192,56 +200,41 @@ } } - protected abstract T genLoadIndexed(T index, T array, Kind kind); + protected abstract ValueNode genLoadIndexed(ValueNode index, ValueNode array, Kind kind); private void genLoadIndexed(Kind kind) { emitExplicitExceptions(frameState.peek(1), frameState.peek(0)); - T index = frameState.ipop(); - T array = frameState.apop(); + ValueNode index = frameState.ipop(); + ValueNode array = frameState.apop(); frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind))); } - protected abstract T genStoreIndexed(T array, T index, Kind kind, T value); + protected abstract ValueNode genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value); private void genStoreIndexed(Kind kind) { emitExplicitExceptions(frameState.peek(2), frameState.peek(1)); - T value = frameState.pop(kind.getStackKind()); - T index = frameState.ipop(); - T array = frameState.apop(); + ValueNode value = frameState.pop(kind.getStackKind()); + ValueNode index = frameState.ipop(); + ValueNode array = frameState.apop(); append(genStoreIndexed(array, index, kind, value)); } private void stackOp(int opcode) { switch (opcode) { - case POP: { - frameState.xpop(); - break; - } - case POP2: { - frameState.xpop(); - frameState.xpop(); - break; - } - case DUP: { - T w = frameState.xpop(); - frameState.xpush(w); - frameState.xpush(w); - break; - } case DUP_X1: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); frameState.xpush(w1); frameState.xpush(w2); frameState.xpush(w1); break; } case DUP_X2: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); - T w3 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); frameState.xpush(w1); frameState.xpush(w3); frameState.xpush(w2); @@ -249,8 +242,8 @@ break; } case DUP2: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); frameState.xpush(w2); frameState.xpush(w1); frameState.xpush(w2); @@ -258,9 +251,9 @@ break; } case DUP2_X1: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); - T w3 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); frameState.xpush(w2); frameState.xpush(w1); frameState.xpush(w3); @@ -269,10 +262,10 @@ break; } case DUP2_X2: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); - T w3 = frameState.xpop(); - T w4 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + ValueNode w4 = frameState.xpop(); frameState.xpush(w2); frameState.xpush(w1); frameState.xpush(w4); @@ -282,8 +275,8 @@ break; } case SWAP: { - T w1 = frameState.xpop(); - T w2 = frameState.xpop(); + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); frameState.xpush(w1); frameState.xpush(w2); break; @@ -293,27 +286,27 @@ } } - protected abstract T genIntegerAdd(Kind kind, T x, T y); + protected abstract ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y); - protected abstract T genIntegerSub(Kind kind, T x, T y); + protected abstract ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y); - protected abstract T genIntegerMul(Kind kind, T x, T y); + protected abstract ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y); - protected abstract T genFloatAdd(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatSub(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatMul(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatDiv(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - protected abstract T genFloatRem(Kind kind, T x, T y, boolean isStrictFP); + protected abstract ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); private void genArithmeticOp(Kind result, int opcode) { - T y = frameState.pop(result); - T x = frameState.pop(result); + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); boolean isStrictFP = method.isStrict(); - T v; + ValueNode v; switch (opcode) { case IADD: case LADD: @@ -353,14 +346,14 @@ frameState.push(result, append(v)); } - protected abstract T genIntegerDiv(Kind kind, T x, T y); + protected abstract ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y); - protected abstract T genIntegerRem(Kind kind, T x, T y); + protected abstract ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y); private void genIntegerDivOp(Kind result, int opcode) { - T y = frameState.pop(result); - T x = frameState.pop(result); - T v; + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); + ValueNode v; switch (opcode) { case IDIV: case LDIV: @@ -376,22 +369,22 @@ frameState.push(result, append(v)); } - protected abstract T genNegateOp(T x); + protected abstract ValueNode genNegateOp(ValueNode x); private void genNegateOp(Kind kind) { frameState.push(kind, append(genNegateOp(frameState.pop(kind)))); } - protected abstract T genLeftShift(Kind kind, T x, T y); + protected abstract ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y); - protected abstract T genRightShift(Kind kind, T x, T y); + protected abstract ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y); - protected abstract T genUnsignedRightShift(Kind kind, T x, T y); + protected abstract ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y); private void genShiftOp(Kind kind, int opcode) { - T s = frameState.ipop(); - T x = frameState.pop(kind); - T v; + ValueNode s = frameState.ipop(); + ValueNode x = frameState.pop(kind); + ValueNode v; switch (opcode) { case ISHL: case LSHL: @@ -411,16 +404,16 @@ frameState.push(kind, append(v)); } - protected abstract T genAnd(Kind kind, T x, T y); + protected abstract ValueNode genAnd(Kind kind, ValueNode x, ValueNode y); - protected abstract T genOr(Kind kind, T x, T y); + protected abstract ValueNode genOr(Kind kind, ValueNode x, ValueNode y); - protected abstract T genXor(Kind kind, T x, T y); + protected abstract ValueNode genXor(Kind kind, ValueNode x, ValueNode y); private void genLogicOp(Kind kind, int opcode) { - T y = frameState.pop(kind); - T x = frameState.pop(kind); - T v; + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + ValueNode v; switch (opcode) { case IAND: case LAND: @@ -440,29 +433,29 @@ frameState.push(kind, append(v)); } - protected abstract T genNormalizeCompare(T x, T y, boolean isUnorderedLess); + protected abstract ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess); private void genCompareOp(Kind kind, boolean isUnorderedLess) { - T y = frameState.pop(kind); - T x = frameState.pop(kind); + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess))); } - protected abstract T genFloatConvert(FloatConvert op, T input); + protected abstract ValueNode genFloatConvert(FloatConvert op, ValueNode input); private void genFloatConvert(FloatConvert op, Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); frameState.push(to.getStackKind(), append(genFloatConvert(op, input))); } - protected abstract T genNarrow(T input, int bitCount); + protected abstract ValueNode genNarrow(ValueNode input, int bitCount); - protected abstract T genSignExtend(T input, int bitCount); + protected abstract ValueNode genSignExtend(ValueNode input, int bitCount); - protected abstract T genZeroExtend(T input, int bitCount); + protected abstract ValueNode genZeroExtend(ValueNode input, int bitCount); private void genSignExtend(Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); if (from != from.getStackKind()) { input = append(genNarrow(input, from.getBitCount())); } @@ -470,7 +463,7 @@ } private void genZeroExtend(Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); if (from != from.getStackKind()) { input = append(genNarrow(input, from.getBitCount())); } @@ -478,46 +471,45 @@ } private void genNarrow(Kind from, Kind to) { - T input = frameState.pop(from.getStackKind()); + ValueNode input = frameState.pop(from.getStackKind()); frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount()))); } private void genIncrement() { int index = getStream().readLocalIndex(); int delta = getStream().readIncrement(); - T x = frameState.loadLocal(index); - T y = appendConstant(JavaConstant.forInt(delta)); + ValueNode x = frameState.loadLocal(index); + ValueNode y = appendConstant(JavaConstant.forInt(delta)); frameState.storeLocal(index, append(genIntegerAdd(Kind.Int, x, y))); } protected abstract void genGoto(); - protected abstract T genObjectEquals(T x, T y); + protected abstract ValueNode genObjectEquals(ValueNode x, ValueNode y); - protected abstract T genIntegerEquals(T x, T y); + protected abstract ValueNode genIntegerEquals(ValueNode x, ValueNode y); - protected abstract T genIntegerLessThan(T x, T y); + protected abstract ValueNode genIntegerLessThan(ValueNode x, ValueNode y); - protected abstract T genUnique(T x); + protected abstract ValueNode genUnique(ValueNode x); - protected abstract void genIf(T x, Condition cond, T y); + protected abstract void genIf(ValueNode x, Condition cond, ValueNode y); private void genIfZero(Condition cond) { - T y = appendConstant(JavaConstant.INT_0); - T x = frameState.ipop(); + ValueNode y = appendConstant(JavaConstant.INT_0); + ValueNode x = frameState.ipop(); genIf(x, cond, y); } private void genIfNull(Condition cond) { - T y = appendConstant(JavaConstant.NULL_POINTER); - T x = frameState.apop(); + ValueNode y = appendConstant(JavaConstant.NULL_POINTER); + ValueNode x = frameState.apop(); genIf(x, cond, y); } private void genIfSame(Kind kind, Condition cond) { - T y = frameState.pop(kind); - T x = frameState.pop(kind); - // assert !x.isDeleted() && !y.isDeleted(); + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); genIf(x, cond, y); } @@ -564,48 +556,47 @@ } private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) { - if (!optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { + if (parsingReplacement || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { return null; } else { return profilingInfo.getTypeProfile(bci()); } } - protected abstract T createCheckCast(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck); + protected abstract ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck); private void genCheckCast() { int cpi = getStream().readCPI(); JavaType type = lookupType(cpi, CHECKCAST); - T object = frameState.apop(); + ValueNode object = frameState.apop(); if (type instanceof ResolvedJavaType) { JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type); - T checkCastNode = append(createCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false)); + ValueNode checkCastNode = append(createCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false)); frameState.apush(checkCastNode); } else { handleUnresolvedCheckCast(type, object); } } - protected abstract T createInstanceOf(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck); + protected abstract ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck); - protected abstract T genConditional(T x); + protected abstract ValueNode genConditional(ValueNode x); private void genInstanceOf() { int cpi = getStream().readCPI(); JavaType type = lookupType(cpi, INSTANCEOF); - T object = frameState.apop(); + ValueNode object = frameState.apop(); if (type instanceof ResolvedJavaType) { ResolvedJavaType resolvedType = (ResolvedJavaType) type; - T instanceOfNode = createInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); + ValueNode instanceOfNode = createInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); frameState.ipush(append(genConditional(genUnique(instanceOfNode)))); } else { handleUnresolvedInstanceOf(type, object); } } - protected abstract T createNewInstance(ResolvedJavaType type, boolean fillContents); + protected abstract ValueNode createNewInstance(ResolvedJavaType type, boolean fillContents); - @SuppressWarnings("unchecked") void genNewInstance(int cpi) { JavaType type = lookupType(cpi, NEW); if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { @@ -613,7 +604,7 @@ if (skippedExceptionTypes != null) { for (ResolvedJavaType exceptionType : skippedExceptionTypes) { if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) { - append((T) new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); + append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); return; } } @@ -664,7 +655,7 @@ private void genNewObjectArray(int cpi) { JavaType type = lookupType(cpi, ANEWARRAY); - T length = frameState.ipop(); + ValueNode length = frameState.ipop(); if (type instanceof ResolvedJavaType) { frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true))); } else { @@ -673,12 +664,12 @@ } - protected abstract T createNewArray(ResolvedJavaType elementType, T length, boolean fillContents); + protected abstract ValueNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents); private void genNewMultiArray(int cpi) { JavaType type = lookupType(cpi, MULTIANEWARRAY); int rank = getStream().readUByte(bci() + 3); - List dims = new ArrayList<>(Collections.nCopies(rank, null)); + List dims = new ArrayList<>(Collections.nCopies(rank, null)); for (int i = rank - 1; i >= 0; i--) { dims.set(i, frameState.ipop()); } @@ -689,18 +680,18 @@ } } - protected abstract T createNewMultiArray(ResolvedJavaType type, List dims); + protected abstract ValueNode createNewMultiArray(ResolvedJavaType type, List dims); - protected abstract T genLoadField(T receiver, ResolvedJavaField field); + protected abstract ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field); private void genGetField(JavaField field) { emitExplicitExceptions(frameState.peek(0), null); Kind kind = field.getKind(); - T receiver = frameState.apop(); + ValueNode receiver = frameState.apop(); if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); - if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ValueNode) receiver, (ResolvedJavaField) field)) { + LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); + if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, receiver, (ResolvedJavaField) field)) { appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field)); } } else { @@ -708,36 +699,36 @@ } } - protected abstract void emitNullCheck(T receiver); + protected abstract void emitNullCheck(ValueNode receiver); - protected abstract void emitBoundsCheck(T index, T length); + protected abstract void emitBoundsCheck(ValueNode index, ValueNode length); private static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions"); - protected abstract T genArrayLength(T x); + protected abstract ValueNode genArrayLength(ValueNode x); - protected void emitExplicitExceptions(T receiver, T outOfBoundsIndex) { + protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) { assert receiver != null; - if (graphBuilderConfig.omitAllExceptionEdges() || + if (graphBuilderConfig.omitAllExceptionEdges() || profilingInfo == null || (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) { return; } emitNullCheck(receiver); if (outOfBoundsIndex != null) { - T length = append(genArrayLength(receiver)); + ValueNode length = append(genArrayLength(receiver)); emitBoundsCheck(outOfBoundsIndex, length); } EXPLICIT_EXCEPTIONS.increment(); } - protected abstract T genStoreField(T receiver, ResolvedJavaField field, T value); + protected abstract ValueNode genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value); private void genPutField(JavaField field) { emitExplicitExceptions(frameState.peek(1), null); - T value = frameState.pop(field.getKind().getStackKind()); - T receiver = frameState.apop(); + ValueNode value = frameState.pop(field.getKind().getStackKind()); + ValueNode receiver = frameState.apop(); if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { appendOptimizedStoreField(genStoreField(receiver, (ResolvedJavaField) field, value)); } else { @@ -748,7 +739,7 @@ private void genGetStatic(JavaField field) { Kind kind = field.getKind(); if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); + LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) { appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field)); } @@ -758,7 +749,7 @@ } private void genPutStatic(JavaField field) { - T value = frameState.pop(field.getKind().getStackKind()); + ValueNode value = frameState.pop(field.getKind().getStackKind()); if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { appendOptimizedStoreField(genStoreField(null, (ResolvedJavaField) field, value)); } else { @@ -766,13 +757,13 @@ } } - protected void appendOptimizedStoreField(T store) { + protected void appendOptimizedStoreField(ValueNode store) { append(store); } - protected void appendOptimizedLoadField(Kind kind, T load) { + protected void appendOptimizedLoadField(Kind kind, ValueNode load) { // append the load to the instruction - T optimized = append(load); + ValueNode optimized = append(load); frameState.push(kind.getStackKind(), optimized); } @@ -786,18 +777,18 @@ protected abstract void genInvokeSpecial(JavaMethod target); - protected abstract void genReturn(T x); + protected abstract void genReturn(ValueNode x); - protected abstract T genMonitorEnter(T x); + protected abstract ValueNode genMonitorEnter(ValueNode x); - protected abstract T genMonitorExit(T x, T returnValue); + protected abstract ValueNode genMonitorExit(ValueNode x, ValueNode returnValue); protected abstract void genJsr(int dest); protected abstract void genRet(int localIndex); private double[] switchProbability(int numberOfCases, int bci) { - double[] prob = profilingInfo.getSwitchProbabilities(bci); + double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci)); if (prob != null) { assert prob.length == numberOfCases; } else { @@ -835,7 +826,7 @@ private void genSwitch(BytecodeSwitch bs) { int bci = bci(); - T value = frameState.ipop(); + ValueNode value = frameState.ipop(); int nofCases = bs.numberOfCases(); double[] keyProbabilities = switchProbability(nofCases + 1, bci); @@ -853,12 +844,13 @@ int[] keySuccessors = new int[nofCases + 1]; int deoptSuccessorIndex = -1; int nextSuccessorIndex = 0; + boolean constantValue = value.isConstant(); for (int i = 0; i < nofCases + 1; i++) { if (i < nofCases) { keys[i] = bs.keyAt(i); } - if (isNeverExecutedCode(keyProbabilities[i])) { + if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) { if (deoptSuccessorIndex < 0) { deoptSuccessorIndex = nextSuccessorIndex++; actualSuccessors.add(null); @@ -879,7 +871,7 @@ } - protected abstract void genIntegerSwitch(T value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors); + protected abstract void genIntegerSwitch(ValueNode value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors); private static class SuccessorInfo { @@ -892,15 +884,19 @@ } } - protected abstract T appendConstant(JavaConstant constant); + protected abstract ValueNode appendConstant(JavaConstant constant); - protected abstract T append(T v); + protected abstract ValueNode append(ValueNode v); protected boolean isNeverExecutedCode(double probability) { return probability == 0 && optimisticOpts.removeNeverExecutedCode(); } protected double branchProbability() { + if (profilingInfo == null) { + return 0.5; + } + assert assertAtIfBytecode(); double probability = profilingInfo.getBranchTakenProbability(bci()); if (probability < 0) { assert probability == -1 : "invalid probability"; @@ -918,6 +914,31 @@ return probability; } + private boolean assertAtIfBytecode() { + int bytecode = stream.currentBC(); + switch (bytecode) { + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + case IFNULL: + case IFNONNULL: + return true; + } + assert false : String.format("%x is not an if bytecode", bytecode); + return true; + } + protected abstract void iterateBytecodesForBlock(BciBlock block); public final void processBytecode(int bci, int opcode) { @@ -1013,9 +1034,9 @@ case BASTORE : genStoreIndexed(Kind.Byte ); break; case CASTORE : genStoreIndexed(Kind.Char ); break; case SASTORE : genStoreIndexed(Kind.Short ); break; - case POP : // fall through - case POP2 : // fall through - case DUP : // fall through + case POP : frameState.xpop(); break; + case POP2 : frameState.xpop(); frameState.xpop(); break; + case DUP : frameState.xpush(frameState.xpeek()); break; case DUP_X1 : // fall through case DUP_X2 : // fall through case DUP2 : // fall through @@ -1144,14 +1165,15 @@ return method; } - public F getFrameState() { + public HIRFrameStateBuilder getFrameState() { return frameState; } - protected void traceInstruction(int bci, int opcode, boolean blockStart) { + protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { if (Debug.isEnabled() && Options.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { traceInstructionHelper(bci, opcode, blockStart); } + return true; } private void traceInstructionHelper(int bci, int opcode, boolean blockStart) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; -import com.oracle.graal.java.BciBlockMapping.LocalLiveness; public abstract class AbstractFrameStateBuilder> { @@ -37,15 +36,21 @@ protected T[] lockedObjects; /** + * Specifies if asserting type checks are enabled. + */ + protected final boolean checkTypes; + + /** * @see BytecodeFrame#rethrowException */ protected boolean rethrowException; - public AbstractFrameStateBuilder(ResolvedJavaMethod method) { + public AbstractFrameStateBuilder(ResolvedJavaMethod method, boolean checkTypes) { this.method = method; this.locals = allocateArray(method.getMaxLocals()); this.stack = allocateArray(Math.max(1, method.getMaxStackSize())); this.lockedObjects = allocateArray(0); + this.checkTypes = checkTypes; } protected AbstractFrameStateBuilder(S other) { @@ -55,6 +60,7 @@ this.stack = other.stack.clone(); this.lockedObjects = other.lockedObjects.length == 0 ? other.lockedObjects : other.lockedObjects.clone(); this.rethrowException = other.rethrowException; + this.checkTypes = other.checkTypes; assert locals.length == method.getMaxLocals(); assert stack.length == Math.max(1, method.getMaxStackSize()); @@ -172,8 +178,8 @@ public T loadLocal(int i) { T x = locals[i]; assert x != null : i; - assert x.getKind().getSlotCount() == 1 || locals[i + 1] == null; - assert i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1; + assert !checkTypes || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); + assert !checkTypes || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); return x; } @@ -185,7 +191,7 @@ * @param x the instruction which produces the value for the local */ public void storeLocal(int i, T x) { - assert x == null || x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x; + assert x == null || !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; locals[i] = x; if (x != null && x.getKind().needsTwoSlots()) { // if this is a double word, then kill i+1 @@ -212,7 +218,7 @@ * @param x the instruction to push onto the stack */ public void push(Kind kind, T x) { - assert x.getKind() != Kind.Void && x.getKind() != Kind.Illegal; + assert !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : x; xpush(assertKind(kind, x)); if (kind.needsTwoSlots()) { xpush(null); @@ -225,7 +231,7 @@ * @param x the instruction to push onto the stack */ public void xpush(T x) { - assert x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); + assert !checkTypes || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); stack[stackSize++] = x; } @@ -369,7 +375,7 @@ newStackSize--; assert stack[newStackSize].getKind().needsTwoSlots(); } else { - assert stack[newStackSize].getKind().getSlotCount() == 1; + assert !checkTypes || (stack[newStackSize].getKind().getSlotCount() == 1); } result[i] = stack[newStackSize]; } @@ -405,7 +411,7 @@ } private T assertKind(Kind kind, T x) { - assert x != null && x.getKind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind()); + assert x != null && (!checkTypes || x.getKind() == kind) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind()); return x; } @@ -425,7 +431,7 @@ } private T assertObject(T x) { - assert x != null && (x.getKind() == Kind.Object); + assert x != null && (!checkTypes || (x.getKind() == Kind.Object)); return x; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +32,6 @@ import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.nodes.*; /** * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph @@ -84,11 +82,7 @@ public int loopId; public int loopEnd; protected List successors; - - private FixedWithNextNode firstInstruction; - private AbstractFrameStateBuilder entryState; - private FixedWithNextNode[] firstInstructionArray; - private AbstractFrameStateBuilder[] entryStateArray; + private int predecessorCount; private boolean visited; private boolean active; @@ -127,6 +121,10 @@ return id; } + public int getPredecessorCount() { + return this.predecessorCount; + } + public int numNormalSuccessors() { if (exceptionDispatchBlock() != null) { return successors.size() - 1; @@ -245,7 +243,7 @@ return jsrData; } - public void setEndsWithRet() { + void setEndsWithRet() { getOrCreateJSRData().endsWithRet = true; } @@ -265,7 +263,7 @@ } } - public void setRetSuccessor(BciBlock bciBlock) { + void setRetSuccessor(BciBlock bciBlock) { this.getOrCreateJSRData().retSuccessor = bciBlock; } @@ -308,78 +306,18 @@ } } - public void setJsrScope(JsrScope nextScope) { + void setJsrScope(JsrScope nextScope) { this.getOrCreateJSRData().jsrScope = nextScope; } - public void setJsrSuccessor(BciBlock clone) { + void setJsrSuccessor(BciBlock clone) { this.getOrCreateJSRData().jsrSuccessor = clone; } - public void setJsrReturnBci(int bci) { + void setJsrReturnBci(int bci) { this.getOrCreateJSRData().jsrReturnBci = bci; } - public FixedWithNextNode getFirstInstruction(int dimension) { - if (dimension == 0) { - return firstInstruction; - } else { - if (firstInstructionArray != null && dimension - 1 < firstInstructionArray.length) { - return firstInstructionArray[dimension - 1]; - } else { - return null; - } - } - } - - public void setFirstInstruction(int dimension, FixedWithNextNode firstInstruction) { - if (dimension == 0) { - this.firstInstruction = firstInstruction; - } else { - if (firstInstructionArray == null) { - firstInstructionArray = new FixedWithNextNode[4]; - } - if (dimension - 1 < firstInstructionArray.length) { - // We are within bounds. - } else { - // We are out of bounds. - firstInstructionArray = Arrays.copyOf(firstInstructionArray, Math.max(firstInstructionArray.length * 2, dimension)); - } - - firstInstructionArray[dimension - 1] = firstInstruction; - } - } - - public AbstractFrameStateBuilder getEntryState(int dimension) { - if (dimension == 0) { - return entryState; - } else { - if (entryStateArray != null && dimension - 1 < entryStateArray.length) { - return entryStateArray[dimension - 1]; - } else { - return null; - } - } - } - - public void setEntryState(int dimension, AbstractFrameStateBuilder entryState) { - if (dimension == 0) { - this.entryState = entryState; - } else { - if (entryStateArray == null) { - entryStateArray = new AbstractFrameStateBuilder[4]; - } - if (dimension - 1 < entryStateArray.length) { - // We are within bounds. - } else { - // We are out of bounds. - entryStateArray = Arrays.copyOf(entryStateArray, Math.max(entryStateArray.length * 2, dimension)); - } - - entryStateArray[dimension - 1] = entryState; - } - } - public int getSuccessorCount() { return successors.size(); } @@ -388,9 +326,21 @@ return successors; } - public void setId(int i) { + void setId(int i) { this.id = i; } + + public void addSuccessor(BciBlock sux) { + successors.add(sux); + sux.predecessorCount++; + } + + public void clearSucccessors() { + for (BciBlock sux : successors) { + sux.predecessorCount--; + } + successors.clear(); + } } public static class ExceptionDispatchBlock extends BciBlock { @@ -407,74 +357,61 @@ private BciBlock[] blocks; public final ResolvedJavaMethod method; public boolean hasJsrBytecodes; - public BciBlock startBlock; - private final BytecodeStream stream; private final ExceptionHandler[] exceptionHandlers; - private BciBlock[] blockMap; + private BciBlock startBlock; private BciBlock[] loopHeaders; private static final int LOOP_HEADER_MAX_CAPACITY = Long.SIZE; private static final int LOOP_HEADER_INITIAL_CAPACITY = 4; - private final boolean doLivenessAnalysis; - public LocalLiveness liveness; private int blocksNotYetAssignedId; - private final boolean consecutiveLoopBlocks; + public int returnCount; + private int returnBci; /** * Creates a new BlockMap instance from bytecode of the given method . * * @param method the compiler interface method containing the code */ - private BciBlockMapping(ResolvedJavaMethod method, boolean doLivenessAnalysis, boolean consecutiveLoopBlocks) { - this.doLivenessAnalysis = doLivenessAnalysis; - this.consecutiveLoopBlocks = consecutiveLoopBlocks; + private BciBlockMapping(ResolvedJavaMethod method) { this.method = method; this.exceptionHandlers = method.getExceptionHandlers(); - this.stream = new BytecodeStream(method.getCode()); - int codeSize = method.getCodeSize(); - this.blockMap = new BciBlock[codeSize]; } public BciBlock[] getBlocks() { return this.blocks; } + public int getReturnCount() { + return this.returnCount; + } + /** * Builds the block map and conservative CFG and numbers blocks. */ - public void build() { - makeExceptionEntries(); - iterateOverBytecodes(); + public void build(BytecodeStream stream) { + int codeSize = method.getCodeSize(); + BciBlock[] blockMap = new BciBlock[codeSize]; + makeExceptionEntries(blockMap); + iterateOverBytecodes(blockMap, stream); if (hasJsrBytecodes) { if (!SupportJsrBytecodes.getValue()) { throw new JsrNotSupportedBailout("jsr/ret parsing disabled"); } - createJsrAlternatives(blockMap[0]); + createJsrAlternatives(blockMap, blockMap[0]); } if (Debug.isLogEnabled()) { - this.log("Before BlockOrder"); + this.log(blockMap, "Before BlockOrder"); } - computeBlockOrder(); - fixLoopBits(); - - startBlock = blockMap[0]; + computeBlockOrder(blockMap); + fixLoopBits(blockMap); assert verify(); - // Discard big arrays so that they can be GCed - blockMap = null; + startBlock = blockMap[0]; if (Debug.isLogEnabled()) { - this.log("Before LivenessAnalysis"); - } - if (doLivenessAnalysis) { - try (Scope s = Debug.scope("LivenessAnalysis")) { - liveness = method.getMaxLocals() <= 64 ? new SmallLocalLiveness() : new LargeLocalLiveness(); - liveness.computeLiveness(); - } catch (Throwable e) { - throw Debug.handle(e); - } + this.log(blockMap, "Before LivenessAnalysis"); } } @@ -493,15 +430,15 @@ return true; } - private void makeExceptionEntries() { + private void makeExceptionEntries(BciBlock[] blockMap) { // start basic blocks at all exception handler blocks and mark them as exception entries for (ExceptionHandler h : this.exceptionHandlers) { - BciBlock xhandler = makeBlock(h.getHandlerBCI()); + BciBlock xhandler = makeBlock(blockMap, h.getHandlerBCI()); xhandler.isExceptionEntry = true; } } - private void iterateOverBytecodes() { + private void iterateOverBytecodes(BciBlock[] blockMap, BytecodeStream stream) { // iterate over the bytecodes top to bottom. // mark the entrypoints of basic blocks and build lists of successors for // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret) @@ -511,9 +448,9 @@ int bci = stream.currentBCI(); if (current == null || blockMap[bci] != null) { - BciBlock b = makeBlock(bci); + BciBlock b = makeBlock(blockMap, bci); if (current != null) { - addSuccessor(current.endBci, b); + addSuccessor(blockMap, current.endBci, b); } current = b; } @@ -527,14 +464,16 @@ case DRETURN: // fall through case ARETURN: // fall through case RETURN: { + returnCount++; current = null; + returnBci = bci; break; } case ATHROW: { current = null; - ExceptionDispatchBlock handler = handleExceptions(bci); + ExceptionDispatchBlock handler = handleExceptions(blockMap, bci); if (handler != null) { - addSuccessor(bci, handler); + addSuccessor(blockMap, bci, handler); } break; } @@ -555,24 +494,24 @@ case IFNULL: // fall through case IFNONNULL: { current = null; - addSuccessor(bci, makeBlock(stream.readBranchDest())); - addSuccessor(bci, makeBlock(stream.nextBCI())); + addSuccessor(blockMap, bci, makeBlock(blockMap, stream.readBranchDest())); + addSuccessor(blockMap, bci, makeBlock(blockMap, stream.nextBCI())); break; } case GOTO: case GOTO_W: { current = null; - addSuccessor(bci, makeBlock(stream.readBranchDest())); + addSuccessor(blockMap, bci, makeBlock(blockMap, stream.readBranchDest())); break; } case TABLESWITCH: { current = null; - addSwitchSuccessors(bci, new BytecodeTableSwitch(stream, bci)); + addSwitchSuccessors(blockMap, bci, new BytecodeTableSwitch(stream, bci)); break; } case LOOKUPSWITCH: { current = null; - addSwitchSuccessors(bci, new BytecodeLookupSwitch(stream, bci)); + addSwitchSuccessors(blockMap, bci, new BytecodeLookupSwitch(stream, bci)); break; } case JSR: @@ -582,11 +521,11 @@ if (target == 0) { throw new JsrNotSupportedBailout("jsr target bci 0 not allowed"); } - BciBlock b1 = makeBlock(target); + BciBlock b1 = makeBlock(blockMap, target); current.setJsrSuccessor(b1); current.setJsrReturnBci(stream.nextBCI()); current = null; - addSuccessor(bci, b1); + addSuccessor(blockMap, bci, b1); break; } case RET: { @@ -599,11 +538,11 @@ case INVOKESTATIC: case INVOKEVIRTUAL: case INVOKEDYNAMIC: { - ExceptionDispatchBlock handler = handleExceptions(bci); + ExceptionDispatchBlock handler = handleExceptions(blockMap, bci); if (handler != null) { current = null; - addSuccessor(bci, makeBlock(stream.nextBCI())); - addSuccessor(bci, handler); + addSuccessor(blockMap, bci, makeBlock(blockMap, stream.nextBCI())); + addSuccessor(blockMap, bci, handler); } break; } @@ -625,11 +564,11 @@ case SALOAD: case PUTFIELD: case GETFIELD: { - ExceptionDispatchBlock handler = handleExceptions(bci); + ExceptionDispatchBlock handler = handleExceptions(blockMap, bci); if (handler != null) { current = null; - addSuccessor(bci, makeBlock(stream.nextBCI())); - addSuccessor(bci, handler); + addSuccessor(blockMap, bci, makeBlock(blockMap, stream.nextBCI())); + addSuccessor(blockMap, bci, handler); } } } @@ -637,7 +576,7 @@ } } - private BciBlock makeBlock(int startBci) { + private BciBlock makeBlock(BciBlock[] blockMap, int startBci) { BciBlock oldBlock = blockMap[startBci]; if (oldBlock == null) { BciBlock newBlock = new BciBlock(); @@ -653,11 +592,13 @@ blocksNotYetAssignedId++; newBlock.startBci = startBci; newBlock.endBci = oldBlock.endBci; - newBlock.getSuccessors().addAll(oldBlock.getSuccessors()); + for (BciBlock oldSuccessor : oldBlock.getSuccessors()) { + newBlock.addSuccessor(oldSuccessor); + } oldBlock.endBci = startBci - 1; - oldBlock.getSuccessors().clear(); - oldBlock.getSuccessors().add(newBlock); + oldBlock.clearSucccessors(); + oldBlock.addSuccessor(newBlock); for (int i = startBci; i <= newBlock.endBci; i++) { blockMap[i] = newBlock; @@ -669,7 +610,7 @@ } } - private void addSwitchSuccessors(int predBci, BytecodeSwitch bswitch) { + private void addSwitchSuccessors(BciBlock[] blockMap, int predBci, BytecodeSwitch bswitch) { // adds distinct targets to the successor list Collection targets = new TreeSet<>(); for (int i = 0; i < bswitch.numberOfCases(); i++) { @@ -677,27 +618,27 @@ } targets.add(bswitch.defaultTarget()); for (int targetBci : targets) { - addSuccessor(predBci, makeBlock(targetBci)); + addSuccessor(blockMap, predBci, makeBlock(blockMap, targetBci)); } } - private void addSuccessor(int predBci, BciBlock sux) { + private static void addSuccessor(BciBlock[] blockMap, int predBci, BciBlock sux) { BciBlock predecessor = blockMap[predBci]; if (sux.isExceptionEntry) { throw new BailoutException("Exception handler can be reached by both normal and exceptional control flow"); } - predecessor.getSuccessors().add(sux); + predecessor.addSuccessor(sux); } private final ArrayList jsrVisited = new ArrayList<>(); - private void createJsrAlternatives(BciBlock block) { + private void createJsrAlternatives(BciBlock[] blockMap, BciBlock block) { jsrVisited.add(block); JsrScope scope = block.getJsrScope(); if (block.endsWithRet()) { block.setRetSuccessor(blockMap[scope.nextReturnAddress()]); - block.getSuccessors().add(block.getRetSuccessor()); + block.addSuccessor(block.getRetSuccessor()); assert block.getRetSuccessor() != block.getJsrSuccessor(); } Debug.log("JSR alternatives block %s sux %s jsrSux %s retSux %s jsrScope %s", block, block.getSuccessors(), block.getJsrSuccessor(), block.getRetSuccessor(), block.getJsrScope()); @@ -738,14 +679,14 @@ } for (BciBlock successor : block.getSuccessors()) { if (!jsrVisited.contains(successor)) { - createJsrAlternatives(successor); + createJsrAlternatives(blockMap, successor); } } } private HashMap initialExceptionDispatch = CollectionsFactory.newMap(); - private ExceptionDispatchBlock handleExceptions(int bci) { + private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) { ExceptionDispatchBlock lastHandler = null; for (int i = exceptionHandlers.length - 1; i >= 0; i--) { @@ -766,9 +707,9 @@ curHandler.endBci = -1; curHandler.deoptBci = bci; curHandler.handler = h; - curHandler.getSuccessors().add(blockMap[h.getHandlerBCI()]); + curHandler.addSuccessor(blockMap[h.getHandlerBCI()]); if (lastHandler != null) { - curHandler.getSuccessors().add(lastHandler); + curHandler.addSuccessor(lastHandler); } exceptionDispatch.put(h, curHandler); } @@ -780,14 +721,14 @@ private boolean loopChanges; - private void fixLoopBits() { + private void fixLoopBits(BciBlock[] blockMap) { do { loopChanges = false; for (BciBlock b : blocks) { b.visited = false; } - long loop = fixLoopBits(blockMap[0]); + long loop = fixLoopBits(blockMap, blockMap[0]); if (loop != 0) { // There is a path from a loop end to the method entry that does not pass the loop @@ -800,7 +741,7 @@ } while (loopChanges); } - private void computeBlockOrder() { + private void computeBlockOrder(BciBlock[] blockMap) { int maxBlocks = blocksNotYetAssignedId; this.blocks = new BciBlock[blocksNotYetAssignedId]; long loop = computeBlockOrder(blockMap[0]); @@ -812,17 +753,9 @@ throw new BailoutException("Non-reducible loop"); } - if (blocks[0] != null && this.nextLoop == 0) { - // No unreached blocks and no loops - for (int i = 0; i < blocks.length; ++i) { - blocks[i].setId(i); - } - return; - } - // Purge null entries for unreached blocks and sort blocks such that loop bodies are always // consecutively in the array. - int blockCount = maxBlocks - blocksNotYetAssignedId; + int blockCount = maxBlocks - blocksNotYetAssignedId + 2; BciBlock[] newBlocks = new BciBlock[blockCount]; int next = 0; for (int i = 0; i < blocks.length; ++i) { @@ -830,11 +763,27 @@ if (b != null) { b.setId(next); newBlocks[next++] = b; - if (consecutiveLoopBlocks && b.isLoopHeader) { + if (b.isLoopHeader) { next = handleLoopHeader(newBlocks, next, i, b); } } } + + // Add return block. + BciBlock returnBlock = new BciBlock(); + returnBlock.startBci = returnBci; + returnBlock.endBci = returnBci; + returnBlock.setId(newBlocks.length - 2); + newBlocks[newBlocks.length - 2] = returnBlock; + + // Add unwind block. + ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(); + unwindBlock.startBci = -1; + unwindBlock.endBci = -1; + unwindBlock.deoptBci = method.isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI; + unwindBlock.setId(newBlocks.length - 1); + newBlocks[newBlocks.length - 1] = unwindBlock; + blocks = newBlocks; } @@ -857,7 +806,7 @@ return next; } - public void log(String name) { + public void log(BciBlock[] blockMap, String name) { if (Debug.isLogEnabled()) { String n = System.lineSeparator(); StringBuilder sb = new StringBuilder(Debug.currentScope()).append("BlockMap ").append(name).append(" :"); @@ -993,7 +942,7 @@ return loops; } - private long fixLoopBits(BciBlock block) { + private long fixLoopBits(BciBlock[] blockMap, BciBlock block) { if (block.visited) { // Return cached loop information for this block. if (block.isLoopHeader) { @@ -1007,7 +956,7 @@ long loops = block.loops; for (BciBlock successor : block.getSuccessors()) { // Recursively process successors. - loops |= fixLoopBits(successor); + loops |= fixLoopBits(blockMap, successor); } if (block.loops != loops) { loopChanges = true; @@ -1022,241 +971,9 @@ return loops; } - /** - * Encapsulates the liveness calculation, so that subclasses for locals ≤ 64 and locals > - * 64 can be implemented. - */ - public abstract class LocalLiveness { - - private void computeLiveness() { - for (BciBlock block : blocks) { - computeLocalLiveness(block); - } - - boolean changed; - int iteration = 0; - do { - Debug.log("Iteration %d", iteration); - changed = false; - for (int i = blocks.length - 1; i >= 0; i--) { - BciBlock block = blocks[i]; - int blockID = block.getId(); - // log statements in IFs because debugLiveX creates a new String - if (Debug.isLogEnabled()) { - Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), - debugLiveGen(blockID), debugLiveKill(blockID)); - } - - boolean blockChanged = (iteration == 0); - if (block.getSuccessorCount() > 0) { - int oldCardinality = liveOutCardinality(blockID); - for (BciBlock sux : block.getSuccessors()) { - if (Debug.isLogEnabled()) { - Debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); - } - propagateLiveness(blockID, sux.getId()); - } - blockChanged |= (oldCardinality != liveOutCardinality(blockID)); - } - - if (blockChanged) { - updateLiveness(blockID); - if (Debug.isLogEnabled()) { - Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), - debugLiveGen(blockID), debugLiveKill(blockID)); - } - } - changed |= blockChanged; - } - iteration++; - } while (changed); - } - - /** - * Returns whether the local is live at the beginning of the given block. - */ - public abstract boolean localIsLiveIn(BciBlock block, int local); - - /** - * Returns whether the local is set in the given loop. - */ - public abstract boolean localIsChangedInLoop(int loopId, int local); - - /** - * Returns whether the local is live at the end of the given block. - */ - public abstract boolean localIsLiveOut(BciBlock block, int local); - - /** - * Returns a string representation of the liveIn values of the given block. - */ - protected abstract String debugLiveIn(int blockID); - - /** - * Returns a string representation of the liveOut values of the given block. - */ - protected abstract String debugLiveOut(int blockID); - - /** - * Returns a string representation of the liveGen values of the given block. - */ - protected abstract String debugLiveGen(int blockID); - - /** - * Returns a string representation of the liveKill values of the given block. - */ - protected abstract String debugLiveKill(int blockID); - - /** - * Returns the number of live locals at the end of the given block. - */ - protected abstract int liveOutCardinality(int blockID); - - /** - * Adds all locals the are in the liveIn of the successor to the liveOut of the block. - */ - protected abstract void propagateLiveness(int blockID, int successorID); - - /** - * Calculates a new liveIn for the given block from liveOut, liveKill and liveGen. - */ - protected abstract void updateLiveness(int blockID); - - /** - * Adds the local to liveGen if it wasn't already killed in this block. - */ - protected abstract void loadOne(int blockID, int local); - - /** - * Add this local to liveKill if it wasn't already generated in this block. - */ - protected abstract void storeOne(int blockID, int local); - - private void computeLocalLiveness(BciBlock block) { - if (block.startBci < 0 || block.endBci < 0) { - return; - } - int blockID = block.getId(); - int localIndex; - stream.setBCI(block.startBci); - while (stream.currentBCI() <= block.endBci) { - switch (stream.currentBC()) { - case LLOAD: - case DLOAD: - loadTwo(blockID, stream.readLocalIndex()); - break; - case LLOAD_0: - case DLOAD_0: - loadTwo(blockID, 0); - break; - case LLOAD_1: - case DLOAD_1: - loadTwo(blockID, 1); - break; - case LLOAD_2: - case DLOAD_2: - loadTwo(blockID, 2); - break; - case LLOAD_3: - case DLOAD_3: - loadTwo(blockID, 3); - break; - case IINC: - localIndex = stream.readLocalIndex(); - loadOne(blockID, localIndex); - storeOne(blockID, localIndex); - break; - case ILOAD: - case FLOAD: - case ALOAD: - case RET: - loadOne(blockID, stream.readLocalIndex()); - break; - case ILOAD_0: - case FLOAD_0: - case ALOAD_0: - loadOne(blockID, 0); - break; - case ILOAD_1: - case FLOAD_1: - case ALOAD_1: - loadOne(blockID, 1); - break; - case ILOAD_2: - case FLOAD_2: - case ALOAD_2: - loadOne(blockID, 2); - break; - case ILOAD_3: - case FLOAD_3: - case ALOAD_3: - loadOne(blockID, 3); - break; - - case LSTORE: - case DSTORE: - storeTwo(blockID, stream.readLocalIndex()); - break; - case LSTORE_0: - case DSTORE_0: - storeTwo(blockID, 0); - break; - case LSTORE_1: - case DSTORE_1: - storeTwo(blockID, 1); - break; - case LSTORE_2: - case DSTORE_2: - storeTwo(blockID, 2); - break; - case LSTORE_3: - case DSTORE_3: - storeTwo(blockID, 3); - break; - case ISTORE: - case FSTORE: - case ASTORE: - storeOne(blockID, stream.readLocalIndex()); - break; - case ISTORE_0: - case FSTORE_0: - case ASTORE_0: - storeOne(blockID, 0); - break; - case ISTORE_1: - case FSTORE_1: - case ASTORE_1: - storeOne(blockID, 1); - break; - case ISTORE_2: - case FSTORE_2: - case ASTORE_2: - storeOne(blockID, 2); - break; - case ISTORE_3: - case FSTORE_3: - case ASTORE_3: - storeOne(blockID, 3); - break; - } - stream.next(); - } - } - - private void loadTwo(int blockID, int local) { - loadOne(blockID, local); - loadOne(blockID, local + 1); - } - - private void storeTwo(int blockID, int local) { - storeOne(blockID, local); - storeOne(blockID, local + 1); - } - } - - public static BciBlockMapping create(ResolvedJavaMethod method, boolean doLivenessAnalysis, boolean consecutiveLoopBlocks) { - BciBlockMapping map = new BciBlockMapping(method, doLivenessAnalysis, consecutiveLoopBlocks); - map.build(); + public static BciBlockMapping create(BytecodeStream stream, ResolvedJavaMethod method) { + BciBlockMapping map = new BciBlockMapping(method); + map.build(stream); if (Debug.isDumpEnabled()) { Debug.dump(map, method.format("After block building %f %R %H.%n(%P)")); } @@ -1264,228 +981,27 @@ return map; } - public final class SmallLocalLiveness extends LocalLiveness { - /* - * local n is represented by the bit accessible as (1 << n) - */ - - private final long[] localsLiveIn; - private final long[] localsLiveOut; - private final long[] localsLiveGen; - private final long[] localsLiveKill; - private final long[] localsChangedInLoop; - - public SmallLocalLiveness() { - int blockSize = blocks.length; - localsLiveIn = new long[blockSize]; - localsLiveOut = new long[blockSize]; - localsLiveGen = new long[blockSize]; - localsLiveKill = new long[blockSize]; - localsChangedInLoop = new long[BciBlockMapping.this.nextLoop]; - } - - private String debugString(long value) { - StringBuilder str = new StringBuilder("{"); - long current = value; - for (int i = 0; i < method.getMaxLocals(); i++) { - if ((current & 1L) == 1L) { - if (str.length() > 1) { - str.append(", "); - } - str.append(i); - } - current >>= 1; - } - return str.append('}').toString(); - } - - @Override - protected String debugLiveIn(int blockID) { - return debugString(localsLiveIn[blockID]); - } - - @Override - protected String debugLiveOut(int blockID) { - return debugString(localsLiveOut[blockID]); - } - - @Override - protected String debugLiveGen(int blockID) { - return debugString(localsLiveGen[blockID]); - } - - @Override - protected String debugLiveKill(int blockID) { - return debugString(localsLiveKill[blockID]); - } - - @Override - protected int liveOutCardinality(int blockID) { - return Long.bitCount(localsLiveOut[blockID]); - } - - @Override - protected void propagateLiveness(int blockID, int successorID) { - localsLiveOut[blockID] |= localsLiveIn[successorID]; - } - - @Override - protected void updateLiveness(int blockID) { - localsLiveIn[blockID] = (localsLiveOut[blockID] & ~localsLiveKill[blockID]) | localsLiveGen[blockID]; - } - - @Override - protected void loadOne(int blockID, int local) { - long bit = 1L << local; - if ((localsLiveKill[blockID] & bit) == 0L) { - localsLiveGen[blockID] |= bit; - } - } - - @Override - protected void storeOne(int blockID, int local) { - long bit = 1L << local; - if ((localsLiveGen[blockID] & bit) == 0L) { - localsLiveKill[blockID] |= bit; - } - - BciBlock block = blocks[blockID]; - long tmp = block.loops; - int pos = 0; - while (tmp != 0) { - if ((tmp & 1L) == 1L) { - this.localsChangedInLoop[pos] |= bit; - } - tmp >>= 1; - ++pos; - } - } - - @Override - public boolean localIsLiveIn(BciBlock block, int local) { - int blockID = block.getId(); - return blockID >= Integer.MAX_VALUE ? false : (localsLiveIn[blockID] & (1L << local)) != 0L; - } - - @Override - public boolean localIsLiveOut(BciBlock block, int local) { - int blockID = block.getId(); - return blockID >= Integer.MAX_VALUE ? false : (localsLiveOut[blockID] & (1L << local)) != 0L; - } - - @Override - public boolean localIsChangedInLoop(int loopId, int local) { - return (localsChangedInLoop[loopId] & (1L << local)) != 0L; - } - } - - public final class LargeLocalLiveness extends LocalLiveness { - private BitSet[] localsLiveIn; - private BitSet[] localsLiveOut; - private BitSet[] localsLiveGen; - private BitSet[] localsLiveKill; - private BitSet[] localsChangedInLoop; - - public LargeLocalLiveness() { - int blocksSize = blocks.length; - localsLiveIn = new BitSet[blocksSize]; - localsLiveOut = new BitSet[blocksSize]; - localsLiveGen = new BitSet[blocksSize]; - localsLiveKill = new BitSet[blocksSize]; - int maxLocals = method.getMaxLocals(); - for (int i = 0; i < blocksSize; i++) { - localsLiveIn[i] = new BitSet(maxLocals); - localsLiveOut[i] = new BitSet(maxLocals); - localsLiveGen[i] = new BitSet(maxLocals); - localsLiveKill[i] = new BitSet(maxLocals); - } - localsChangedInLoop = new BitSet[nextLoop]; - for (int i = 0; i < nextLoop; ++i) { - localsChangedInLoop[i] = new BitSet(maxLocals); - } - } - - @Override - protected String debugLiveIn(int blockID) { - return localsLiveIn[blockID].toString(); - } - - @Override - protected String debugLiveOut(int blockID) { - return localsLiveOut[blockID].toString(); - } - - @Override - protected String debugLiveGen(int blockID) { - return localsLiveGen[blockID].toString(); - } - - @Override - protected String debugLiveKill(int blockID) { - return localsLiveKill[blockID].toString(); - } - - @Override - protected int liveOutCardinality(int blockID) { - return localsLiveOut[blockID].cardinality(); - } - - @Override - protected void propagateLiveness(int blockID, int successorID) { - localsLiveOut[blockID].or(localsLiveIn[successorID]); - } - - @Override - protected void updateLiveness(int blockID) { - BitSet liveIn = localsLiveIn[blockID]; - liveIn.clear(); - liveIn.or(localsLiveOut[blockID]); - liveIn.andNot(localsLiveKill[blockID]); - liveIn.or(localsLiveGen[blockID]); - } - - @Override - protected void loadOne(int blockID, int local) { - if (!localsLiveKill[blockID].get(local)) { - localsLiveGen[blockID].set(local); - } - } - - @Override - protected void storeOne(int blockID, int local) { - if (!localsLiveGen[blockID].get(local)) { - localsLiveKill[blockID].set(local); - } - - BciBlock block = blocks[blockID]; - long tmp = block.loops; - int pos = 0; - while (tmp != 0) { - if ((tmp & 1L) == 1L) { - this.localsChangedInLoop[pos].set(local); - } - tmp >>= 1; - ++pos; - } - } - - @Override - public boolean localIsLiveIn(BciBlock block, int local) { - return block.getId() >= Integer.MAX_VALUE ? true : localsLiveIn[block.getId()].get(local); - } - - @Override - public boolean localIsLiveOut(BciBlock block, int local) { - return block.getId() >= Integer.MAX_VALUE ? true : localsLiveOut[block.getId()].get(local); - } - - @Override - public boolean localIsChangedInLoop(int loopId, int local) { - return localsChangedInLoop[loopId].get(local); - } - } - public BciBlock[] getLoopHeaders() { return loopHeaders; } + + public BciBlock getStartBlock() { + return startBlock; + } + + public BciBlock getReturnBlock() { + return blocks[blocks.length - 2]; + } + + public ExceptionDispatchBlock getUnwindBlock() { + return (ExceptionDispatchBlock) blocks[blocks.length - 1]; + } + + public int getLoopCount() { + return nextLoop; + } + + public int getBlockCount() { + return blocks.length; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java Mon Mar 02 19:11:22 2015 +0100 @@ -62,10 +62,11 @@ Map exitStates = ReentrantNodeIterator.processLoop(this, loop, 1D).exitStates; double exitProbability = exitStates.values().stream().mapToDouble(d -> d).sum(); - assert exitProbability <= 1D && exitProbability >= 0D; + exitProbability = Math.min(1D, exitProbability); if (exitProbability < MIN_PROBABILITY) { exitProbability = MIN_PROBABILITY; } + assert exitProbability <= 1D && exitProbability >= 0D; double loopFrequency = 1D / exitProbability; loop.setLoopFrequency(loopFrequency); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * 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 java.util.*; -import java.util.stream.*; - -import com.oracle.graal.api.meta.*; - -/** - * Default implementation of {@link GraphBuilderPlugins} that uses a map. - */ -public class DefaultGraphBuilderPlugins implements GraphBuilderPlugins { - - private final Map plugins = new HashMap<>(); - - /** - * Registers an invocation plugin for a given method. There must be no plugin currently - * registered for {@code method}. - */ - public void register(ResolvedJavaMethod method, InvocationPlugin plugin) { - assert InvocationPluginChecker.check(method, plugin); - GraphBuilderPlugin oldValue = plugins.put(method, plugin); - // System.out.println("registered: " + plugin); - assert oldValue == null; - } - - /** - * Gets the plugin for a given method. - * - * @param method the method to lookup - * @return the plugin associated with {@code method} or {@code null} if none exists - */ - public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { - return plugins.get(method); - } - - public DefaultGraphBuilderPlugins copy() { - DefaultGraphBuilderPlugins result = new DefaultGraphBuilderPlugins(); - result.plugins.putAll(plugins); - return result; - } - - @Override - public String toString() { - return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * 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 com.oracle.graal.api.directives.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.debug.*; -import com.oracle.graal.nodes.extended.*; - -public class GraalDirectivePlugins { - - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - Registration r = new Registration(plugins, metaAccess, GraalDirectives.class); - r.register0("deoptimize", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); - return true; - } - }); - - r.register0("deoptimizeAndInvalidate", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); - return true; - } - }); - - r.register0("inCompiledCode", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.push(Kind.Int, builder.append(ConstantNode.forInt(1))); - return true; - } - }); - - r.register0("controlFlowAnchor", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new ControlFlowAnchorNode()); - return true; - } - }); - - r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { - builder.push(Kind.Int, builder.append(new BranchProbabilityNode(probability, condition))); - return true; - } - }); - - InvocationPlugin blackholePlugin = new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.append(new BlackholeNode(value)); - return true; - } - }; - - for (Kind kind : Kind.values()) { - Class cls = null; - switch (kind) { - case Object: - cls = Object.class; - break; - case Void: - case Illegal: - continue; - default: - cls = kind.toJavaClass(); - } - - r.register1("blackhole", cls, blackholePlugin); - - final Kind stackKind = kind.getStackKind(); - r.register1("opaque", cls, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(stackKind, builder.append(new OpaqueNode(value))); - return true; - } - }); - } - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.java.GraphBuilderPlugin.AnnotatedInvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodes.*; public class GraphBuilderConfiguration { @@ -36,10 +41,13 @@ private final ResolvedJavaType[] skippedExceptionTypes; private final DebugInfoMode debugInfoMode; private final boolean doLivenessAnalysis; - private GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin; - private GraphBuilderPlugins.ParameterPlugin parameterPlugin; - private GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin; - private GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin; + private InvocationPlugins invocationPlugins = new InvocationPlugins(); + private LoadFieldPlugin loadFieldPlugin; + private ParameterPlugin parameterPlugin; + private InlineInvokePlugin inlineInvokePlugin; + private AnnotatedInvocationPlugin annotatedInvocationPlugin; + private LoopExplosionPlugin loopExplosionPlugin; + private boolean useProfiling; public static enum DebugInfoMode { SafePointsOnly, @@ -71,14 +79,24 @@ this.debugInfoMode = debugInfoMode; this.skippedExceptionTypes = skippedExceptionTypes; this.doLivenessAnalysis = doLivenessAnalysis; + this.useProfiling = true; } public GraphBuilderConfiguration copy() { GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis); - result.loadFieldPlugin = loadFieldPlugin; + result.useProfiling = useProfiling; + result.copyPluginsFrom(this); return result; } + public boolean getUseProfiling() { + return useProfiling; + } + + public void setUseProfiling(boolean b) { + this.useProfiling = b; + } + public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) { return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis); } @@ -96,12 +114,24 @@ return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis); } - public GraphBuilderPlugins.LoadFieldPlugin getLoadFieldPlugin() { + public InvocationPlugins getInvocationPlugins() { + return invocationPlugins; + } + + public AnnotatedInvocationPlugin getAnnotatedInvocationPlugin() { + return annotatedInvocationPlugin; + } + + public void setAnnotatedInvocationPlugin(AnnotatedInvocationPlugin plugin) { + this.annotatedInvocationPlugin = plugin; + } + + public LoadFieldPlugin getLoadFieldPlugin() { return loadFieldPlugin; } - public void setLoadFieldPlugin(GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin) { - this.loadFieldPlugin = loadFieldPlugin; + public void setLoadFieldPlugin(LoadFieldPlugin plugin) { + this.loadFieldPlugin = plugin; } public ResolvedJavaType[] getSkippedExceptionTypes() { @@ -153,27 +183,37 @@ return eagerResolving; } - public GraphBuilderPlugins.ParameterPlugin getParameterPlugin() { + public ParameterPlugin getParameterPlugin() { return parameterPlugin; } - public void setParameterPlugin(GraphBuilderPlugins.ParameterPlugin parameterPlugin) { - this.parameterPlugin = parameterPlugin; + public void setParameterPlugin(ParameterPlugin plugin) { + this.parameterPlugin = plugin; } - public GraphBuilderPlugins.InlineInvokePlugin getInlineInvokePlugin() { + public InlineInvokePlugin getInlineInvokePlugin() { return inlineInvokePlugin; } - public void setInlineInvokePlugin(GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin) { - this.inlineInvokePlugin = inlineInvokePlugin; + public void setInlineInvokePlugin(InlineInvokePlugin plugin) { + this.inlineInvokePlugin = plugin; } - public GraphBuilderPlugins.LoopExplosionPlugin getLoopExplosionPlugin() { + public LoopExplosionPlugin getLoopExplosionPlugin() { return loopExplosionPlugin; } - public void setLoopExplosionPlugin(GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin) { - this.loopExplosionPlugin = loopExplosionPlugin; + public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) { + this.loopExplosionPlugin = plugin; + } + + public GraphBuilderConfiguration copyPluginsFrom(GraphBuilderConfiguration other) { + this.invocationPlugins.updateFrom(other.getInvocationPlugins()); + this.parameterPlugin = other.parameterPlugin; + this.loadFieldPlugin = other.loadFieldPlugin; + this.inlineInvokePlugin = other.inlineInvokePlugin; + this.loopExplosionPlugin = other.loopExplosionPlugin; + this.annotatedInvocationPlugin = other.annotatedInvocationPlugin; + return this; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; /** @@ -56,6 +57,13 @@ void push(Kind kind, ValueNode value); + StructuredGraph getGraph(); + + /** + * Determines if the graph builder is parsing a snippet or method substitution. + */ + boolean parsingReplacement(); + /** * @see GuardingPiNode#nullCheckedValue(ValueNode) */ @@ -66,4 +74,8 @@ } return nonNullValue; } + + GuardingNode getCurrentBlockGuard(); + + BailoutException bailout(String string); } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,9 @@ import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.graph.iterators.NodePredicates.*; +import static com.oracle.graal.nodes.StructuredGraph.*; +import static java.lang.String.*; import java.util.*; @@ -38,16 +41,17 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.*; import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; -import com.oracle.graal.java.BciBlockMapping.LocalLiveness; -import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.LoopExplosionPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.AnnotatedInvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; @@ -65,30 +69,20 @@ public class GraphBuilderPhase extends BasePhase { private final GraphBuilderConfiguration graphBuilderConfig; - private final GraphBuilderPlugins graphBuilderPlugins; public GraphBuilderPhase(GraphBuilderConfiguration config) { - this(config, new DefaultGraphBuilderPlugins()); - } - - public GraphBuilderPhase(GraphBuilderConfiguration config, GraphBuilderPlugins graphBuilderPlugins) { this.graphBuilderConfig = config; - this.graphBuilderPlugins = graphBuilderPlugins; } @Override protected void run(StructuredGraph graph, HighTierContext context) { - new Instance(context.getMetaAccess(), context.getStampProvider(), null, context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins, context.getOptimisticOptimizations()).run(graph); + new Instance(context.getMetaAccess(), context.getStampProvider(), null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph); } public GraphBuilderConfiguration getGraphBuilderConfig() { return graphBuilderConfig; } - public GraphBuilderPlugins getGraphBuilderPlugins() { - return graphBuilderPlugins; - } - public static class Instance extends Phase { protected StructuredGraph currentGraph; @@ -98,7 +92,6 @@ private ResolvedJavaMethod rootMethod; private final GraphBuilderConfiguration graphBuilderConfig; - private final GraphBuilderPlugins graphBuilderPlugins; private final OptimisticOptimizations optimisticOpts; private final StampProvider stampProvider; private final ConstantReflectionProvider constantReflection; @@ -112,12 +105,11 @@ } public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, ConstantReflectionProvider constantReflection, - GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) { + GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; this.stampProvider = stampProvider; - this.graphBuilderPlugins = graphBuilderPlugins; this.constantReflection = constantReflection; this.snippetReflectionProvider = snippetReflectionProvider; assert metaAccess != null; @@ -125,7 +117,7 @@ public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, null, optimisticOpts); + this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, optimisticOpts); } @Override @@ -135,22 +127,33 @@ int entryBCI = graph.getEntryBCI(); assert method.getCode() != null : "method must contain bytecodes: " + method; this.currentGraph = graph; - HIRFrameStateBuilder frameState = new HIRFrameStateBuilder(method, graph, null); + HIRFrameStateBuilder frameState = new HIRFrameStateBuilder(method, graph, true, null); frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving(), this.graphBuilderConfig.getParameterPlugin()); TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); try { - BytecodeParser parser = new BytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, entryBCI); + BytecodeParser parser = new BytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, entryBCI, false); parser.build(0, graph.start(), frameState); parser.connectLoopEndToBegin(); - // remove dead parameters - for (ParameterNode param : currentGraph.getNodes(ParameterNode.class)) { + // Remove dead parameters. + for (ParameterNode param : currentGraph.getNodes(ParameterNode.TYPE)) { if (param.hasNoUsages()) { assert param.inputs().isEmpty(); param.safeDelete(); } } + + // Remove redundant begin nodes. + for (BeginNode beginNode : currentGraph.getNodes(BeginNode.TYPE)) { + Node predecessor = beginNode.predecessor(); + if (predecessor instanceof ControlSplitNode) { + // The begin node is necessary. + } else { + GraphUtil.unlinkFixedNode(beginNode); + beginNode.safeDelete(); + } + } } finally { filter.remove(); } @@ -176,13 +179,13 @@ private static class ExplodedLoopContext { private BciBlock header; - private int targetPeelIteration; + private int[] targetPeelIteration; private int peelIteration; } - public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { + public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { - private BciBlock[] loopHeaders; + private BciBlockMapping blockMap; private LocalLiveness liveness; protected final int entryBCI; private int currentDepth; @@ -192,8 +195,6 @@ private int currentLineNumber; private ValueNode methodSynchronizedObject; - private ExceptionDispatchBlock unwindBlock; - private BciBlock returnBlock; private ValueNode returnValue; private FixedWithNextNode beforeReturnNode; @@ -202,11 +203,25 @@ private FixedWithNextNode lastInstr; // the last instruction added private final boolean explodeLoops; + private final boolean mergeExplosions; + private final Map mergeExplosionsMap; private Stack explodeLoopsContext; private int nextPeelIteration = 1; + private boolean controlFlowSplit; - public BytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, int entryBCI) { - super(metaAccess, method, graphBuilderConfig, optimisticOpts); + private FixedWithNextNode[] firstInstructionArray; + private HIRFrameStateBuilder[] entryStateArray; + private FixedWithNextNode[][] firstInstructionMatrix; + private HIRFrameStateBuilder[][] entryStateMatrix; + + /** + * @param isReplacement specifies if this object is being used to parse a method that + * implements the semantics of another method (i.e., an intrinsic) or + * bytecode instruction (i.e., a snippet) + */ + public BytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, int entryBCI, + boolean isReplacement) { + super(metaAccess, method, graphBuilderConfig, optimisticOpts, isReplacement); this.entryBCI = entryBCI; if (graphBuilderConfig.insertNonSafepointDebugInfo()) { @@ -217,8 +232,17 @@ LoopExplosionPlugin loopExplosionPlugin = graphBuilderConfig.getLoopExplosionPlugin(); if (loopExplosionPlugin != null) { explodeLoops = loopExplosionPlugin.shouldExplodeLoops(method); + if (explodeLoops) { + mergeExplosions = loopExplosionPlugin.shouldMergeExplosions(method); + mergeExplosionsMap = new HashMap<>(); + } else { + mergeExplosions = false; + mergeExplosionsMap = null; + } } else { explodeLoops = false; + mergeExplosions = false; + mergeExplosionsMap = null; } } @@ -240,7 +264,7 @@ protected void build(int depth, FixedWithNextNode startInstruction, HIRFrameStateBuilder startFrameState) { this.currentDepth = depth; - if (PrintProfilingInformation.getValue()) { + if (PrintProfilingInformation.getValue() && profilingInfo != null) { TTY.println("Profiling info for " + method.format("%H.%n(%p)")); TTY.println(MetaUtil.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), " ")); } @@ -248,21 +272,33 @@ try (Indent indent = Debug.logAndIndent("build graph for %s", method)) { // compute the block map, setup exception handlers and get the entrypoint(s) - BciBlockMapping blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis(), explodeLoops); - loopHeaders = blockMap.getLoopHeaders(); - liveness = blockMap.liveness; + BciBlockMapping newMapping = BciBlockMapping.create(stream, method); + this.blockMap = newMapping; + this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()]; + this.entryStateArray = new HIRFrameStateBuilder[blockMap.getBlockCount()]; + + if (graphBuilderConfig.doLivenessAnalysis()) { + try (Scope s = Debug.scope("LivenessAnalysis")) { + int maxLocals = method.getMaxLocals(); + liveness = LocalLiveness.compute(stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount()); + } catch (Throwable e) { + throw Debug.handle(e); + } + } lastInstr = startInstruction; this.setCurrentFrameState(startFrameState); + stream.setBCI(0); + BciBlock startBlock = blockMap.getStartBlock(); if (startInstruction == currentGraph.start()) { StartNode startNode = currentGraph.start(); if (method.isSynchronized()) { - startNode.setStateAfter(frameState.create(BytecodeFrame.BEFORE_BCI)); + startNode.setStateAfter(createFrameState(BytecodeFrame.BEFORE_BCI)); } else { - frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true); + frameState.clearNonLiveLocals(startBlock, liveness, true); assert bci() == 0; - startNode.setStateAfter(frameState.create(bci())); + startNode.setStateAfter(createFrameState(bci())); } } @@ -270,21 +306,21 @@ // add a monitor enter to the start block methodSynchronizedObject = synchronizedObject(frameState, method); MonitorEnterNode monitorEnter = genMonitorEnter(methodSynchronizedObject); - frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true); + frameState.clearNonLiveLocals(startBlock, liveness, true); assert bci() == 0; - monitorEnter.setStateAfter(frameState.create(bci())); + monitorEnter.setStateAfter(createFrameState(bci())); } if (graphBuilderConfig.insertNonSafepointDebugInfo()) { append(createInfoPointNode(InfopointReason.METHOD_START)); } - currentBlock = blockMap.startBlock; - blockMap.startBlock.setEntryState(0, frameState); - if (blockMap.startBlock.isLoopHeader && !explodeLoops) { - appendGoto(createTarget(blockMap.startBlock, frameState)); + currentBlock = blockMap.getStartBlock(); + setEntryState(startBlock, 0, frameState); + if (startBlock.isLoopHeader && !explodeLoops) { + appendGoto(startBlock); } else { - blockMap.startBlock.setFirstInstruction(0, lastInstr); + setFirstInstruction(startBlock, 0, lastInstr); } int index = 0; @@ -293,15 +329,180 @@ BciBlock block = blocks[index]; index = iterateBlock(blocks, block); } - processBlock(this, returnBlock); - processBlock(this, unwindBlock); - if (Debug.isDumpEnabled()) { + if (this.mergeExplosions) { + Debug.dump(currentGraph, "Before loop detection"); + detectLoops(startInstruction); + } + + if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue() && this.beforeReturnNode != startInstruction) { Debug.dump(currentGraph, "Bytecodes parsed: " + method.getDeclaringClass().getUnqualifiedName() + "." + method.getName()); } } } + private void detectLoops(FixedNode startInstruction) { + NodeBitMap visited = currentGraph.createNodeBitMap(); + NodeBitMap active = currentGraph.createNodeBitMap(); + Stack stack = new Stack<>(); + stack.add(startInstruction); + visited.mark(startInstruction); + while (!stack.isEmpty()) { + Node next = stack.peek(); + assert next.isDeleted() || visited.isMarked(next); + if (next.isDeleted() || active.isMarked(next)) { + stack.pop(); + if (!next.isDeleted()) { + active.clear(next); + } + } else { + active.mark(next); + for (Node n : next.cfgSuccessors()) { + if (active.contains(n)) { + // Detected cycle. + assert n instanceof MergeNode; + assert next instanceof EndNode; + MergeNode merge = (MergeNode) n; + EndNode endNode = (EndNode) next; + merge.removeEnd(endNode); + FixedNode afterMerge = merge.next(); + if (!(afterMerge instanceof EndNode) || !(((EndNode) afterMerge).merge() instanceof LoopBeginNode)) { + merge.setNext(null); + LoopBeginNode newLoopBegin = this.appendLoopBegin(merge); + newLoopBegin.setNext(afterMerge); + } + LoopBeginNode loopBegin = (LoopBeginNode) ((EndNode) merge.next()).merge(); + LoopEndNode loopEnd = currentGraph.add(new LoopEndNode(loopBegin)); + endNode.replaceAndDelete(loopEnd); + } else if (visited.contains(n)) { + // Normal merge into a branch we are already exploring. + } else { + visited.mark(n); + stack.push(n); + } + } + } + } + + Debug.dump(currentGraph, "After loops detected"); + insertLoopEnds(startInstruction); + } + + private void insertLoopEnds(FixedNode startInstruction) { + NodeBitMap visited = currentGraph.createNodeBitMap(); + Stack stack = new Stack<>(); + stack.add(startInstruction); + visited.mark(startInstruction); + List loopBegins = new ArrayList<>(); + while (!stack.isEmpty()) { + Node next = stack.pop(); + assert visited.isMarked(next); + if (next instanceof LoopBeginNode) { + loopBegins.add((LoopBeginNode) next); + } + for (Node n : next.cfgSuccessors()) { + if (visited.contains(n)) { + // Nothing to do. + } else { + visited.mark(n); + stack.push(n); + } + } + } + + IdentityHashMap> innerLoopsMap = new IdentityHashMap<>(); + for (int i = loopBegins.size() - 1; i >= 0; --i) { + LoopBeginNode loopBegin = loopBegins.get(i); + insertLoopExits(loopBegin, innerLoopsMap); + if (GraalOptions.DumpDuringGraphBuilding.getValue()) { + Debug.dump(currentGraph, "After building loop exits for %s.", loopBegin); + } + } + + // Remove degenerated merges with only one predecessor. + for (LoopBeginNode loopBegin : loopBegins) { + Node pred = loopBegin.forwardEnd().predecessor(); + if (pred instanceof MergeNode) { + MergeNode.removeMergeIfDegenerated((MergeNode) pred); + } + } + } + + private void insertLoopExits(LoopBeginNode loopBegin, IdentityHashMap> innerLoopsMap) { + NodeBitMap visited = currentGraph.createNodeBitMap(); + Stack stack = new Stack<>(); + for (LoopEndNode loopEnd : loopBegin.loopEnds()) { + stack.push(loopEnd); + visited.mark(loopEnd); + } + + List controlSplits = new ArrayList<>(); + List innerLoopBegins = new ArrayList<>(); + + while (!stack.isEmpty()) { + Node current = stack.pop(); + if (current == loopBegin) { + continue; + } + for (Node pred : current.cfgPredecessors()) { + if (!visited.isMarked(pred)) { + visited.mark(pred); + if (pred instanceof LoopExitNode) { + // Inner loop + LoopExitNode loopExitNode = (LoopExitNode) pred; + LoopBeginNode innerLoopBegin = loopExitNode.loopBegin(); + if (!visited.isMarked(innerLoopBegin)) { + stack.push(innerLoopBegin); + visited.mark(innerLoopBegin); + innerLoopBegins.add(innerLoopBegin); + } + } else { + if (pred instanceof ControlSplitNode) { + ControlSplitNode controlSplitNode = (ControlSplitNode) pred; + controlSplits.add(controlSplitNode); + } + stack.push(pred); + } + } + } + } + + for (ControlSplitNode controlSplit : controlSplits) { + for (Node succ : controlSplit.cfgSuccessors()) { + if (!visited.isMarked(succ)) { + LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin)); + FixedNode next = ((FixedWithNextNode) succ).next(); + next.replaceAtPredecessor(loopExit); + loopExit.setNext(next); + } + } + } + + for (LoopBeginNode inner : innerLoopBegins) { + addLoopExits(loopBegin, inner, innerLoopsMap, visited); + if (GraalOptions.DumpDuringGraphBuilding.getValue()) { + Debug.dump(currentGraph, "After adding loop exits for %s.", inner); + } + } + + innerLoopsMap.put(loopBegin, innerLoopBegins); + } + + private void addLoopExits(LoopBeginNode loopBegin, LoopBeginNode inner, IdentityHashMap> innerLoopsMap, NodeBitMap visited) { + for (LoopExitNode exit : inner.loopExits()) { + if (!visited.isMarked(exit)) { + LoopExitNode newLoopExit = currentGraph.add(new LoopExitNode(loopBegin)); + FixedNode next = exit.next(); + next.replaceAtPredecessor(newLoopExit); + newLoopExit.setNext(next); + } + } + + for (LoopBeginNode innerInner : innerLoopsMap.get(inner)) { + addLoopExits(loopBegin, innerInner, innerLoopsMap, visited); + } + } + private int iterateBlock(BciBlock[] blocks, BciBlock block) { if (block.isLoopHeader && this.explodeLoops) { return iterateExplodedLoopHeader(blocks, block); @@ -319,52 +520,49 @@ ExplodedLoopContext context = new ExplodedLoopContext(); context.header = header; context.peelIteration = this.getCurrentDimension(); - context.targetPeelIteration = -1; + if (this.mergeExplosions) { + this.addToMergeCache(getEntryState(context.header, context.peelIteration), context.peelIteration); + } explodeLoopsContext.push(context); - Debug.dump(currentGraph, "before loop explosion " + context.peelIteration); + if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue()) { + Debug.dump(currentGraph, "before loop explosion dimension " + context.peelIteration); + } + peelIteration(blocks, header, context); + explodeLoopsContext.pop(); + return header.loopEnd + 1; + } + + private void addToMergeCache(HIRFrameStateBuilder key, int dimension) { + mergeExplosionsMap.put(key, dimension); + } + + private void peelIteration(BciBlock[] blocks, BciBlock header, ExplodedLoopContext context) { while (true) { - processBlock(this, header); for (int j = header.getId() + 1; j <= header.loopEnd; ++j) { BciBlock block = blocks[j]; iterateBlock(blocks, block); } - if (context.targetPeelIteration != -1) { + int[] targets = context.targetPeelIteration; + if (targets != null) { // We were reaching the backedge during explosion. Explode further. - Debug.dump(currentGraph, "Before loop explosion " + context.targetPeelIteration); - context.peelIteration = context.targetPeelIteration; - context.targetPeelIteration = -1; + for (int i = 0; i < targets.length; ++i) { + context.peelIteration = targets[i]; + context.targetPeelIteration = null; + if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue()) { + Debug.dump(currentGraph, "next loop explosion iteration " + context.peelIteration); + } + if (i < targets.length - 1) { + peelIteration(blocks, header, context); + } + } } else { // We did not reach the backedge. Exit. - Debug.dump(currentGraph, "after loop explosion " + context.peelIteration); break; } } - explodeLoopsContext.pop(); - return header.loopEnd + 1; - } - - private BciBlock returnBlock(int bci) { - if (returnBlock == null) { - returnBlock = new BciBlock(); - returnBlock.startBci = bci; - returnBlock.endBci = bci; - returnBlock.setId(Integer.MAX_VALUE); - } - return returnBlock; - } - - private BciBlock unwindBlock() { - if (unwindBlock == null) { - unwindBlock = new ExceptionDispatchBlock(); - unwindBlock.startBci = -1; - unwindBlock.endBci = -1; - unwindBlock.deoptBci = method.isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI; - unwindBlock.setId(Integer.MAX_VALUE); - } - return unwindBlock; } /** @@ -473,7 +671,7 @@ private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci"; - Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); + Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci))); BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock(); /* @@ -482,7 +680,7 @@ * unwind immediately. */ if (bci != currentBlock.endBci || dispatchBlock == null) { - dispatchBlock = unwindBlock(); + dispatchBlock = blockMap.getUnwindBlock(); } HIRFrameStateBuilder dispatchState = frameState.copy(); @@ -500,6 +698,7 @@ dispatchBegin.setStateAfter(dispatchState.create(bci)); dispatchState.setRethrowException(true); } + this.controlFlowSplit = true; FixedNode target = createTarget(dispatchBlock, dispatchState); FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, dispatchState); finishedDispatch.setNext(target); @@ -528,7 +727,7 @@ @Override protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) { - return new MulNode(x, y); + return MulNode.create(x, y); } @Override @@ -543,12 +742,12 @@ @Override protected ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new MulNode(x, y); + return MulNode.create(x, y); } @Override protected ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new DivNode(x, y); + return DivNode.create(x, y); } @Override @@ -588,62 +787,62 @@ @Override protected ValueNode genAnd(Kind kind, ValueNode x, ValueNode y) { - return new AndNode(x, y); + return AndNode.create(x, y); } @Override protected ValueNode genOr(Kind kind, ValueNode x, ValueNode y) { - return new OrNode(x, y); + return OrNode.create(x, y); } @Override protected ValueNode genXor(Kind kind, ValueNode x, ValueNode y) { - return new XorNode(x, y); + return XorNode.create(x, y); } @Override protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) { - return new NormalizeCompareNode(x, y, isUnorderedLess); + return NormalizeCompareNode.create(x, y, isUnorderedLess, constantReflection); } @Override protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) { - return new FloatConvertNode(op, input); + return FloatConvertNode.create(op, input); } @Override protected ValueNode genNarrow(ValueNode input, int bitCount) { - return new NarrowNode(input, bitCount); + return NarrowNode.create(input, bitCount); } @Override protected ValueNode genSignExtend(ValueNode input, int bitCount) { - return new SignExtendNode(input, bitCount); + return SignExtendNode.create(input, bitCount); } @Override protected ValueNode genZeroExtend(ValueNode input, int bitCount) { - return new ZeroExtendNode(input, bitCount); + return ZeroExtendNode.create(input, bitCount); } @Override protected void genGoto() { - appendGoto(createTarget(currentBlock.getSuccessors().get(0), frameState)); + appendGoto(currentBlock.getSuccessor(0)); assert currentBlock.numNormalSuccessors() == 1; } @Override - protected ValueNode genObjectEquals(ValueNode x, ValueNode y) { + protected LogicNode genObjectEquals(ValueNode x, ValueNode y) { return ObjectEqualsNode.create(x, y, constantReflection); } @Override - protected ValueNode genIntegerEquals(ValueNode x, ValueNode y) { + protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) { return IntegerEqualsNode.create(x, y, constantReflection); } @Override - protected ValueNode genIntegerLessThan(ValueNode x, ValueNode y) { + protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) { return IntegerLessThanNode.create(x, y, constantReflection); } @@ -652,8 +851,8 @@ return (ValueNode) currentGraph.unique((Node & ValueNumberable) x); } - protected ValueNode genIfNode(ValueNode condition, ValueNode falseSuccessor, ValueNode trueSuccessor, double d) { - return new IfNode((LogicNode) condition, (FixedNode) falseSuccessor, (FixedNode) trueSuccessor, d); + protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) { + return new IfNode(condition, falseSuccessor, trueSuccessor, d); } @Override @@ -708,7 +907,7 @@ append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), exception, falseSucc, 0.01)); lastInstr = falseSucc; - exception.setStateAfter(frameState.create(bci())); + exception.setStateAfter(createFrameState(bci())); exception.setNext(handleException(exception, bci())); } @@ -719,7 +918,7 @@ append(new IfNode(currentGraph.unique(IntegerBelowNode.create(index, length, constantReflection)), trueSucc, exception, 0.99)); lastInstr = trueSucc; - exception.setStateAfter(frameState.create(bci())); + exception.setStateAfter(createFrameState(bci())); exception.setNext(handleException(exception, bci())); } @@ -853,48 +1052,35 @@ } if (invokeKind.hasReceiver()) { emitExplicitExceptions(args[0], null); - if (invokeKind.isIndirect() && this.optimisticOpts.useTypeCheckHints()) { + if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints()) { JavaTypeProfile profile = profilingInfo.getTypeProfile(bci()); args[0] = TypeProfileProxyNode.proxify(args[0], profile); } } - if (graphBuilderPlugins != null) { - if (tryUsingInvocationPlugin(args, targetMethod, resultType)) { - if (GraalOptions.TraceInlineDuringParsing.getValue()) { - for (int i = 0; i < this.currentDepth; ++i) { - TTY.print(' '); - } - TTY.println("Used invocation plugin for " + targetMethod); - } - return; + if (tryInvocationPlugin(args, targetMethod, resultType)) { + if (GraalOptions.TraceInlineDuringParsing.getValue()) { + TTY.println(format("%sUsed invocation plugin for %s", nSpaces(currentDepth), targetMethod)); } + return; } - InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin(); - if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() && - inlineInvokePlugin.shouldInlineInvoke(targetMethod, currentDepth)) { + if (tryAnnotatedInvocationPlugin(args, targetMethod)) { if (GraalOptions.TraceInlineDuringParsing.getValue()) { - int bci = this.bci(); - for (int i = 0; i < this.currentDepth; ++i) { - TTY.print(' '); - } - StackTraceElement stackTraceElement = this.method.asStackTraceElement(bci); - String s = String.format("%s (%s:%d)", method.getName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber()); - TTY.print(s); - TTY.println(" inlining call " + targetMethod.getName()); + TTY.println(format("%sUsed annotated invocation plugin for %s", nSpaces(currentDepth), targetMethod)); } - parseAndInlineCallee(targetMethod, args); return; - } else { - // System.out.println("Could not inline invoke " + targetMethod); + } + + if (tryInline(args, targetMethod, invokeKind, returnType)) { + return; } MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); // be conservative if information was not recorded (could result in endless // recompiles otherwise) - if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { + if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo != null && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { createInvoke(callTarget, resultType); } else { InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType); @@ -904,16 +1090,17 @@ } } - private boolean tryUsingInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) { - InvocationPlugin plugin = graphBuilderPlugins.lookupInvocation(targetMethod); + private boolean tryInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) { + InvocationPlugin plugin = graphBuilderConfig.getInvocationPlugins().lookupInvocation(targetMethod); if (plugin != null) { int beforeStackSize = frameState.stackSize; - boolean needsNullCheck = !targetMethod.isStatic() && !StampTool.isPointerNonNull(args[0].stamp()); + boolean needsNullCheck = !targetMethod.isStatic() && args[0].getKind() == Kind.Object && !StampTool.isPointerNonNull(args[0].stamp()); int nodeCount = currentGraph.getNodeCount(); Mark mark = needsNullCheck ? currentGraph.getMark() : null; if (InvocationPlugin.execute(this, plugin, args)) { - assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize : "plugin manipulated the stack incorrectly"; - assert !needsNullCheck || containsNullCheckOf(currentGraph.getNewNodes(mark), args[0]) : "plugin needs to null check the receiver of " + targetMethod + ": " + args[0]; + assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize : "plugin manipulated the stack incorrectly " + targetMethod; + assert !needsNullCheck || args[0].usages().filter(isNotA(FrameState.class)).isEmpty() || containsNullCheckOf(currentGraph.getNewNodes(mark), args[0]) : "plugin needs to null check the receiver of " + + targetMethod + ": " + args[0]; return true; } assert nodeCount == currentGraph.getNodeCount() : "plugin that returns false must not create new nodes"; @@ -922,6 +1109,11 @@ return false; } + private boolean tryAnnotatedInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod) { + AnnotatedInvocationPlugin plugin = graphBuilderConfig.getAnnotatedInvocationPlugin(); + return plugin != null && plugin.apply(this, targetMethod, args); + } + private boolean containsNullCheckOf(NodeIterable nodes, Node value) { for (Node n : nodes) { if (n instanceof GuardingPiNode) { @@ -934,12 +1126,38 @@ return false; } - private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args) { - BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI); + private boolean tryInline(ValueNode[] args, ResolvedJavaMethod targetMethod, InvokeKind invokeKind, JavaType returnType) { + InlineInvokePlugin plugin = graphBuilderConfig.getInlineInvokePlugin(); + if (plugin == null || !invokeKind.isDirect() || !targetMethod.canBeInlined()) { + return false; + } + ResolvedJavaMethod inlinedMethod = plugin.getInlinedMethod(this, targetMethod, args, returnType, currentDepth); + if (inlinedMethod != null && inlinedMethod.hasBytecodes()) { + if (TraceInlineDuringParsing.getValue()) { + int bci = this.bci(); + StackTraceElement ste = this.method.asStackTraceElement(bci); + TTY.println(format("%s%s (%s:%d) inlining call to %s", nSpaces(currentDepth), method.getName(), ste.getFileName(), ste.getLineNumber(), inlinedMethod.format("%h.%n(%p)"))); + } + parseAndInlineCallee(inlinedMethod, args, parsingReplacement || !inlinedMethod.equals(targetMethod)); + plugin.postInline(inlinedMethod); + return true; + } + + return false; + } + + private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, boolean isReplacement) { + BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, INVOCATION_ENTRY_BCI, isReplacement); final FrameState[] lazyFrameState = new FrameState[1]; - HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> { + + // Replacements often produce nodes with an illegal kind (e.g., pointer stamps) + // so the frame state builder should not check the types flowing through the frame + // since all such assertions are in terms of Java kinds. + boolean checkTypes = !isReplacement; + + HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, checkTypes, () -> { if (lazyFrameState[0] == null) { - lazyFrameState[0] = frameState.create(bci()); + lazyFrameState[0] = createFrameState(bci()); } return lazyFrameState[0]; }); @@ -959,15 +1177,6 @@ if (calleeBeforeUnwindNode != null) { ValueNode calleeUnwindValue = parser.getUnwindValue(); assert calleeUnwindValue != null; - if (calleeBeforeUnwindNode instanceof AbstractMergeNode) { - AbstractMergeNode mergeNode = (AbstractMergeNode) calleeBeforeUnwindNode; - HIRFrameStateBuilder dispatchState = frameState.copy(); - dispatchState.clearStack(); - dispatchState.apush(calleeUnwindValue); - dispatchState.setRethrowException(true); - mergeNode.setStateAfter(dispatchState.create(bci())); - - } calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci())); } @@ -991,23 +1200,34 @@ DispatchBeginNode exceptionEdge = handleException(null, bci()); InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); frameState.pushReturn(resultType, invoke); - invoke.setStateAfter(frameState.create(stream.nextBCI())); + invoke.setStateAfter(createFrameState(stream.nextBCI())); return invoke; } @Override protected void genReturn(ValueNode x) { - frameState.setRethrowException(false); - frameState.clearStack(); if (this.currentDepth == 0) { + frameState.setRethrowException(false); + frameState.clearStack(); beforeReturn(x); append(new ReturnNode(x)); } else { - if (x != null) { - frameState.push(x.getKind(), x); + if (blockMap.getReturnCount() == 1 || !controlFlowSplit) { + // There is only a single return. + beforeReturn(x); + this.returnValue = x; + this.beforeReturnNode = this.lastInstr; + this.lastInstr = null; + } else { + frameState.setRethrowException(false); + frameState.clearStack(); + if (x != null) { + frameState.push(x.getKind(), x); + } + assert blockMap.getReturnCount() > 1; + appendGoto(blockMap.getReturnBlock()); } - appendGoto(createTarget(returnBlock(bci()), frameState)); } } @@ -1018,7 +1238,7 @@ synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x); if (frameState.lockDepth() != 0) { - throw new BailoutException("unbalanced monitors"); + throw bailout("unbalanced monitors"); } } @@ -1035,7 +1255,7 @@ MonitorIdNode monitorId = frameState.peekMonitorId(); ValueNode lockedObject = frameState.popLock(); if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { - throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); + throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject))); } MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, escapedReturnValue)); return monitorExit; @@ -1055,7 +1275,7 @@ } ConstantNode nextBciNode = getJsrConstant(nextBci); frameState.push(Kind.Int, nextBciNode); - appendGoto(createTarget(successor, frameState)); + appendGoto(successor); } @Override @@ -1071,7 +1291,7 @@ if (!successor.getJsrScope().equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); } - appendGoto(createTarget(successor, frameState)); + appendGoto(successor); } private ConstantNode getJsrConstant(long bci) { @@ -1083,10 +1303,23 @@ @Override protected void genIntegerSwitch(ValueNode value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { - double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); - IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); - for (int i = 0; i < actualSuccessors.size(); i++) { - switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); + if (value.isConstant()) { + JavaConstant constant = (JavaConstant) value.asConstant(); + int constantValue = constant.asInt(); + for (int i = 0; i < keys.length; ++i) { + if (keys[i] == constantValue) { + appendGoto(actualSuccessors.get(keySuccessors[i])); + return; + } + } + appendGoto(actualSuccessors.get(keySuccessors[keys.length])); + } else { + this.controlFlowSplit = true; + double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); + IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); + for (int i = 0; i < actualSuccessors.size(); i++) { + switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); + } } } @@ -1146,6 +1379,9 @@ } public T append(T v) { + if (v.graph() != null) { + return v; + } T added = currentGraph.unique(v); return added; } @@ -1162,7 +1398,7 @@ do { long lMask = 1L << pos; if ((exits & lMask) != 0) { - exitLoops.add(loopHeaders[pos]); + exitLoops.add(blockMap.getLoopHeader(pos)); exits &= ~lMask; } pos++; @@ -1182,7 +1418,7 @@ } HIRFrameStateBuilder newState = state.copy(); for (BciBlock loop : exitLoops) { - LoopBeginNode loopBegin = (LoopBeginNode) loop.getFirstInstruction(this.getCurrentDimension()); + LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(loop, this.getCurrentDimension()); LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin)); if (lastLoopExit != null) { lastLoopExit.setNext(loopExit); @@ -1191,8 +1427,8 @@ firstLoopExit = loopExit; } lastLoopExit = loopExit; - Debug.log("Target %s (%s) Exits %s, scanning framestates...", targetBlock, target, loop); - newState.insertLoopProxies(loopExit, (HIRFrameStateBuilder) loop.getEntryState(this.getCurrentDimension())); + Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); + newState.insertLoopProxies(loopExit, getEntryState(loop, this.getCurrentDimension())); loopExit.setStateAfter(newState.create(bci)); } @@ -1203,6 +1439,98 @@ return new Target(target, state); } + private HIRFrameStateBuilder getEntryState(BciBlock block, int dimension) { + int id = block.id; + if (dimension == 0) { + return entryStateArray[id]; + } else { + return getEntryStateMultiDimension(dimension, id); + } + } + + private HIRFrameStateBuilder getEntryStateMultiDimension(int dimension, int id) { + if (entryStateMatrix != null && dimension - 1 < entryStateMatrix.length) { + HIRFrameStateBuilder[] entryStateArrayEntry = entryStateMatrix[dimension - 1]; + if (entryStateArrayEntry == null) { + return null; + } + return entryStateArrayEntry[id]; + } else { + return null; + } + } + + private void setEntryState(BciBlock block, int dimension, HIRFrameStateBuilder entryState) { + int id = block.id; + if (dimension == 0) { + this.entryStateArray[id] = entryState; + } else { + setEntryStateMultiDimension(dimension, entryState, id); + } + } + + private void setEntryStateMultiDimension(int dimension, HIRFrameStateBuilder entryState, int id) { + if (entryStateMatrix == null) { + entryStateMatrix = new HIRFrameStateBuilder[4][]; + } + if (dimension - 1 < entryStateMatrix.length) { + // We are within bounds. + } else { + // We are out of bounds. + entryStateMatrix = Arrays.copyOf(entryStateMatrix, Math.max(entryStateMatrix.length * 2, dimension)); + } + if (entryStateMatrix[dimension - 1] == null) { + entryStateMatrix[dimension - 1] = new HIRFrameStateBuilder[blockMap.getBlockCount()]; + } + entryStateMatrix[dimension - 1][id] = entryState; + } + + private void setFirstInstruction(BciBlock block, int dimension, FixedWithNextNode firstInstruction) { + int id = block.id; + if (dimension == 0) { + this.firstInstructionArray[id] = firstInstruction; + } else { + setFirstInstructionMultiDimension(dimension, firstInstruction, id); + } + } + + private void setFirstInstructionMultiDimension(int dimension, FixedWithNextNode firstInstruction, int id) { + if (firstInstructionMatrix == null) { + firstInstructionMatrix = new FixedWithNextNode[4][]; + } + if (dimension - 1 < firstInstructionMatrix.length) { + // We are within bounds. + } else { + // We are out of bounds. + firstInstructionMatrix = Arrays.copyOf(firstInstructionMatrix, Math.max(firstInstructionMatrix.length * 2, dimension)); + } + if (firstInstructionMatrix[dimension - 1] == null) { + firstInstructionMatrix[dimension - 1] = new FixedWithNextNode[blockMap.getBlockCount()]; + } + firstInstructionMatrix[dimension - 1][id] = firstInstruction; + } + + private FixedWithNextNode getFirstInstruction(BciBlock block, int dimension) { + int id = block.id; + if (dimension == 0) { + return firstInstructionArray[id]; + } else { + return getFirstInstructionMultiDimension(dimension, id); + } + } + + private FixedWithNextNode getFirstInstructionMultiDimension(int dimension, int id) { + if (firstInstructionMatrix != null && dimension - 1 < firstInstructionMatrix.length) { + FixedWithNextNode[] firstInstructionArrayEntry = firstInstructionMatrix[dimension - 1]; + if (firstInstructionArrayEntry == null) { + return null; + } + return firstInstructionArrayEntry[id]; + } else { + return null; + } + } + private FixedNode createTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) { assert probability >= 0 && probability <= 1.01 : probability; if (isNeverExecutedCode(probability)) { @@ -1214,124 +1542,156 @@ } private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) { + return createTarget(block, state, false, false); + } + + private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) { assert block != null && state != null; assert !block.isExceptionEntry || state.stackSize() == 1; - int operatingDimension = this.getCurrentDimension(); - if (this.explodeLoops && this.explodeLoopsContext != null && !this.explodeLoopsContext.isEmpty()) { - int i; - for (i = explodeLoopsContext.size() - 1; i >= 0; --i) { - ExplodedLoopContext context = explodeLoopsContext.elementAt(i); - if (context.header == block) { - - // We have a hit on our current explosion context loop begin. - if (context.targetPeelIteration == -1) { - // This is the first hit => allocate a new dimension and at the same - // time mark the context loop begin as hit during the current - // iteration. - context.targetPeelIteration = nextPeelIteration++; - if (nextPeelIteration > GraalOptions.MaximumLoopExplosionCount.getValue()) { - throw new BailoutException("too many loop explosion interations - does the explosion not terminate?"); - } - } + int operatingDimension = findOperatingDimension(block, state); - // Operate on the target dimension. - operatingDimension = context.targetPeelIteration; - break; - } else if (block.getId() > context.header.getId() && block.getId() <= context.header.loopEnd) { - // We hit the range of this context. - operatingDimension = context.peelIteration; - break; - } - } - - if (i == -1) { - // I did not find a dimension. - operatingDimension = 0; - } - } - - if (block.getFirstInstruction(operatingDimension) == null) { + if (getFirstInstruction(block, operatingDimension) == null) { /* * This is the first time we see this block as a branch target. Create and * return a placeholder that later can be replaced with a MergeNode when we see * this block again. */ FixedNode targetNode; - block.setFirstInstruction(operatingDimension, currentGraph.add(new BeginNode())); - targetNode = block.getFirstInstruction(operatingDimension); + if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) { + setFirstInstruction(block, operatingDimension, lastInstr); + lastInstr = null; + } else { + setFirstInstruction(block, operatingDimension, currentGraph.add(new BeginNode())); + } + targetNode = getFirstInstruction(block, operatingDimension); Target target = checkLoopExit(targetNode, block, state); FixedNode result = target.fixed; - AbstractFrameStateBuilder entryState = target.state == state ? state.copy() : target.state; - block.setEntryState(operatingDimension, entryState); - entryState.clearNonLiveLocals(block, liveness, true); + HIRFrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state; + setEntryState(block, operatingDimension, currentEntryState); + currentEntryState.clearNonLiveLocals(block, liveness, true); Debug.log("createTarget %s: first visit, result: %s", block, targetNode); return result; } // We already saw this block before, so we have to merge states. - if (!((HIRFrameStateBuilder) block.getEntryState(operatingDimension)).isCompatibleWith(state)) { - throw new BailoutException("stacks do not match; bytecodes would not verify"); + if (!getEntryState(block, operatingDimension).isCompatibleWith(state)) { + throw bailout("stacks do not match; bytecodes would not verify"); } - if (block.getFirstInstruction(operatingDimension) instanceof LoopBeginNode) { + if (getFirstInstruction(block, operatingDimension) instanceof LoopBeginNode) { assert this.explodeLoops || (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch"; /* * Backward loop edge. We need to create a special LoopEndNode and merge with * the loop begin node created before. */ - LoopBeginNode loopBegin = (LoopBeginNode) block.getFirstInstruction(operatingDimension); + LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block, operatingDimension); Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state); FixedNode result = target.fixed; - ((HIRFrameStateBuilder) block.getEntryState(operatingDimension)).merge(loopBegin, target.state); + getEntryState(block, operatingDimension).merge(loopBegin, target.state); Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); return result; } - assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch"; - assert block.getFirstInstruction(operatingDimension).next() == null : "bytecodes already parsed for block"; + assert currentBlock == null || currentBlock.getId() < block.getId() || this.mergeExplosions : "must not be backward branch"; + assert getFirstInstruction(block, operatingDimension).next() == null || this.mergeExplosions : "bytecodes already parsed for block"; - if (block.getFirstInstruction(operatingDimension) instanceof AbstractBeginNode && !(block.getFirstInstruction(operatingDimension) instanceof AbstractMergeNode)) { + if (getFirstInstruction(block, operatingDimension) instanceof AbstractBeginNode && !(getFirstInstruction(block, operatingDimension) instanceof AbstractMergeNode)) { /* * This is the second time we see this block. Create the actual MergeNode and - * the End Node for the already existing edge. For simplicity, we leave the - * placeholder in the graph and just append the new nodes after the placeholder. + * the End Node for the already existing edge. */ - AbstractBeginNode placeholder = (AbstractBeginNode) block.getFirstInstruction(operatingDimension); + AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block, operatingDimension); // The EndNode for the already existing edge. - AbstractEndNode end = currentGraph.add(new EndNode()); + EndNode end = currentGraph.add(new EndNode()); // The MergeNode that replaces the placeholder. AbstractMergeNode mergeNode = currentGraph.add(new MergeNode()); - FixedNode next = placeholder.next(); + FixedNode next = beginNode.next(); - if (placeholder.predecessor() instanceof ControlSplitNode) { - placeholder.setNext(end); + if (beginNode.predecessor() instanceof ControlSplitNode) { + beginNode.setNext(end); } else { - placeholder.replaceAtPredecessor(end); - placeholder.safeDelete(); + beginNode.replaceAtPredecessor(end); + beginNode.safeDelete(); } mergeNode.addForwardEnd(end); mergeNode.setNext(next); - block.setFirstInstruction(operatingDimension, mergeNode); + setFirstInstruction(block, operatingDimension, mergeNode); } - AbstractMergeNode mergeNode = (AbstractMergeNode) block.getFirstInstruction(operatingDimension); + AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block, operatingDimension); // The EndNode for the newly merged edge. - AbstractEndNode newEnd = currentGraph.add(new EndNode()); + EndNode newEnd = currentGraph.add(new EndNode()); Target target = checkLoopExit(newEnd, block, state); FixedNode result = target.fixed; - ((HIRFrameStateBuilder) block.getEntryState(operatingDimension)).merge(mergeNode, target.state); + getEntryState(block, operatingDimension).merge(mergeNode, target.state); mergeNode.addForwardEnd(newEnd); Debug.log("createTarget %s: merging state, result: %s", block, result); return result; } + private int findOperatingDimension(BciBlock block, HIRFrameStateBuilder state) { + if (this.explodeLoops && this.explodeLoopsContext != null && !this.explodeLoopsContext.isEmpty()) { + return findOperatingDimensionWithLoopExplosion(block, state); + } + return this.getCurrentDimension(); + } + + private int findOperatingDimensionWithLoopExplosion(BciBlock block, HIRFrameStateBuilder state) { + int i; + for (i = explodeLoopsContext.size() - 1; i >= 0; --i) { + ExplodedLoopContext context = explodeLoopsContext.elementAt(i); + if (context.header == block) { + + if (this.mergeExplosions) { + state.clearNonLiveLocals(block, liveness, true); + Integer cachedDimension = mergeExplosionsMap.get(state); + if (cachedDimension != null) { + return cachedDimension; + } + } + + // We have a hit on our current explosion context loop begin. + if (context.targetPeelIteration == null) { + context.targetPeelIteration = new int[1]; + } else { + context.targetPeelIteration = Arrays.copyOf(context.targetPeelIteration, context.targetPeelIteration.length + 1); + } + + // This is the first hit => allocate a new dimension and at the same + // time mark the context loop begin as hit during the current + // iteration. + if (this.mergeExplosions) { + this.addToMergeCache(state, nextPeelIteration); + } + context.targetPeelIteration[context.targetPeelIteration.length - 1] = nextPeelIteration++; + if (nextPeelIteration > MaximumLoopExplosionCount.getValue()) { + String message = "too many loop explosion interations - does the explosion not terminate for method " + method + "?"; + if (FailedLoopExplosionIsFatal.getValue()) { + throw new RuntimeException(message); + } else { + throw bailout(message); + } + } + + // Operate on the target dimension. + return context.targetPeelIteration[context.targetPeelIteration.length - 1]; + } else if (block.getId() > context.header.getId() && block.getId() <= context.header.loopEnd) { + // We hit the range of this context. + return context.peelIteration; + } + } + + // No dimension found. + return 0; + } + /** * Returns a block begin node with the specified state. If the specified probability is * 0, the block deoptimizes immediately. @@ -1355,41 +1715,27 @@ protected void processBlock(BytecodeParser parser, BciBlock block) { // Ignore blocks that have no predecessors by the time their bytecodes are parsed - if (block == null || block.getFirstInstruction(this.getCurrentDimension()) == null) { + int currentDimension = this.getCurrentDimension(); + FixedWithNextNode firstInstruction = getFirstInstruction(block, currentDimension); + if (firstInstruction == null) { Debug.log("Ignoring block %s", block); return; } - try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, block.getFirstInstruction(this.getCurrentDimension()), block.isLoopHeader)) { + try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { - lastInstr = block.getFirstInstruction(this.getCurrentDimension()); - frameState = (HIRFrameStateBuilder) block.getEntryState(this.getCurrentDimension()); + lastInstr = firstInstruction; + frameState = getEntryState(block, currentDimension); parser.setCurrentFrameState(frameState); currentBlock = block; - if (lastInstr instanceof AbstractMergeNode) { - int bci = block.startBci; - if (block instanceof ExceptionDispatchBlock) { - bci = ((ExceptionDispatchBlock) block).deoptBci; - } - ((AbstractMergeNode) lastInstr).setStateAfter(frameState.create(bci)); + if (firstInstruction instanceof AbstractMergeNode) { + setMergeStateAfter(block, firstInstruction); } - if (block == returnBlock) { - Kind returnKind = method.getSignature().getReturnKind().getStackKind(); - ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); - assert frameState.stackSize() == 0; - beforeReturn(x); - this.returnValue = x; - this.beforeReturnNode = this.lastInstr; - } else if (block == unwindBlock) { - if (currentDepth == 0) { - frameState.setRethrowException(false); - createUnwind(); - } else { - ValueNode exception = frameState.apop(); - this.unwindValue = exception; - this.beforeUnwindNode = this.lastInstr; - } + if (block == blockMap.getReturnBlock()) { + handleReturnBlock(); + } else if (block == blockMap.getUnwindBlock()) { + handleUnwindBlock(); } else if (block instanceof ExceptionDispatchBlock) { createExceptionDispatch((ExceptionDispatchBlock) block); } else { @@ -1399,6 +1745,37 @@ } } + private void handleUnwindBlock() { + if (currentDepth == 0) { + frameState.setRethrowException(false); + createUnwind(); + } else { + ValueNode exception = frameState.apop(); + this.unwindValue = exception; + this.beforeUnwindNode = this.lastInstr; + } + } + + private void handleReturnBlock() { + Kind returnKind = method.getSignature().getReturnKind().getStackKind(); + ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); + assert frameState.stackSize() == 0; + beforeReturn(x); + this.returnValue = x; + this.beforeReturnNode = this.lastInstr; + } + + private void setMergeStateAfter(BciBlock block, FixedWithNextNode firstInstruction) { + AbstractMergeNode abstractMergeNode = (AbstractMergeNode) firstInstruction; + if (abstractMergeNode.stateAfter() == null) { + int bci = block.startBci; + if (block instanceof ExceptionDispatchBlock) { + bci = ((ExceptionDispatchBlock) block).deoptBci; + } + abstractMergeNode.setStateAfter(createFrameState(bci)); + } + } + /** * Remove loop header without loop ends. This can happen with degenerated loops like * this one: @@ -1413,7 +1790,7 @@ *
    */ private void connectLoopEndToBegin() { - for (LoopBeginNode begin : currentGraph.getNodes(LoopBeginNode.class)) { + for (LoopBeginNode begin : currentGraph.getNodes(LoopBeginNode.TYPE)) { if (begin.loopEnds().isEmpty()) { assert begin.forwardEndCount() == 1; currentGraph.reduceDegenerateLoopBegin(begin); @@ -1436,7 +1813,7 @@ if (currentReturnValue != null) { frameState.push(currentReturnValue.getKind(), currentReturnValue); } - monitorExit.setStateAfter(frameState.create(bci)); + monitorExit.setStateAfter(createFrameState(bci)); assert !frameState.rethrowException(); } } @@ -1445,7 +1822,7 @@ assert frameState.stackSize() == 1 : frameState; if (block.handler.isCatchAll()) { assert block.getSuccessorCount() == 1; - appendGoto(createTarget(block.getSuccessor(0), frameState)); + appendGoto(block.getSuccessor(0)); return; } @@ -1458,7 +1835,7 @@ ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType; for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { if (skippedType.isAssignableFrom(resolvedCatchType)) { - BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1); + BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); FixedNode trueSuccessor = currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); FixedNode nextDispatch = createTarget(nextBlock, frameState); @@ -1469,7 +1846,7 @@ } if (initialized) { - BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1); + BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false)); frameState.apop(); @@ -1485,9 +1862,10 @@ } } - private void appendGoto(FixedNode target) { - if (lastInstr != null) { - lastInstr.setNext(target); + private void appendGoto(BciBlock successor) { + FixedNode targetInstr = createTarget(successor, frameState, true, true); + if (lastInstr != null && lastInstr != targetInstr) { + lastInstr.setNext(targetInstr); } } @@ -1500,30 +1878,29 @@ if (block.isLoopHeader && !explodeLoops) { // Create the loop header block, which later will merge the backward branches of // the loop. - AbstractEndNode preLoopEnd = currentGraph.add(new EndNode()); - LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); - lastInstr.setNext(preLoopEnd); - // Add the single non-loop predecessor of the loop header. - loopBegin.addForwardEnd(preLoopEnd); + controlFlowSplit = true; + LoopBeginNode loopBegin = appendLoopBegin(this.lastInstr); lastInstr = loopBegin; // Create phi functions for all local variables and operand stack slots. frameState.insertLoopPhis(liveness, block.loopId, loopBegin); - loopBegin.setStateAfter(frameState.create(block.startBci)); + loopBegin.setStateAfter(createFrameState(block.startBci)); /* * We have seen all forward branches. All subsequent backward branches will * merge to the loop header. This ensures that the loop header has exactly one * non-loop predecessor. */ - block.setFirstInstruction(this.getCurrentDimension(), loopBegin); + setFirstInstruction(block, this.getCurrentDimension(), loopBegin); /* * We need to preserve the frame state builder of the loop header so that we can * merge values for phi functions, so make a copy of it. */ - block.setEntryState(this.getCurrentDimension(), frameState.copy()); + setEntryState(block, this.getCurrentDimension(), frameState.copy()); Debug.log(" created loop header %s", loopBegin); + } else if (block.isLoopHeader && explodeLoops && this.mergeExplosions) { + frameState = frameState.copy(); } assert lastInstr.next() == null : "instructions already appended at block " + block; Debug.log(" frameState: %s", frameState); @@ -1547,15 +1924,15 @@ // read the opcode int opcode = stream.currentBC(); - traceState(); - traceInstruction(bci, opcode, bci == block.startBci); + assert traceState(); + assert traceInstruction(bci, opcode, bci == block.startBci); if (currentDepth == 0 && bci == entryBCI) { if (block.getJsrScope() != JsrScope.EMPTY_SCOPE) { throw new BailoutException("OSR into a JSR scope is not supported"); } EntryMarkerNode x = append(new EntryMarkerNode()); frameState.insertProxies(x); - x.setStateAfter(frameState.create(bci)); + x.setStateAfter(createFrameState(bci)); } processBytecode(bci, opcode); @@ -1575,7 +1952,7 @@ } else { StateSplit stateSplit = (StateSplit) lastInstr; if (stateSplit.stateAfter() == null) { - stateSplit.setStateAfter(frameState.create(bci)); + stateSplit.setStateAfter(createFrameState(bci)); } } } @@ -1585,13 +1962,22 @@ assert !block.getSuccessor(0).isExceptionEntry; assert block.numNormalSuccessors() == 1; // we fell through to the next block, add a goto and break - appendGoto(createTarget(block.getSuccessor(0), frameState)); + appendGoto(block.getSuccessor(0)); break; } } } } + private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext) { + EndNode preLoopEnd = currentGraph.add(new EndNode()); + LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); + fixedWithNext.setNext(preLoopEnd); + // Add the single non-loop predecessor of the loop header. + loopBegin.addForwardEnd(preLoopEnd); + return loopBegin; + } + /** * A hook for derived classes to modify the last instruction or add other instructions. * @@ -1605,16 +1991,17 @@ private InfopointNode createInfoPointNode(InfopointReason reason) { if (graphBuilderConfig.insertFullDebugInfo()) { - return new FullInfopointNode(reason, frameState.create(bci())); + return new FullInfopointNode(reason, createFrameState(bci())); } else { return new SimpleInfopointNode(reason, new BytecodePosition(null, method, bci())); } } - private void traceState() { + private boolean traceState() { if (Debug.isEnabled() && Options.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) { traceStateHelper(); } + return true; } private void traceStateHelper() { @@ -1631,26 +2018,112 @@ @Override protected void genIf(ValueNode x, Condition cond, ValueNode y) { - // assert !x.isDeleted() && !y.isDeleted(); - // assert currentBlock.numNormalSuccessors() == 2; - assert currentBlock.getSuccessors().size() == 2; - BciBlock trueBlock = currentBlock.getSuccessors().get(0); - BciBlock falseBlock = currentBlock.getSuccessors().get(1); + assert currentBlock.getSuccessorCount() == 2; + BciBlock trueBlock = currentBlock.getSuccessor(0); + BciBlock falseBlock = currentBlock.getSuccessor(1); if (trueBlock == falseBlock) { - appendGoto(createTarget(trueBlock, frameState)); + // The target block is the same independent of the condition. + appendGoto(trueBlock); return; } - double probability = branchProbability(); + ValueNode a = x; + ValueNode b = y; - // the mirroring and negation operations get the condition into canonical form - boolean mirror = cond.canonicalMirror(); + // Check whether the condition needs to mirror the operands. + if (cond.canonicalMirror()) { + a = y; + b = x; + } + + // Create the logic node for the condition. + LogicNode condition = createLogicNode(cond, a, b); + + // Check whether the condition needs to negate the result. boolean negate = cond.canonicalNegate(); - ValueNode a = mirror ? y : x; - ValueNode b = mirror ? x : y; + // Remove a logic negation node and fold it into the negate boolean. + if (condition instanceof LogicNegationNode) { + LogicNegationNode logicNegationNode = (LogicNegationNode) condition; + negate = !negate; + condition = logicNegationNode.getValue(); + } + + if (condition instanceof LogicConstantNode) { + genConstantTargetIf(trueBlock, falseBlock, negate, condition); + } else { + if (condition.graph() == null) { + condition = currentGraph.unique(condition); + } + + // Need to get probability based on current bci. + double probability = branchProbability(); + + if (negate) { + BciBlock tmpBlock = trueBlock; + trueBlock = falseBlock; + falseBlock = tmpBlock; + probability = 1 - probability; + } + + if (isNeverExecutedCode(probability)) { + append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true)); + appendGoto(falseBlock); + return; + } else if (isNeverExecutedCode(1 - probability)) { + append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false)); + appendGoto(trueBlock); + return; + } - ValueNode condition; + int oldBci = stream.currentBCI(); + int trueBlockInt = checkPositiveIntConstantPushed(trueBlock); + if (trueBlockInt != -1) { + int falseBlockInt = checkPositiveIntConstantPushed(falseBlock); + if (falseBlockInt != -1) { + if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) { + return; + } + } + } + + this.controlFlowSplit = true; + FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false); + FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true); + ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability); + append(ifNode); + } + } + + private boolean tryGenConditionalForIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt) { + if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) { + genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, false); + return true; + } else if (this.currentDepth != 0 && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) { + genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, true); + return true; + } + return false; + } + + private void genConditionalForIf(BciBlock trueBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt, boolean genReturn) { + ConstantNode trueValue = currentGraph.unique(ConstantNode.forInt(trueBlockInt)); + ConstantNode falseValue = currentGraph.unique(ConstantNode.forInt(falseBlockInt)); + ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue); + if (conditionalNode.graph() == null) { + conditionalNode = currentGraph.addOrUnique(conditionalNode); + } + if (genReturn) { + this.genReturn(conditionalNode); + } else { + frameState.push(Kind.Int, conditionalNode); + appendGoto(trueBlock.getSuccessor(0)); + stream.setBCI(oldBci); + } + } + + private LogicNode createLogicNode(Condition cond, ValueNode a, ValueNode b) { + LogicNode condition; assert !a.getKind().isNumericFloat(); if (cond == Condition.EQ || cond == Condition.NE) { if (a.getKind() == Kind.Object) { @@ -1662,26 +2135,46 @@ assert a.getKind() != Kind.Object && !cond.isUnsigned(); condition = genIntegerLessThan(a, b); } - condition = genUnique(condition); + return condition; + } + + private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, boolean negate, LogicNode condition) { + LogicConstantNode constantLogicNode = (LogicConstantNode) condition; + boolean value = constantLogicNode.getValue(); + if (negate) { + value = !value; + } + BciBlock nextBlock = falseBlock; + if (value) { + nextBlock = trueBlock; + } + appendGoto(nextBlock); + } - if (condition instanceof LogicConstantNode) { - LogicConstantNode constantLogicNode = (LogicConstantNode) condition; - boolean value = constantLogicNode.getValue(); - if (negate) { - value = !value; - } - BciBlock nextBlock = falseBlock; - if (value) { - nextBlock = trueBlock; - } - appendGoto(createTarget(nextBlock, frameState)); - } else { - ValueNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState); - ValueNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState); + private int checkPositiveIntConstantPushed(BciBlock block) { + stream.setBCI(block.startBci); + int currentBC = stream.currentBC(); + if (currentBC >= Bytecodes.ICONST_0 && currentBC <= Bytecodes.ICONST_5) { + int constValue = currentBC - Bytecodes.ICONST_0; + return constValue; + } + return -1; + } - ValueNode ifNode = negate ? genIfNode(condition, falseSuccessor, trueSuccessor, 1 - probability) : genIfNode(condition, trueSuccessor, falseSuccessor, probability); - append(ifNode); - } + private boolean gotoOrFallThroughAfterConstant(BciBlock block) { + stream.setBCI(block.startBci); + int currentBCI = stream.nextBCI(); + stream.setBCI(currentBCI); + int currentBC = stream.currentBC(); + return stream.currentBCI() > block.endBci || currentBC == Bytecodes.GOTO || currentBC == Bytecodes.GOTO_W; + } + + private boolean returnAfterConstant(BciBlock block) { + stream.setBCI(block.startBci); + int currentBCI = stream.nextBCI(); + stream.setBCI(currentBCI); + int currentBC = stream.currentBC(); + return currentBC == Bytecodes.IRETURN; } public StampProvider getStampProvider() { @@ -1717,6 +2210,37 @@ return snippetReflectionProvider; } + public boolean parsingReplacement() { + return parsingReplacement; + } + + public StructuredGraph getGraph() { + return currentGraph; + } + + public GuardingNode getCurrentBlockGuard() { + return (GuardingNode) getFirstInstruction(currentBlock, getCurrentDimension()); + } + + @Override + public String toString() { + return method.format("%H.%n(%p)@") + bci(); + } + + public BailoutException bailout(String string) { + FrameState currentFrameState = createFrameState(bci()); + StackTraceElement[] elements = GraphUtil.approxSourceStackTraceElement(currentFrameState); + BailoutException bailout = new BailoutException(string); + throw GraphUtil.createBailoutException(string, bailout, elements); + } + + private FrameState createFrameState(int bci) { + return frameState.create(bci); + } } } + + static String nSpaces(int n) { + return n == 0 ? "" : format("%" + n + "s", ""); + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,13 +22,143 @@ */ package com.oracle.graal.java; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + /** * Marker interface for graph builder plugins. - * - * Concrete plugins implement one of the sub-interfaces of this interface. - * - * @see GraphBuilderPlugins - * @see GraphBuilderPlugins.Registration */ public interface GraphBuilderPlugin { + + public interface LoadFieldPlugin extends GraphBuilderPlugin { + @SuppressWarnings("unused") + default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { + return false; + } + + @SuppressWarnings("unused") + default boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) { + return false; + } + + default boolean tryConstantFold(GraphBuilderContext builder, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ResolvedJavaField field, JavaConstant asJavaConstant) { + JavaConstant result = constantReflection.readConstantFieldValue(field, asJavaConstant); + if (result != null) { + ConstantNode constantNode = builder.append(ConstantNode.forConstant(result, metaAccess)); + builder.push(constantNode.getKind().getStackKind(), constantNode); + return true; + } + return false; + } + } + + /** + * Plugin for customizing how the graph builder handles a CHECKCAST instruction in the context + * of the instruction that consumes it from the stack. + */ + public interface CheckCastPlugin extends GraphBuilderPlugin { + boolean apply(GraphBuilderContext builder, ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck); + } + + public interface InlineInvokePlugin extends GraphBuilderPlugin { + + default void postInline(@SuppressWarnings("unused") ResolvedJavaMethod inlinedTargetMethod) { + + } + + ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType, int depth); + } + + public interface LoopExplosionPlugin extends GraphBuilderPlugin { + boolean shouldExplodeLoops(ResolvedJavaMethod method); + + boolean shouldMergeExplosions(ResolvedJavaMethod method); + } + + public interface ParameterPlugin extends GraphBuilderPlugin { + FloatingNode interceptParameter(int index); + } + + /** + * Plugin for handling an invocation based on the annotations of the invoked method. + */ + public interface AnnotatedInvocationPlugin extends GraphBuilderPlugin { + /** + * Executes this plugin for an invocation of a given method with a given set of arguments. + * + * @return {@code true} if this plugin handled the invocation, {@code false} if not + */ + boolean apply(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args); + } + + /** + * Plugin for handling a specific method invocation. + */ + public interface InvocationPlugin extends GraphBuilderPlugin { + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder) { + throw invalidHandler(builder); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg) { + throw invalidHandler(builder, arg); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { + throw invalidHandler(builder, arg1, arg2); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + throw invalidHandler(builder, arg1, arg2, arg3); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { + throw invalidHandler(builder, arg1, arg2, arg3, arg4); + } + + /** + * Executes a given plugin against a set of invocation arguments by dispatching to the + * plugin's {@code apply(...)} method that matches the number of arguments. + * + * @return {@code true} if the plugin handled the invocation, {@code false} if the graph + * builder should process the invoke further (e.g., by inlining it or creating an + * {@link Invoke} node). A plugin that does not handle an invocation must not modify + * the graph being constructed. + */ + static boolean execute(GraphBuilderContext builder, InvocationPlugin plugin, ValueNode[] args) { + if (args.length == 0) { + return plugin.apply(builder); + } else if (args.length == 1) { + return plugin.apply(builder, args[0]); + } else if (args.length == 2) { + return plugin.apply(builder, args[0], args[1]); + } else if (args.length == 3) { + return plugin.apply(builder, args[0], args[1], args[2]); + } else if (args.length == 4) { + return plugin.apply(builder, args[0], args[1], args[2], args[3]); + } else { + throw plugin.invalidHandler(builder, args); + } + } + + default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext builder, ValueNode... args) { + return new GraalInternalError("Invocation plugin %s does not handle invocations with %d arguments", getClass().getSimpleName(), args.length); + } + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * 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 java.lang.String.*; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; - -/** - * Interface for managing a set of graph builder {@link GraphBuilderPlugin}s. - */ -public interface GraphBuilderPlugins { - - public interface LoadFieldPlugin extends GraphBuilderPlugin { - @SuppressWarnings("unused") - default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { - return false; - } - - @SuppressWarnings("unused") - default boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) { - return false; - } - } - - public interface ParameterPlugin extends GraphBuilderPlugin { - FloatingNode interceptParameter(int index); - } - - public interface InlineInvokePlugin extends GraphBuilderPlugin { - boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth); - } - - public interface LoopExplosionPlugin extends GraphBuilderPlugin { - boolean shouldExplodeLoops(ResolvedJavaMethod method); - } - - /** - * Plugin for handling a method invocation. - */ - public interface InvocationPlugin extends GraphBuilderPlugin { - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder) { - throw invalidHandler(builder); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg) { - throw invalidHandler(builder, arg); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { - throw invalidHandler(builder, arg1, arg2); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) { - throw invalidHandler(builder, arg1, arg2, arg3); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { - throw invalidHandler(builder, arg1, arg2, arg3, arg4); - } - - /** - * Executes a given plugin against a set of invocation arguments by dispatching to the - * plugin's {@code apply(...)} method that matches the number of arguments. - * - * @return {@code true} if the plugin handled the invocation, {@code false} if the graph - * builder should process the invoke further (e.g., by inlining it or creating an - * {@link Invoke} node). A plugin that does not handle an invocation must not modify - * the graph being constructed. - */ - static boolean execute(GraphBuilderContext builder, InvocationPlugin plugin, ValueNode[] args) { - if (args.length == 0) { - return plugin.apply(builder); - } else if (args.length == 1) { - return plugin.apply(builder, args[0]); - } else if (args.length == 2) { - return plugin.apply(builder, args[0], args[1]); - } else if (args.length == 3) { - return plugin.apply(builder, args[0], args[1], args[2]); - } else if (args.length == 4) { - return plugin.apply(builder, args[0], args[1], args[2], args[3]); - } else { - throw plugin.invalidHandler(builder, args); - } - } - - default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext builder, ValueNode... args) { - return new GraalInternalError("Invocation plugin %s does not handle invocations with %d arguments", getClass().getSimpleName(), args.length); - } - } - - /** - * Utility for {@linkplain GraphBuilderPlugins#register(ResolvedJavaMethod, InvocationPlugin) - * registration} of plugins. - */ - public static class Registration { - - /** - * Sentinel class for use with {@link Registration#register1}, - * {@link Registration#register2} or {@link Registration#register3} to denote the receiver - * argument for a non-static method. - */ - public static final class Receiver { - private Receiver() { - throw GraalInternalError.shouldNotReachHere(); - } - } - - private final GraphBuilderPlugins plugins; - private final MetaAccessProvider metaAccess; - private final Class declaringClass; - - /** - * Creates an object for registering plugins for methods declared by a given class. - * - * @param plugins where to register the plugins - * @param metaAccess used to resolve classes and methods - * @param declaringClass the class declaring the methods for which plugins will be - * registered via this object - */ - public Registration(GraphBuilderPlugins plugins, MetaAccessProvider metaAccess, Class declaringClass) { - this.plugins = plugins; - this.metaAccess = metaAccess; - this.declaringClass = declaringClass; - } - - /** - * Registers a plugin for a method with no arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register0(String name, InvocationPlugin plugin) { - plugins.register(resolve(metaAccess, declaringClass, name), plugin); - } - - /** - * Registers a plugin for a method with 1 argument. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register1(String name, Class arg, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg == Receiver.class ? resolve(metaAccess, declaringClass, name) : resolve(metaAccess, declaringClass, name, arg); - plugins.register(method, plugin); - } - - /** - * Registers a plugin for a method with 2 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2) : resolve(metaAccess, declaringClass, name, arg1, arg2); - plugins.register(method, plugin); - } - - /** - * Registers a plugin for a method with 3 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3); - plugins.register(method, plugin); - } - - /** - * Registers a plugin for a method with 4 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4); - plugins.register(method, plugin); - } - - /** - * Resolves a method given a declaring class, name and parameter types. - */ - public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class declaringClass, String name, Class... parameterTypes) { - try { - return metaAccess.lookupJavaMethod(name.equals("") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(name, parameterTypes)); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalInternalError(e); - } - } - } - - public static class InvocationPluginChecker { - /** - * The set of all {@link InvocationPlugin#apply} method signatures. - */ - static final Class[][] SIGS; - static { - ArrayList[]> sigs = new ArrayList<>(5); - for (Method method : InvocationPlugin.class.getDeclaredMethods()) { - if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) { - Class[] sig = method.getParameterTypes(); - assert sig[0] == GraphBuilderContext.class; - assert Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class); - while (sigs.size() < sig.length) { - sigs.add(null); - } - sigs.set(sig.length - 1, sig); - } - } - assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null), - ValueNode.class.getSimpleName()); - SIGS = sigs.toArray(new Class[sigs.size()][]); - } - - public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) { - int arguments = method.getSignature().getParameterCount(!method.isStatic()); - assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method.format("%H.%n(%p)")); - Method expected = null; - for (Method m : plugin.getClass().getDeclaredMethods()) { - if (m.getName().equals("apply")) { - Class[] parameterTypes = m.getParameterTypes(); - assert Arrays.equals(SIGS[arguments], parameterTypes) : format("graph builder plugin for %s has wrong signature%nexpected: (%s)%n actual: (%s)", method.format("%H.%n(%p)"), - sigString(SIGS[arguments]), sigString(m.getParameterTypes())); - expected = m; - } - } - assert expected != null : format("graph builder plugin %s must define exactly one \"apply\" method, none found", plugin); - return true; - } - - protected static String sigString(Class... sig) { - StringBuilder sb = new StringBuilder(); - for (Class t : sig) { - if (sb.length() != 0) { - sb.append(", "); - } - sb.append(t.getSimpleName()); - } - return sb.toString(); - } - - } - - /** - * Registers an {@link InvocationPlugin} for a given method. There must be no plugin currently - * registered for {@code method}. - */ - void register(ResolvedJavaMethod method, InvocationPlugin plugin); - - /** - * Gets the {@link InvocationPlugin} for a given method. - * - * @param method the method to lookup - * @return the plugin associated with {@code method} or {@code null} if none exists - */ - InvocationPlugin lookupInvocation(ResolvedJavaMethod method); - - DefaultGraphBuilderPlugins copy(); -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,19 +31,35 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.java.BciBlockMapping.LocalLiveness; -import com.oracle.graal.java.GraphBuilderPlugins.ParameterPlugin; +import com.oracle.graal.java.BciBlockMapping.*; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; -public class HIRFrameStateBuilder extends AbstractFrameStateBuilder { +public final class HIRFrameStateBuilder { private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; + protected final ResolvedJavaMethod method; + protected int stackSize; + protected final ValueNode[] locals; + protected final ValueNode[] stack; + protected ValueNode[] lockedObjects; + + /** + * Specifies if asserting type checks are enabled. + */ + protected final boolean checkTypes; + + /** + * @see BytecodeFrame#rethrowException + */ + protected boolean rethrowException; + private MonitorIdNode[] monitorIds; private final StructuredGraph graph; private final Supplier outerFrameStateSupplier; @@ -54,8 +70,12 @@ * @param method the method whose frame is simulated * @param graph the target graph of Graal nodes created by the builder */ - public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, Supplier outerFrameStateSupplier) { - super(method); + public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean checkTypes, Supplier outerFrameStateSupplier) { + this.method = method; + this.locals = allocateArray(method.getMaxLocals()); + this.stack = allocateArray(Math.max(1, method.getMaxStackSize())); + this.lockedObjects = allocateArray(0); + this.checkTypes = checkTypes; assert graph != null; @@ -64,26 +84,26 @@ this.outerFrameStateSupplier = outerFrameStateSupplier; } - public final void initializeFromArgumentsArray(ValueNode[] arguments) { + public void initializeFromArgumentsArray(ValueNode[] arguments) { int javaIndex = 0; int index = 0; if (!method.isStatic()) { // set the receiver - storeLocal(javaIndex, arguments[index]); + locals[javaIndex] = arguments[index]; javaIndex = 1; index = 1; } Signature sig = method.getSignature(); int max = sig.getParameterCount(false); for (int i = 0; i < max; i++) { - storeLocal(javaIndex, arguments[index]); + locals[javaIndex] = arguments[index]; javaIndex += arguments[index].getKind().getSlotCount(); index++; } } - public final void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) { + public void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) { int javaIndex = 0; int index = 0; @@ -96,7 +116,7 @@ if (receiver == null) { receiver = new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass())); } - storeLocal(javaIndex, graph.unique(receiver)); + locals[javaIndex] = graph.unique(receiver); javaIndex = 1; index = 1; } @@ -122,14 +142,24 @@ if (param == null) { param = new ParameterNode(index, stamp); } - storeLocal(javaIndex, graph.unique(param)); + locals[javaIndex] = graph.unique(param); javaIndex += kind.getSlotCount(); index++; } } private HIRFrameStateBuilder(HIRFrameStateBuilder other) { - super(other); + this.method = other.method; + this.stackSize = other.stackSize; + this.locals = other.locals.clone(); + this.stack = other.stack.clone(); + this.lockedObjects = other.lockedObjects.length == 0 ? other.lockedObjects : other.lockedObjects.clone(); + this.rethrowException = other.rethrowException; + this.checkTypes = other.checkTypes; + + assert locals.length == method.getMaxLocals(); + assert stack.length == Math.max(1, method.getMaxStackSize()); + assert other.graph != null; graph = other.graph; monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); @@ -140,8 +170,7 @@ assert lockedObjects.length == monitorIds.length; } - @Override - protected ValueNode[] allocateArray(int length) { + private static ValueNode[] allocateArray(int length) { return length == 0 ? EMPTY_ARRAY : new ValueNode[length]; } @@ -172,16 +201,18 @@ FrameState outerFrameState = null; if (outerFrameStateSupplier != null) { outerFrameState = outerFrameStateSupplier.get(); + if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { + FrameState newFrameState = outerFrameState.duplicateModified(outerFrameState.bci, true, Kind.Void, this.peek(0)); + return newFrameState; + } } return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, false)); } - @Override public HIRFrameStateBuilder copy() { return new HIRFrameStateBuilder(this); } - @Override public boolean isCompatibleWith(HIRFrameStateBuilder other) { assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds"; @@ -211,10 +242,18 @@ assert isCompatibleWith(other); for (int i = 0; i < localsSize(); i++) { - storeLocal(i, merge(localAt(i), other.localAt(i), block)); + ValueNode curLocal = localAt(i); + ValueNode mergedLocal = merge(curLocal, other.localAt(i), block); + if (curLocal != mergedLocal) { + storeLocal(i, mergedLocal); + } } for (int i = 0; i < stackSize(); i++) { - storeStack(i, merge(stackAt(i), other.stackAt(i), block)); + ValueNode curStack = stackAt(i); + ValueNode mergedStack = merge(curStack, other.stackAt(i), block); + if (curStack != mergedStack) { + storeStack(i, mergedStack); + } } for (int i = 0; i < lockedObjects.length; i++) { lockedObjects[i] = merge(lockedObjects[i], other.lockedObjects[i], block); @@ -225,7 +264,6 @@ private ValueNode merge(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) { if (currentValue == null || currentValue.isDeleted()) { return null; - } else if (block.isPhiAtMerge(currentValue)) { if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { propagateDelete((ValuePhiNode) currentValue); @@ -233,26 +271,27 @@ } ((PhiNode) currentValue).addInput(otherValue); return currentValue; - } else if (currentValue != otherValue) { assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for changed locals and all stack slots"; if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { return null; } - - ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block)); - for (int i = 0; i < block.phiPredecessorCount(); i++) { - phi.addInput(currentValue); - } - phi.addInput(otherValue); - assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount(); - return phi; - + return createValuePhi(currentValue, otherValue, block); } else { return currentValue; } } + private ValuePhiNode createValuePhi(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) { + ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block)); + for (int i = 0; i < block.phiPredecessorCount(); i++) { + phi.addInput(currentValue); + } + phi.addInput(otherValue); + assert phi.valueCount() == block.phiPredecessorCount() + 1; + return phi; + } + private void propagateDelete(FloatingNode node) { assert node instanceof ValuePhiNode || node instanceof ProxyNode; if (node.isDeleted()) { @@ -381,7 +420,6 @@ /** * @return the current lock depth */ - @Override public int lockDepth() { assert lockedObjects.length == monitorIds.length; return lockedObjects.length; @@ -406,4 +444,490 @@ } return false; } + + public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) { + /* + * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to + * remove it for normal compilations, but not for OSR compilations - otherwise dead object + * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with + * Kind.Illegal, because the conflicting branch might not have been parsed. + */ + if (liveness == null) { + return; + } + if (liveIn) { + for (int i = 0; i < locals.length; i++) { + if (!liveness.localIsLiveIn(block, i)) { + locals[i] = null; + } + } + } else { + for (int i = 0; i < locals.length; i++) { + if (!liveness.localIsLiveOut(block, i)) { + locals[i] = null; + } + } + } + } + + /** + * @see BytecodeFrame#rethrowException + */ + public boolean rethrowException() { + return rethrowException; + } + + /** + * @see BytecodeFrame#rethrowException + */ + public void setRethrowException(boolean b) { + rethrowException = b; + } + + /** + * Returns the size of the local variables. + * + * @return the size of the local variables + */ + public int localsSize() { + return locals.length; + } + + /** + * Gets the current size (height) of the stack. + */ + public int stackSize() { + return stackSize; + } + + /** + * Gets the value in the local variables at the specified index, without any sanity checking. + * + * @param i the index into the locals + * @return the instruction that produced the value for the specified local + */ + public ValueNode localAt(int i) { + return locals[i]; + } + + /** + * Get the value on the stack at the specified stack index. + * + * @param i the index into the stack, with {@code 0} being the bottom of the stack + * @return the instruction at the specified position in the stack + */ + public ValueNode stackAt(int i) { + return stack[i]; + } + + /** + * Gets the value in the lock at the specified index, without any sanity checking. + * + * @param i the index into the lock + * @return the instruction that produced the value for the specified lock + */ + public ValueNode lockAt(int i) { + return lockedObjects[i]; + } + + public void storeLock(int i, ValueNode lock) { + lockedObjects[i] = lock; + } + + /** + * Loads the local variable at the specified index, checking that the returned value is non-null + * and that two-stack values are properly handled. + * + * @param i the index of the local variable to load + * @return the instruction that produced the specified local + */ + public ValueNode loadLocal(int i) { + ValueNode x = locals[i]; + assert assertLoadLocal(i, x); + return x; + } + + private boolean assertLoadLocal(int i, ValueNode x) { + assert x != null : i; + assert !checkTypes || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); + assert !checkTypes || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); + return true; + } + + /** + * Stores a given local variable at the specified index. If the value occupies two slots, then + * the next local variable index is also overwritten. + * + * @param i the index at which to store + * @param x the instruction which produces the value for the local + */ + public void storeLocal(int i, ValueNode x) { + assert assertStoreLocal(x); + locals[i] = x; + if (x != null && x.getKind().needsTwoSlots()) { + // if this is a double word, then kill i+1 + locals[i + 1] = null; + } + if (x != null && i > 0) { + ValueNode p = locals[i - 1]; + if (p != null && p.getKind().needsTwoSlots()) { + // if there was a double word at i - 1, then kill it + locals[i - 1] = null; + } + } + } + + private boolean assertStoreLocal(ValueNode x) { + assert x == null || !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; + return true; + } + + public void storeStack(int i, ValueNode x) { + assert assertStoreStack(i, x); + stack[i] = x; + } + + private boolean assertStoreStack(int i, ValueNode x) { + assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; + return true; + } + + /** + * Pushes an instruction onto the stack with the expected type. + * + * @param kind the type expected for this instruction + * @param x the instruction to push onto the stack + */ + public void push(Kind kind, ValueNode x) { + assert assertPush(kind, x); + xpush(x); + if (kind.needsTwoSlots()) { + xpush(null); + } + } + + private boolean assertPush(Kind kind, ValueNode x) { + assert !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); + assert x != null && (!checkTypes || x.getKind() == kind); + return true; + } + + /** + * Pushes a value onto the stack without checking the type. + * + * @param x the instruction to push onto the stack + */ + public void xpush(ValueNode x) { + assert assertXpush(x); + stack[stackSize++] = x; + } + + private boolean assertXpush(ValueNode x) { + assert !checkTypes || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); + return true; + } + + /** + * Pushes a value onto the stack and checks that it is an int. + * + * @param x the instruction to push onto the stack + */ + public void ipush(ValueNode x) { + assert assertInt(x); + xpush(x); + } + + /** + * Pushes a value onto the stack and checks that it is a float. + * + * @param x the instruction to push onto the stack + */ + public void fpush(ValueNode x) { + assert assertFloat(x); + xpush(x); + } + + /** + * Pushes a value onto the stack and checks that it is an object. + * + * @param x the instruction to push onto the stack + */ + public void apush(ValueNode x) { + assert assertObject(x); + xpush(x); + } + + /** + * Pushes a value onto the stack and checks that it is a long. + * + * @param x the instruction to push onto the stack + */ + public void lpush(ValueNode x) { + assert assertLong(x); + xpush(x); + xpush(null); + } + + /** + * Pushes a value onto the stack and checks that it is a double. + * + * @param x the instruction to push onto the stack + */ + public void dpush(ValueNode x) { + assert assertDouble(x); + xpush(x); + xpush(null); + } + + public void pushReturn(Kind kind, ValueNode x) { + if (kind != Kind.Void) { + push(kind.getStackKind(), x); + } + } + + /** + * Pops an instruction off the stack with the expected type. + * + * @param kind the expected type + * @return the instruction on the top of the stack + */ + public ValueNode pop(Kind kind) { + if (kind.needsTwoSlots()) { + xpop(); + } + assert assertPop(kind); + return xpop(); + } + + private boolean assertPop(Kind kind) { + assert kind != Kind.Void; + ValueNode x = xpeek(); + assert x != null && (!checkTypes || x.getKind() == kind); + return true; + } + + /** + * Pops a value off of the stack without checking the type. + * + * @return x the instruction popped off the stack + */ + public ValueNode xpop() { + return stack[--stackSize]; + } + + public ValueNode xpeek() { + return stack[stackSize - 1]; + } + + /** + * Pops a value off of the stack and checks that it is an int. + * + * @return x the instruction popped off the stack + */ + public ValueNode ipop() { + assert assertIntPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is a float. + * + * @return x the instruction popped off the stack + */ + public ValueNode fpop() { + assert assertFloatPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is an object. + * + * @return x the instruction popped off the stack + */ + public ValueNode apop() { + assert assertObjectPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is a long. + * + * @return x the instruction popped off the stack + */ + public ValueNode lpop() { + assert assertHighPeek(); + xpop(); + assert assertLongPeek(); + return xpop(); + } + + /** + * Pops a value off of the stack and checks that it is a double. + * + * @return x the instruction popped off the stack + */ + public ValueNode dpop() { + assert assertHighPeek(); + xpop(); + assert assertDoublePeek(); + return xpop(); + } + + /** + * Pop the specified number of slots off of this stack and return them as an array of + * instructions. + * + * @return an array containing the arguments off of the stack + */ + public ValueNode[] popArguments(int argSize) { + ValueNode[] result = allocateArray(argSize); + int newStackSize = stackSize; + for (int i = argSize - 1; i >= 0; i--) { + newStackSize--; + if (stack[newStackSize] == null) { + /* Two-slot value. */ + newStackSize--; + assert stack[newStackSize].getKind().needsTwoSlots(); + } else { + assert !checkTypes || (stack[newStackSize].getKind().getSlotCount() == 1); + } + result[i] = stack[newStackSize]; + } + stackSize = newStackSize; + return result; + } + + /** + * Peeks an element from the operand stack. + * + * @param argumentNumber The number of the argument, relative from the top of the stack (0 = + * top). Long and double arguments only count as one argument, i.e., null-slots are + * ignored. + * @return The peeked argument. + */ + public ValueNode peek(int argumentNumber) { + int idx = stackSize() - 1; + for (int i = 0; i < argumentNumber; i++) { + if (stackAt(idx) == null) { + idx--; + assert stackAt(idx).getKind().needsTwoSlots(); + } + idx--; + } + return stackAt(idx); + } + + /** + * Clears all values on this stack. + */ + public void clearStack() { + stackSize = 0; + } + + private boolean assertLongPeek() { + return assertLong(xpeek()); + } + + private static boolean assertLong(ValueNode x) { + assert x != null && (x.getKind() == Kind.Long); + return true; + } + + private boolean assertIntPeek() { + return assertInt(xpeek()); + } + + private static boolean assertInt(ValueNode x) { + assert x != null && (x.getKind() == Kind.Int); + return true; + } + + private boolean assertFloatPeek() { + return assertFloat(xpeek()); + } + + private static boolean assertFloat(ValueNode x) { + assert x != null && (x.getKind() == Kind.Float); + return true; + } + + private boolean assertObjectPeek() { + return assertObject(xpeek()); + } + + private boolean assertObject(ValueNode x) { + assert x != null && (!checkTypes || (x.getKind() == Kind.Object)); + return true; + } + + private boolean assertDoublePeek() { + return assertDouble(xpeek()); + } + + private static boolean assertDouble(ValueNode x) { + assert x != null && (x.getKind() == Kind.Double); + return true; + } + + private boolean assertHighPeek() { + assert xpeek() == null; + return true; + } + + @Override + public int hashCode() { + int result = hashCode(locals, locals.length); + result *= 13; + result += hashCode(stack, this.stackSize); + return result; + } + + private static int hashCode(Object[] a, int length) { + int result = 1; + for (int i = 0; i < length; ++i) { + Object element = a[i]; + result = 31 * result + (element == null ? 0 : System.identityHashCode(element)); + } + return result; + } + + private static boolean equals(ValueNode[] a, ValueNode[] b, int length) { + for (int i = 0; i < length; ++i) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } + + @Override + public boolean equals(Object otherObject) { + if (otherObject instanceof HIRFrameStateBuilder) { + HIRFrameStateBuilder other = (HIRFrameStateBuilder) otherObject; + if (!other.method.equals(method)) { + return false; + } + if (other.stackSize != stackSize) { + return false; + } + if (other.checkTypes != checkTypes) { + return false; + } + if (other.rethrowException != rethrowException) { + return false; + } + if (other.graph != graph) { + return false; + } + if (other.outerFrameStateSupplier != outerFrameStateSupplier) { + return false; + } + if (other.locals.length != locals.length) { + return false; + } + return equals(other.locals, locals, locals.length) && equals(other.stack, stack, stackSize) && equals(other.lockedObjects, lockedObjects, lockedObjects.length) && + equals(other.monitorIds, monitorIds, monitorIds.length); + } + return false; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 java.lang.String.*; + +import java.lang.reflect.*; +import java.util.*; +import java.util.stream.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.nodes.*; + +/** + * Manages a set of {@link InvocationPlugin}s. + */ +public class InvocationPlugins { + /** + * Utility for {@linkplain InvocationPlugins#register(ResolvedJavaMethod, InvocationPlugin) + * registration} of invocation plugins. + */ + public static class Registration { + + /** + * Sentinel class for use with {@link Registration#register1}, + * {@link Registration#register2} or {@link Registration#register3} to denote the receiver + * argument for a non-static method. + */ + public static final class Receiver { + private Receiver() { + throw GraalInternalError.shouldNotReachHere(); + } + } + + private final InvocationPlugins plugins; + private final MetaAccessProvider metaAccess; + private final Class declaringClass; + + /** + * Creates an object for registering {@link InvocationPlugin}s for methods declared by a + * given class. + * + * @param plugins where to register the plugins + * @param metaAccess used to resolve classes and methods + * @param declaringClass the class declaring the methods for which plugins will be + * registered via this object + */ + public Registration(InvocationPlugins plugins, MetaAccessProvider metaAccess, Class declaringClass) { + this.plugins = plugins; + this.metaAccess = metaAccess; + this.declaringClass = declaringClass; + } + + /** + * Registers a plugin for a method with no arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register0(String name, InvocationPlugin plugin) { + plugins.register(resolve(metaAccess, declaringClass, name), plugin); + } + + /** + * Registers a plugin for a method with 1 argument. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register1(String name, Class arg, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg == Receiver.class ? resolve(metaAccess, declaringClass, name) : resolve(metaAccess, declaringClass, name, arg); + plugins.register(method, plugin); + } + + /** + * Registers a plugin for a method with 2 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2) : resolve(metaAccess, declaringClass, name, arg1, arg2); + plugins.register(method, plugin); + } + + /** + * Registers a plugin for a method with 3 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3); + plugins.register(method, plugin); + } + + /** + * Registers a plugin for a method with 4 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4); + plugins.register(method, plugin); + } + + /** + * Resolves a method given a declaring class, name and parameter types. + */ + public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class declaringClass, String name, Class... parameterTypes) { + try { + return metaAccess.lookupJavaMethod(name.equals("") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(name, parameterTypes)); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } + } + + private final Map plugins = new HashMap<>(); + + /** + * The invocation plugins deferred to if a plugin is not found in this object. + */ + private InvocationPlugins defaults; + + /** + * Registers an invocation plugin for a given method. There must be no plugin currently + * registered for {@code method}. + */ + public void register(ResolvedJavaMethod method, InvocationPlugin plugin) { + assert Checker.check(method, plugin); + GraphBuilderPlugin oldValue = plugins.put(method, plugin); + // System.out.println("registered: " + plugin); + assert oldValue == null; + } + + /** + * Gets the plugin for a given method. + * + * @param method the method to lookup + * @return the plugin associated with {@code method} or {@code null} if none exists + */ + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { + InvocationPlugin res = plugins.get(method); + if (res == null && defaults != null) { + return defaults.lookupInvocation(method); + } + return res; + } + + /** + * Sets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} if a + * plugin is not found in this object. + */ + public InvocationPlugins setDefaults(InvocationPlugins defaults) { + InvocationPlugins old = this.defaults; + this.defaults = defaults; + return old; + } + + /** + * Adds all the plugins from {@code other} to this object. + */ + public void updateFrom(InvocationPlugins other) { + this.plugins.putAll(other.plugins); + if (other.defaults != null) { + updateFrom(other.defaults); + } + } + + @Override + public String toString() { + return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")) + " / defaults: " + this.defaults; + } + + private static class Checker { + /** + * The set of all {@link InvocationPlugin#apply} method signatures. + */ + static final Class[][] SIGS; + static { + ArrayList[]> sigs = new ArrayList<>(5); + for (Method method : InvocationPlugin.class.getDeclaredMethods()) { + if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) { + Class[] sig = method.getParameterTypes(); + assert sig[0] == GraphBuilderContext.class; + assert Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class); + while (sigs.size() < sig.length) { + sigs.add(null); + } + sigs.set(sig.length - 1, sig); + } + } + assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null), + ValueNode.class.getSimpleName()); + SIGS = sigs.toArray(new Class[sigs.size()][]); + } + + public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) { + int arguments = method.getSignature().getParameterCount(!method.isStatic()); + assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method.format("%H.%n(%p)")); + for (Method m : plugin.getClass().getDeclaredMethods()) { + if (m.getName().equals("apply")) { + Class[] parameterTypes = m.getParameterTypes(); + if (Arrays.equals(SIGS[arguments], parameterTypes)) { + return true; + } + } + } + throw new AssertionError(format("graph builder plugin for %s not found", method.format("%H.%n(%p)"))); + } + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/LargeLocalLiveness.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/LargeLocalLiveness.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 java.util.*; + +import com.oracle.graal.java.BciBlockMapping.*; + +public final class LargeLocalLiveness extends LocalLiveness { + private BitSet[] localsLiveIn; + private BitSet[] localsLiveOut; + private BitSet[] localsLiveGen; + private BitSet[] localsLiveKill; + private BitSet[] localsChangedInLoop; + + public LargeLocalLiveness(BciBlock[] blocks, int maxLocals, int loopCount) { + super(blocks); + int blocksSize = blocks.length; + localsLiveIn = new BitSet[blocksSize]; + localsLiveOut = new BitSet[blocksSize]; + localsLiveGen = new BitSet[blocksSize]; + localsLiveKill = new BitSet[blocksSize]; + for (int i = 0; i < blocksSize; i++) { + localsLiveIn[i] = new BitSet(maxLocals); + localsLiveOut[i] = new BitSet(maxLocals); + localsLiveGen[i] = new BitSet(maxLocals); + localsLiveKill[i] = new BitSet(maxLocals); + } + localsChangedInLoop = new BitSet[loopCount]; + for (int i = 0; i < loopCount; ++i) { + localsChangedInLoop[i] = new BitSet(maxLocals); + } + } + + @Override + protected String debugLiveIn(int blockID) { + return localsLiveIn[blockID].toString(); + } + + @Override + protected String debugLiveOut(int blockID) { + return localsLiveOut[blockID].toString(); + } + + @Override + protected String debugLiveGen(int blockID) { + return localsLiveGen[blockID].toString(); + } + + @Override + protected String debugLiveKill(int blockID) { + return localsLiveKill[blockID].toString(); + } + + @Override + protected int liveOutCardinality(int blockID) { + return localsLiveOut[blockID].cardinality(); + } + + @Override + protected void propagateLiveness(int blockID, int successorID) { + localsLiveOut[blockID].or(localsLiveIn[successorID]); + } + + @Override + protected void updateLiveness(int blockID) { + BitSet liveIn = localsLiveIn[blockID]; + liveIn.clear(); + liveIn.or(localsLiveOut[blockID]); + liveIn.andNot(localsLiveKill[blockID]); + liveIn.or(localsLiveGen[blockID]); + } + + @Override + protected void loadOne(int blockID, int local) { + if (!localsLiveKill[blockID].get(local)) { + localsLiveGen[blockID].set(local); + } + } + + @Override + protected void storeOne(int blockID, int local) { + if (!localsLiveGen[blockID].get(local)) { + localsLiveKill[blockID].set(local); + } + + BciBlock block = blocks[blockID]; + long tmp = block.loops; + int pos = 0; + while (tmp != 0) { + if ((tmp & 1L) == 1L) { + this.localsChangedInLoop[pos].set(local); + } + tmp >>= 1; + ++pos; + } + } + + @Override + public boolean localIsLiveIn(BciBlock block, int local) { + return block.getId() >= Integer.MAX_VALUE ? true : localsLiveIn[block.getId()].get(local); + } + + @Override + public boolean localIsLiveOut(BciBlock block, int local) { + return block.getId() >= Integer.MAX_VALUE ? true : localsLiveOut[block.getId()].get(local); + } + + @Override + public boolean localIsChangedInLoop(int loopId, int local) { + return localsChangedInLoop[loopId].get(local); + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/LocalLiveness.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/LocalLiveness.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.bytecode.Bytecodes.*; + +import com.oracle.graal.bytecode.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.BciBlockMapping.*; + +/** + * Encapsulates the liveness calculation, so that subclasses for locals ≤ 64 and locals > 64 + * can be implemented. + */ +public abstract class LocalLiveness { + protected final BciBlock[] blocks; + + public static LocalLiveness compute(BytecodeStream stream, BciBlock[] blocks, int maxLocals, int loopCount) { + LocalLiveness liveness = maxLocals <= 64 ? new SmallLocalLiveness(blocks, maxLocals, loopCount) : new LargeLocalLiveness(blocks, maxLocals, loopCount); + liveness.computeLiveness(stream); + return liveness; + } + + protected LocalLiveness(BciBlock[] blocks) { + this.blocks = blocks; + } + + void computeLiveness(BytecodeStream stream) { + for (BciBlock block : blocks) { + computeLocalLiveness(stream, block); + } + + boolean changed; + int iteration = 0; + do { + Debug.log("Iteration %d", iteration); + changed = false; + for (int i = blocks.length - 1; i >= 0; i--) { + BciBlock block = blocks[i]; + int blockID = block.getId(); + // log statements in IFs because debugLiveX creates a new String + if (Debug.isLogEnabled()) { + Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), + debugLiveGen(blockID), debugLiveKill(blockID)); + } + + boolean blockChanged = (iteration == 0); + if (block.getSuccessorCount() > 0) { + int oldCardinality = liveOutCardinality(blockID); + for (BciBlock sux : block.getSuccessors()) { + if (Debug.isLogEnabled()) { + Debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); + } + propagateLiveness(blockID, sux.getId()); + } + blockChanged |= (oldCardinality != liveOutCardinality(blockID)); + } + + if (blockChanged) { + updateLiveness(blockID); + if (Debug.isLogEnabled()) { + Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), + debugLiveGen(blockID), debugLiveKill(blockID)); + } + } + changed |= blockChanged; + } + iteration++; + } while (changed); + } + + /** + * Returns whether the local is live at the beginning of the given block. + */ + public abstract boolean localIsLiveIn(BciBlock block, int local); + + /** + * Returns whether the local is set in the given loop. + */ + public abstract boolean localIsChangedInLoop(int loopId, int local); + + /** + * Returns whether the local is live at the end of the given block. + */ + public abstract boolean localIsLiveOut(BciBlock block, int local); + + /** + * Returns a string representation of the liveIn values of the given block. + */ + protected abstract String debugLiveIn(int blockID); + + /** + * Returns a string representation of the liveOut values of the given block. + */ + protected abstract String debugLiveOut(int blockID); + + /** + * Returns a string representation of the liveGen values of the given block. + */ + protected abstract String debugLiveGen(int blockID); + + /** + * Returns a string representation of the liveKill values of the given block. + */ + protected abstract String debugLiveKill(int blockID); + + /** + * Returns the number of live locals at the end of the given block. + */ + protected abstract int liveOutCardinality(int blockID); + + /** + * Adds all locals the are in the liveIn of the successor to the liveOut of the block. + */ + protected abstract void propagateLiveness(int blockID, int successorID); + + /** + * Calculates a new liveIn for the given block from liveOut, liveKill and liveGen. + */ + protected abstract void updateLiveness(int blockID); + + /** + * Adds the local to liveGen if it wasn't already killed in this block. + */ + protected abstract void loadOne(int blockID, int local); + + /** + * Add this local to liveKill if it wasn't already generated in this block. + */ + protected abstract void storeOne(int blockID, int local); + + private void computeLocalLiveness(BytecodeStream stream, BciBlock block) { + if (block.startBci < 0 || block.endBci < 0) { + return; + } + int blockID = block.getId(); + int localIndex; + stream.setBCI(block.startBci); + while (stream.currentBCI() <= block.endBci) { + switch (stream.currentBC()) { + case LLOAD: + case DLOAD: + loadTwo(blockID, stream.readLocalIndex()); + break; + case LLOAD_0: + case DLOAD_0: + loadTwo(blockID, 0); + break; + case LLOAD_1: + case DLOAD_1: + loadTwo(blockID, 1); + break; + case LLOAD_2: + case DLOAD_2: + loadTwo(blockID, 2); + break; + case LLOAD_3: + case DLOAD_3: + loadTwo(blockID, 3); + break; + case IINC: + localIndex = stream.readLocalIndex(); + loadOne(blockID, localIndex); + storeOne(blockID, localIndex); + break; + case ILOAD: + case FLOAD: + case ALOAD: + case RET: + loadOne(blockID, stream.readLocalIndex()); + break; + case ILOAD_0: + case FLOAD_0: + case ALOAD_0: + loadOne(blockID, 0); + break; + case ILOAD_1: + case FLOAD_1: + case ALOAD_1: + loadOne(blockID, 1); + break; + case ILOAD_2: + case FLOAD_2: + case ALOAD_2: + loadOne(blockID, 2); + break; + case ILOAD_3: + case FLOAD_3: + case ALOAD_3: + loadOne(blockID, 3); + break; + + case LSTORE: + case DSTORE: + storeTwo(blockID, stream.readLocalIndex()); + break; + case LSTORE_0: + case DSTORE_0: + storeTwo(blockID, 0); + break; + case LSTORE_1: + case DSTORE_1: + storeTwo(blockID, 1); + break; + case LSTORE_2: + case DSTORE_2: + storeTwo(blockID, 2); + break; + case LSTORE_3: + case DSTORE_3: + storeTwo(blockID, 3); + break; + case ISTORE: + case FSTORE: + case ASTORE: + storeOne(blockID, stream.readLocalIndex()); + break; + case ISTORE_0: + case FSTORE_0: + case ASTORE_0: + storeOne(blockID, 0); + break; + case ISTORE_1: + case FSTORE_1: + case ASTORE_1: + storeOne(blockID, 1); + break; + case ISTORE_2: + case FSTORE_2: + case ASTORE_2: + storeOne(blockID, 2); + break; + case ISTORE_3: + case FSTORE_3: + case ASTORE_3: + storeOne(blockID, 3); + break; + } + stream.next(); + } + } + + private void loadTwo(int blockID, int local) { + loadOne(blockID, local); + loadOne(blockID, local + 1); + } + + private void storeTwo(int blockID, int local) { + storeOne(blockID, local); + storeOne(blockID, local + 1); + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/SmallLocalLiveness.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/SmallLocalLiveness.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 com.oracle.graal.java.BciBlockMapping.*; + +public final class SmallLocalLiveness extends LocalLiveness { + /* + * local n is represented by the bit accessible as (1 << n) + */ + + private final long[] localsLiveIn; + private final long[] localsLiveOut; + private final long[] localsLiveGen; + private final long[] localsLiveKill; + private final long[] localsChangedInLoop; + private final int maxLocals; + + public SmallLocalLiveness(BciBlock[] blocks, int maxLocals, int loopCount) { + super(blocks); + this.maxLocals = maxLocals; + int blockSize = blocks.length; + localsLiveIn = new long[blockSize]; + localsLiveOut = new long[blockSize]; + localsLiveGen = new long[blockSize]; + localsLiveKill = new long[blockSize]; + localsChangedInLoop = new long[loopCount]; + } + + private String debugString(long value) { + StringBuilder str = new StringBuilder("{"); + long current = value; + for (int i = 0; i < maxLocals; i++) { + if ((current & 1L) == 1L) { + if (str.length() > 1) { + str.append(", "); + } + str.append(i); + } + current >>= 1; + } + return str.append('}').toString(); + } + + @Override + protected String debugLiveIn(int blockID) { + return debugString(localsLiveIn[blockID]); + } + + @Override + protected String debugLiveOut(int blockID) { + return debugString(localsLiveOut[blockID]); + } + + @Override + protected String debugLiveGen(int blockID) { + return debugString(localsLiveGen[blockID]); + } + + @Override + protected String debugLiveKill(int blockID) { + return debugString(localsLiveKill[blockID]); + } + + @Override + protected int liveOutCardinality(int blockID) { + return Long.bitCount(localsLiveOut[blockID]); + } + + @Override + protected void propagateLiveness(int blockID, int successorID) { + localsLiveOut[blockID] |= localsLiveIn[successorID]; + } + + @Override + protected void updateLiveness(int blockID) { + localsLiveIn[blockID] = (localsLiveOut[blockID] & ~localsLiveKill[blockID]) | localsLiveGen[blockID]; + } + + @Override + protected void loadOne(int blockID, int local) { + long bit = 1L << local; + if ((localsLiveKill[blockID] & bit) == 0L) { + localsLiveGen[blockID] |= bit; + } + } + + @Override + protected void storeOne(int blockID, int local) { + long bit = 1L << local; + if ((localsLiveGen[blockID] & bit) == 0L) { + localsLiveKill[blockID] |= bit; + } + + BciBlock block = blocks[blockID]; + long tmp = block.loops; + int pos = 0; + while (tmp != 0) { + if ((tmp & 1L) == 1L) { + this.localsChangedInLoop[pos] |= bit; + } + tmp >>= 1; + ++pos; + } + } + + @Override + public boolean localIsLiveIn(BciBlock block, int local) { + int blockID = block.getId(); + return blockID >= Integer.MAX_VALUE ? false : (localsLiveIn[blockID] & (1L << local)) != 0L; + } + + @Override + public boolean localIsLiveOut(BciBlock block, int local) { + int blockID = block.getId(); + return blockID >= Integer.MAX_VALUE ? false : (localsLiveOut[blockID] & (1L << local)) != 0L; + } + + @Override + public boolean localIsChangedInLoop(int loopId, int local) { + return (localsChangedInLoop[loopId] & (1L << local)) != 0L; + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * 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.java.GraphBuilderContext.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; - -/** - * Provider of non-runtime specific {@link GraphBuilderPlugin}s. - */ -public class StandardGraphBuilderPlugins { - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - Registration r = new Registration(plugins, metaAccess, Object.class); - r.register1("", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode object) { - if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { - builder.append(new RegisterFinalizerNode(object)); - } - return true; - } - }); - - for (Kind kind : Kind.values()) { - if (kind.isPrimitive() && kind != Kind.Void) { - new BoxPlugin(kind).register(metaAccess, plugins); - new UnboxPlugin(kind).register(metaAccess, plugins); - } - } - - GraalDirectivePlugins.registerPlugins(metaAccess, plugins); - } - - static class BoxPlugin implements InvocationPlugin { - - private final Kind kind; - - BoxPlugin(Kind kind) { - this.kind = kind; - } - - public boolean apply(GraphBuilderContext builder, ValueNode value) { - ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); - builder.push(Kind.Object, builder.append(new BoxNode(value, resultType, kind))); - return true; - } - - void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass()); - plugins.register(method, this); - } - } - - static class UnboxPlugin implements InvocationPlugin { - - private final Kind kind; - - UnboxPlugin(Kind kind) { - this.kind = kind; - } - - public boolean apply(GraphBuilderContext builder, ValueNode value) { - ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); - builder.push(kind.getStackKind(), builder.append(valueNode)); - return true; - } - - void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - String name = kind.toJavaClass().getSimpleName() + "Value"; - ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); - plugins.register(method, this); - } - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java Mon Mar 02 19:11:22 2015 +0100 @@ -45,20 +45,20 @@ * public void setField() { * field = new TestConstant(); * } - * + * * public void setStaticField() { * staticField = new TestConstant(); * } - * + * * public int callMe(CallBack callback) { * return callback.callBack(new TestConstant()); * } - * + * * public TestInterface get() { * return new TestConstant(); * } * } - * + * * private static final class TestConstant implements TestInterface { * public int method() { * return 42; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6753639.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6753639.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6753639.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,7 +30,7 @@ * @test * @bug 6753639 * @summary Strange optimisation in for loop with cyclic integer condition - * + * * @run main/othervm -Xbatch Test6753639 */ // @formatter:off diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/LongToSomethingArray01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/LongToSomethingArray01.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/LongToSomethingArray01.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,7 +28,7 @@ /** * inspired by java.security.SecureRandom.longToByteArray(long). - * + * */ public class LongToSomethingArray01 extends JTTTest { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandFlag; public final class AMD64AddressValue extends CompositeValue { + public static final CompositeValueClass TYPE = CompositeValueClass.create(AMD64AddressValue.class); private static final long serialVersionUID = -4444600052487578694L; @@ -46,7 +47,7 @@ } public AMD64AddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { - super(kind); + super(TYPE, kind); this.base = base; this.index = index; this.scale = scale; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Mar 02 19:11:22 2015 +0100 @@ -63,13 +63,15 @@ /** * Unary operation with separate source and destination operand. */ - public static class Unary2Op extends AMD64LIRInstruction { + public static final class Unary2Op extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(Unary2Op.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue x; public Unary2Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -84,13 +86,15 @@ /** * Unary operation with separate source and destination operand but register only. */ - public static class Unary2RegOp extends AMD64LIRInstruction { + public static final class Unary2RegOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(Unary2RegOp.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG}) protected AllocatableValue result; @Use({REG}) protected AllocatableValue x; public Unary2RegOp(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -106,12 +110,14 @@ * Unary operation with single operand for source and destination. */ public static class Unary1Op extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(Unary1Op.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG, HINT}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue x; public Unary1Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -127,13 +133,14 @@ /** * Unary operation with separate memory source and destination operand. */ - public static class Unary2MemoryOp extends MemOp { + public static final class Unary2MemoryOp extends MemOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(Unary2MemoryOp.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG}) protected AllocatableValue result; public Unary2MemoryOp(AMD64Arithmetic opcode, AllocatableValue result, Kind kind, AMD64AddressValue address, LIRFrameState state) { - super(kind, address, state); + super(TYPE, kind, address, state); this.opcode = opcode; this.result = result; } @@ -149,6 +156,7 @@ * destination. The second source operand may be a stack slot. */ public static class BinaryRegStack extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryRegStack.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG, HINT}) protected AllocatableValue result; @@ -156,6 +164,7 @@ @Alive({REG, STACK}) protected AllocatableValue y; public BinaryRegStack(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -180,7 +189,8 @@ * Binary operation with two operands. The first source operand is combined with the * destination. The second source operand may be a stack slot. */ - public static class BinaryMemory extends AMD64LIRInstruction { + public static final class BinaryMemory extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryMemory.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG, HINT}) protected AllocatableValue result; @@ -190,6 +200,7 @@ @State protected LIRFrameState state; public BinaryMemory(AMD64Arithmetic opcode, Kind kind, AllocatableValue result, AllocatableValue x, AMD64AddressValue location, LIRFrameState state) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -219,7 +230,8 @@ * Binary operation with two operands. The first source operand is combined with the * destination. The second source operand must be a register. */ - public static class BinaryRegReg extends AMD64LIRInstruction { + public static final class BinaryRegReg extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryRegReg.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG, HINT}) protected AllocatableValue result; @@ -227,6 +239,7 @@ @Alive({REG}) protected AllocatableValue y; public BinaryRegReg(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -250,7 +263,8 @@ /** * Binary operation with single source/destination operand and one constant. */ - public static class BinaryRegConst extends AMD64LIRInstruction { + public static final class BinaryRegConst extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryRegConst.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG, HINT}) protected AllocatableValue result; @@ -258,6 +272,7 @@ protected JavaConstant y; public BinaryRegConst(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, JavaConstant y) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -281,7 +296,8 @@ * Commutative binary operation with two operands. One of the operands is combined with the * result. */ - public static class BinaryCommutative extends AMD64LIRInstruction { + public static final class BinaryCommutative extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryCommutative.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG, HINT}) protected AllocatableValue result; @@ -289,6 +305,7 @@ @Use({REG, STACK}) protected AllocatableValue y; public BinaryCommutative(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -315,7 +332,8 @@ /** * Binary operation with separate source and destination and one constant operand. */ - public static class BinaryRegStackConst extends AMD64LIRInstruction { + public static final class BinaryRegStackConst extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryRegStackConst.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG}) protected AllocatableValue result; @@ -323,6 +341,7 @@ protected JavaConstant y; public BinaryRegStackConst(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, JavaConstant y) { + super(TYPE); this.opcode = opcode; this.result = result; this.x = x; @@ -364,7 +383,8 @@ } } - public static class MulHighOp extends AMD64LIRInstruction { + public static final class MulHighOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MulHighOp.class); @Opcode private final AMD64Arithmetic opcode; @Def({REG}) public AllocatableValue lowResult; @@ -373,6 +393,7 @@ @Use({REG, STACK}) public AllocatableValue y; public MulHighOp(AMD64Arithmetic opcode, LIRKind kind, AllocatableValue y) { + super(TYPE); this.opcode = opcode; this.x = AMD64.rax.asValue(kind); this.y = y; @@ -420,7 +441,8 @@ } } - public static class DivRemOp extends AMD64LIRInstruction { + public static final class DivRemOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(DivRemOp.class); @Opcode private final AMD64Arithmetic opcode; @Def public AllocatableValue divResult; @@ -430,6 +452,7 @@ @State protected LIRFrameState state; public DivRemOp(AMD64Arithmetic opcode, AllocatableValue x, AllocatableValue y, LIRFrameState state) { + super(TYPE); this.opcode = opcode; this.divResult = AMD64.rax.asValue(LIRKind.derive(x, y)); this.remResult = AMD64.rdx.asValue(LIRKind.derive(x, y)); @@ -456,6 +479,7 @@ } public static class FPDivRemOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(FPDivRemOp.class); @Opcode private final AMD64Arithmetic opcode; @Def protected AllocatableValue result; @@ -464,6 +488,7 @@ @Temp protected AllocatableValue raxTemp; public FPDivRemOp(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { + super(TYPE); this.opcode = opcode; this.result = result; this.raxTemp = AMD64.rax.asValue(LIRKind.value(Kind.Int)); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 +45,8 @@ * instructions specialized code is emitted to leverage these instructions. */ @Opcode("ARRAY_EQUALS") -public class AMD64ArrayEqualsOp extends AMD64LIRInstruction { +public final class AMD64ArrayEqualsOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64ArrayEqualsOp.class); private final Kind kind; private final int arrayBaseOffset; @@ -63,6 +64,7 @@ @Temp({REG, ILLEGAL}) protected Value vectorTemp2; public AMD64ArrayEqualsOp(LIRGeneratorTool tool, Kind kind, Value result, Value array1, Value array2, Value length) { + super(TYPE); this.kind = kind; Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,7 +28,8 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -public class AMD64BitManipulationOp extends AMD64LIRInstruction { +public final class AMD64BitManipulationOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64BitManipulationOp.class); public enum IntrinsicOpcode { IPOPCNT, @@ -47,6 +48,7 @@ @Use({OperandFlag.REG, OperandFlag.STACK}) protected AllocatableValue input; public AMD64BitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input) { + super(TYPE); this.opcode = opcode; this.result = result; this.input = input; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ * Emits a breakpoint. */ @Opcode("BREAKPOINT") -public class AMD64BreakpointOp extends AMD64LIRInstruction { +public final class AMD64BreakpointOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64BreakpointOp.class); /** * A set of values loaded into the Java ABI parameter locations (for inspection by a debugger). @@ -41,6 +42,7 @@ @Use({REG, STACK}) protected Value[] parameters; public AMD64BreakpointOp(Value[] parameters) { + super(TYPE); this.parameters = parameters; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +29,14 @@ import com.oracle.graal.lir.asm.*; @Opcode("BSWAP") -public class AMD64ByteSwapOp extends AMD64LIRInstruction { +public final class AMD64ByteSwapOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64ByteSwapOp.class); @Def({OperandFlag.REG, OperandFlag.HINT}) protected Value result; @Use protected Value input; public AMD64ByteSwapOp(Value result, Value input) { + super(TYPE); this.result = result; this.input = input; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64CCall.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64CCall.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64CCall.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,9 +27,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -public class AMD64CCall extends AMD64LIRInstruction { +public final class AMD64CCall extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64CCall.class); @Def({REG, ILLEGAL}) protected Value result; @Use({REG, STACK}) protected Value[] parameters; @@ -37,6 +39,7 @@ @Use({REG}) protected Value numberOfFloatingPointArguments; public AMD64CCall(Value result, Value functionPtr, Value numberOfFloatingPointArguments, Value[] parameters) { + super(TYPE); this.result = result; this.functionPtr = functionPtr; this.parameters = parameters; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,13 +36,15 @@ public class AMD64Call { public abstract static class CallOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CallOp.class); @Def({REG, ILLEGAL}) protected Value result; @Use({REG, STACK}) protected Value[] parameters; @Temp protected Value[] temps; @State protected LIRFrameState state; - public CallOp(Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + protected CallOp(LIRInstructionClass c, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(c); this.result = result; this.parameters = parameters; this.state = state; @@ -57,21 +59,23 @@ } public abstract static class MethodCallOp extends CallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MethodCallOp.class); protected final ResolvedJavaMethod callTarget; - public MethodCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - super(result, parameters, temps, state); + protected MethodCallOp(LIRInstructionClass c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(c, result, parameters, temps, state); this.callTarget = callTarget; } } @Opcode("CALL_DIRECT") - public static class DirectCallOp extends MethodCallOp { + public abstract static class DirectCallOp extends MethodCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(DirectCallOp.class); - public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - super(callTarget, result, parameters, temps, state); + protected DirectCallOp(LIRInstructionClass c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(c, callTarget, result, parameters, temps, state); } @Override @@ -82,11 +86,17 @@ @Opcode("CALL_INDIRECT") public static class IndirectCallOp extends MethodCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(IndirectCallOp.class); @Use({REG}) protected Value targetAddress; public IndirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { - super(callTarget, result, parameters, temps, state); + this(TYPE, callTarget, result, parameters, temps, targetAddress, state); + } + + protected IndirectCallOp(LIRInstructionClass c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, + LIRFrameState state) { + super(c, callTarget, result, parameters, temps, state); this.targetAddress = targetAddress; } @@ -103,11 +113,12 @@ } public abstract static class ForeignCallOp extends CallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ForeignCallOp.class); protected final ForeignCallLinkage callTarget; - public ForeignCallOp(ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - super(result, parameters, temps, state); + public ForeignCallOp(LIRInstructionClass c, ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(c, result, parameters, temps, state); this.callTarget = callTarget; } @@ -118,10 +129,11 @@ } @Opcode("NEAR_FOREIGN_CALL") - public static class DirectNearForeignCallOp extends ForeignCallOp { + public static final class DirectNearForeignCallOp extends ForeignCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(DirectNearForeignCallOp.class); public DirectNearForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - super(linkage, result, parameters, temps, state); + super(TYPE, linkage, result, parameters, temps, state); } @Override @@ -131,12 +143,13 @@ } @Opcode("FAR_FOREIGN_CALL") - public static class DirectFarForeignCallOp extends ForeignCallOp { + public static final class DirectFarForeignCallOp extends ForeignCallOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(DirectFarForeignCallOp.class); @Temp({REG}) protected AllocatableValue callTemp; public DirectFarForeignCallOp(ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - super(callTarget, result, parameters, temps, state); + super(TYPE, callTarget, result, parameters, temps, state); /* * The register allocator does not support virtual registers that are used at the call * site, so use a fixed register. diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Mon Mar 02 19:11:22 2015 +0100 @@ -42,12 +42,14 @@ FCMP, DCMP; - public static class CompareOp extends AMD64LIRInstruction { + public static final class CompareOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompareOp.class); @Opcode private final AMD64Compare opcode; @Use({REG}) protected Value x; @Use({REG, STACK, CONST}) protected Value y; public CompareOp(AMD64Compare opcode, Value x, Value y) { + super(TYPE); this.opcode = opcode; this.x = x; this.y = y; @@ -70,7 +72,8 @@ } } - public static class CompareMemoryOp extends MemOp { + public static final class CompareMemoryOp extends MemOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompareMemoryOp.class); @Opcode private final AMD64Compare opcode; @Use({REG, CONST}) protected Value y; @@ -78,7 +81,7 @@ * Compare memory, constant or register, memory. */ public CompareMemoryOp(AMD64Compare opcode, Kind kind, AMD64AddressValue address, Value y, LIRFrameState state) { - super(kind, address, state); + super(TYPE, kind, address, state); this.opcode = opcode; this.y = y; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,14 +38,17 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure; +import com.oracle.graal.lir.amd64.AMD64Call.CallOp; import com.oracle.graal.lir.asm.*; public class AMD64ControlFlow { - public static class ReturnOp extends AMD64LIRInstruction implements BlockEndOp { + public static final class ReturnOp extends AMD64LIRInstruction implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CallOp.class); @Use({REG, ILLEGAL}) protected Value x; public ReturnOp(Value x) { + super(TYPE); this.x = x; } @@ -57,6 +60,7 @@ } public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BranchOp.class); protected final ConditionFlag condition; protected final LabelRef trueDestination; protected final LabelRef falseDestination; @@ -68,6 +72,11 @@ } public BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { + this(TYPE, condition, trueDestination, falseDestination, trueDestinationProbability); + } + + protected BranchOp(LIRInstructionClass c, ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { + super(c); this.condition = condition; this.trueDestination = trueDestination; this.falseDestination = falseDestination; @@ -102,11 +111,12 @@ } } - public static class FloatBranchOp extends BranchOp { + public static final class FloatBranchOp extends BranchOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(FloatBranchOp.class); protected boolean unorderedIsTrue; public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { - super(floatCond(condition), trueDestination, falseDestination, trueDestinationProbability); + super(TYPE, floatCond(condition), trueDestination, falseDestination, trueDestinationProbability); this.unorderedIsTrue = unorderedIsTrue; } @@ -116,7 +126,8 @@ } } - public static class StrategySwitchOp extends AMD64LIRInstruction implements BlockEndOp { + public static final class StrategySwitchOp extends AMD64LIRInstruction implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StrategySwitchOp.class); @Use({CONST}) protected JavaConstant[] keyConstants; private final LabelRef[] keyTargets; private LabelRef defaultTarget; @@ -125,6 +136,7 @@ private final SwitchStrategy strategy; public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { + super(TYPE); this.strategy = strategy; this.keyConstants = strategy.keyConstants; this.keyTargets = keyTargets; @@ -170,7 +182,8 @@ } } - public static class TableSwitchOp extends AMD64LIRInstruction implements BlockEndOp { + public static final class TableSwitchOp extends AMD64LIRInstruction implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TableSwitchOp.class); private final int lowKey; private final LabelRef defaultTarget; private final LabelRef[] targets; @@ -179,6 +192,7 @@ @Temp protected Value scratch; public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Value index, Variable scratch, Variable idxScratch) { + super(TYPE); this.lowKey = lowKey; this.defaultTarget = defaultTarget; this.targets = targets; @@ -254,13 +268,15 @@ } @Opcode("CMOVE") - public static class CondMoveOp extends AMD64LIRInstruction { + public static final class CondMoveOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CondMoveOp.class); @Def({REG, HINT}) protected Value result; @Alive({REG}) protected Value trueValue; @Use({REG, STACK, CONST}) protected Value falseValue; private final ConditionFlag condition; public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) { + super(TYPE); this.result = result; this.condition = intCond(condition); this.trueValue = trueValue; @@ -274,7 +290,8 @@ } @Opcode("CMOVE") - public static class FloatCondMoveOp extends AMD64LIRInstruction { + public static final class FloatCondMoveOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(FloatCondMoveOp.class); @Def({REG}) protected Value result; @Alive({REG}) protected Value trueValue; @Alive({REG}) protected Value falseValue; @@ -282,6 +299,7 @@ private final boolean unorderedIsTrue; public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + super(TYPE); this.result = result; this.condition = floatCond(condition); this.unorderedIsTrue = unorderedIsTrue; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,7 +36,7 @@ * *
      *   Base       Contents
    - * 
    + *
      *            :                                :  -----
      *   caller   | incoming overflow argument n   |    ^
      *   frame    :     ...                        :    | positive
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java
    --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -29,7 +29,12 @@
     /**
      * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
      */
    -public abstract class AMD64LIRInstruction extends LIRInstructionBase {
    +public abstract class AMD64LIRInstruction extends LIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64LIRInstruction.class);
    +
    +    protected AMD64LIRInstruction(LIRInstructionClass c) {
    +        super(c);
    +    }
     
         @Override
         public final void emitCode(CompilationResultBuilder crb) {
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java
    --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,8 @@
     import com.oracle.graal.lir.asm.*;
     
     // @formatter:off
    -public class AMD64MathIntrinsicOp extends AMD64LIRInstruction {
    +public final class AMD64MathIntrinsicOp extends AMD64LIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64MathIntrinsicOp.class);
         public enum IntrinsicOpcode  {
             SIN, COS, TAN,
             LOG, LOG10
    @@ -42,6 +43,7 @@
         @Use protected Value input;
     
         public AMD64MathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) {
    +        super(TYPE);
             this.opcode = opcode;
             this.result = result;
             this.input = input;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java
    --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,10 +42,12 @@
     public class AMD64Move {
     
         private abstract static class AbstractMoveOp extends AMD64LIRInstruction implements MoveOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AbstractMoveOp.class);
     
             private Kind moveKind;
     
    -        public AbstractMoveOp(Kind moveKind) {
    +        protected AbstractMoveOp(LIRInstructionClass c, Kind moveKind) {
    +            super(c);
                 if (moveKind == Kind.Illegal) {
                     // unknown operand size, conservatively move the whole register
                     this.moveKind = Kind.Long;
    @@ -61,13 +63,14 @@
         }
     
         @Opcode("MOVE")
    -    public static class MoveToRegOp extends AbstractMoveOp {
    +    public static final class MoveToRegOp extends AbstractMoveOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveToRegOp.class);
     
             @Def({REG, HINT}) protected AllocatableValue result;
             @Use({REG, STACK, CONST}) protected Value input;
     
             public MoveToRegOp(Kind moveKind, AllocatableValue result, Value input) {
    -            super(moveKind);
    +            super(TYPE, moveKind);
                 this.result = result;
                 this.input = input;
             }
    @@ -84,13 +87,14 @@
         }
     
         @Opcode("MOVE")
    -    public static class MoveFromRegOp extends AbstractMoveOp {
    +    public static final class MoveFromRegOp extends AbstractMoveOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveFromRegOp.class);
     
             @Def({REG, STACK}) protected AllocatableValue result;
             @Use({REG, CONST, HINT}) protected Value input;
     
             public MoveFromRegOp(Kind moveKind, AllocatableValue result, Value input) {
    -            super(moveKind);
    +            super(TYPE, moveKind);
                 this.result = result;
                 this.input = input;
             }
    @@ -107,12 +111,14 @@
         }
     
         public abstract static class MemOp extends AMD64LIRInstruction implements ImplicitNullCheck {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MemOp.class);
     
             protected final Kind kind;
             @Use({COMPOSITE}) protected AMD64AddressValue address;
             @State protected LIRFrameState state;
     
    -        public MemOp(Kind kind, AMD64AddressValue address, LIRFrameState state) {
    +        public MemOp(LIRInstructionClass c, Kind kind, AMD64AddressValue address, LIRFrameState state) {
    +            super(c);
                 this.kind = kind;
                 this.address = address;
                 this.state = state;
    @@ -137,12 +143,13 @@
             }
         }
     
    -    public static class LoadOp extends MemOp {
    +    public static final class LoadOp extends MemOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadOp.class);
     
             @Def({REG}) protected AllocatableValue result;
     
             public LoadOp(Kind kind, AllocatableValue result, AMD64AddressValue address, LIRFrameState state) {
    -            super(kind, address, state);
    +            super(TYPE, kind, address, state);
                 this.result = result;
             }
     
    @@ -182,12 +189,13 @@
             }
         }
     
    -    public static class ZeroExtendLoadOp extends MemOp {
    +    public static final class ZeroExtendLoadOp extends MemOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ZeroExtendLoadOp.class);
     
             @Def({REG}) protected AllocatableValue result;
     
             public ZeroExtendLoadOp(Kind kind, AllocatableValue result, AMD64AddressValue address, LIRFrameState state) {
    -            super(kind, address, state);
    +            super(TYPE, kind, address, state);
                 this.result = result;
             }
     
    @@ -214,12 +222,13 @@
             }
         }
     
    -    public static class StoreOp extends MemOp {
    +    public static final class StoreOp extends MemOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StoreOp.class);
     
             @Use({REG}) protected AllocatableValue input;
     
             public StoreOp(Kind kind, AMD64AddressValue address, AllocatableValue input, LIRFrameState state) {
    -            super(kind, address, state);
    +            super(TYPE, kind, address, state);
                 this.input = input;
             }
     
    @@ -256,12 +265,13 @@
             }
         }
     
    -    public static class StoreConstantOp extends MemOp {
    +    public abstract static class StoreConstantOp extends MemOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StoreConstantOp.class);
     
             protected final JavaConstant input;
     
    -        public StoreConstantOp(Kind kind, AMD64AddressValue address, JavaConstant input, LIRFrameState state) {
    -            super(kind, address, state);
    +        protected StoreConstantOp(LIRInstructionClass c, Kind kind, AMD64AddressValue address, JavaConstant input, LIRFrameState state) {
    +            super(c, kind, address, state);
                 this.input = input;
             }
     
    @@ -304,12 +314,14 @@
             }
         }
     
    -    public static class LeaOp extends AMD64LIRInstruction {
    +    public static final class LeaOp extends AMD64LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LeaOp.class);
     
             @Def({REG}) protected AllocatableValue result;
             @Use({COMPOSITE, UNINITIALIZED}) protected AMD64AddressValue address;
     
             public LeaOp(AllocatableValue result, AMD64AddressValue address) {
    +            super(TYPE);
                 this.result = result;
                 this.address = address;
             }
    @@ -320,12 +332,14 @@
             }
         }
     
    -    public static class LeaDataOp extends AMD64LIRInstruction {
    +    public static final class LeaDataOp extends AMD64LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LeaDataOp.class);
     
             @Def({REG}) protected AllocatableValue result;
             private final byte[] data;
     
             public LeaDataOp(AllocatableValue result, byte[] data) {
    +            super(TYPE);
                 this.result = result;
                 this.data = data;
             }
    @@ -336,12 +350,14 @@
             }
         }
     
    -    public static class StackLeaOp extends AMD64LIRInstruction {
    +    public static final class StackLeaOp extends AMD64LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StackLeaOp.class);
     
             @Def({REG}) protected AllocatableValue result;
             @Use({STACK, UNINITIALIZED}) protected StackSlotValue slot;
     
             public StackLeaOp(AllocatableValue result, StackSlotValue slot) {
    +            super(TYPE);
                 assert isStackSlotValue(slot) : "Not a stack slot: " + slot;
                 this.result = result;
                 this.slot = slot;
    @@ -353,11 +369,13 @@
             }
         }
     
    -    public static class MembarOp extends AMD64LIRInstruction {
    +    public static final class MembarOp extends AMD64LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MembarOp.class);
     
             private final int barriers;
     
             public MembarOp(final int barriers) {
    +            super(TYPE);
                 this.barriers = barriers;
             }
     
    @@ -367,12 +385,14 @@
             }
         }
     
    -    public static class NullCheckOp extends AMD64LIRInstruction implements NullCheck {
    +    public static final class NullCheckOp extends AMD64LIRInstruction implements NullCheck {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(NullCheckOp.class);
     
             @Use({REG}) protected AllocatableValue input;
             @State protected LIRFrameState state;
     
             public NullCheckOp(Variable input, LIRFrameState state) {
    +            super(TYPE);
                 this.input = input;
                 this.state = state;
             }
    @@ -393,7 +413,8 @@
         }
     
         @Opcode("CAS")
    -    public static class CompareAndSwapOp extends AMD64LIRInstruction {
    +    public static final class CompareAndSwapOp extends AMD64LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
     
             private final Kind accessKind;
     
    @@ -403,6 +424,7 @@
             @Use protected AllocatableValue newValue;
     
             public CompareAndSwapOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
    +            super(TYPE);
                 this.accessKind = accessKind;
                 this.result = result;
                 this.address = address;
    @@ -432,7 +454,8 @@
         }
     
         @Opcode("ATOMIC_READ_AND_ADD")
    -    public static class AtomicReadAndAddOp extends AMD64LIRInstruction {
    +    public static final class AtomicReadAndAddOp extends AMD64LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AtomicReadAndAddOp.class);
     
             private final Kind accessKind;
     
    @@ -441,6 +464,7 @@
             @Use protected AllocatableValue delta;
     
             public AtomicReadAndAddOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue delta) {
    +            super(TYPE);
                 this.accessKind = accessKind;
                 this.result = result;
                 this.address = address;
    @@ -467,7 +491,8 @@
         }
     
         @Opcode("ATOMIC_READ_AND_WRITE")
    -    public static class AtomicReadAndWriteOp extends AMD64LIRInstruction {
    +    public static final class AtomicReadAndWriteOp extends AMD64LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AtomicReadAndWriteOp.class);
     
             private final Kind accessKind;
     
    @@ -476,6 +501,7 @@
             @Use protected AllocatableValue newValue;
     
             public AtomicReadAndWriteOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue newValue) {
    +            super(TYPE);
                 this.accessKind = accessKind;
                 this.result = result;
                 this.address = address;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,6 +37,7 @@
      */
     @Opcode("RESTORE_REGISTER")
     public class AMD64RestoreRegistersOp extends AMD64LIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64RestoreRegistersOp.class);
     
         /**
          * The slots from which the registers are restored.
    @@ -49,6 +50,11 @@
         private final AMD64SaveRegistersOp save;
     
         public AMD64RestoreRegistersOp(StackSlotValue[] values, AMD64SaveRegistersOp save) {
    +        this(TYPE, values, save);
    +    }
    +
    +    protected AMD64RestoreRegistersOp(LIRInstructionClass c, StackSlotValue[] values, AMD64SaveRegistersOp save) {
    +        super(c);
             assert Arrays.asList(values).stream().allMatch(ValueUtil::isVirtualStackSlot);
             this.slots = values;
             this.save = save;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,6 +39,7 @@
      */
     @Opcode("SAVE_REGISTER")
     public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveRegistersOp {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64SaveRegistersOp.class);
     
         /**
          * The registers (potentially) saved by this operation.
    @@ -63,6 +64,11 @@
          * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned}
          */
         public AMD64SaveRegistersOp(Register[] savedRegisters, StackSlotValue[] savedRegisterLocations, boolean supportsRemove) {
    +        this(TYPE, savedRegisters, savedRegisterLocations, supportsRemove);
    +    }
    +
    +    public AMD64SaveRegistersOp(LIRInstructionClass c, Register[] savedRegisters, StackSlotValue[] savedRegisterLocations, boolean supportsRemove) {
    +        super(c);
             assert Arrays.asList(savedRegisterLocations).stream().allMatch(ValueUtil::isVirtualStackSlot);
             this.savedRegisters = savedRegisters;
             this.slots = savedRegisterLocations;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java
    --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,12 +32,13 @@
     import com.oracle.graal.lir.amd64.AMD64Move.MemOp;
     import com.oracle.graal.lir.asm.*;
     
    -public class AMD64TestMemoryOp extends MemOp {
    +public final class AMD64TestMemoryOp extends MemOp {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64TestMemoryOp.class);
     
         @Use({REG, CONST}) protected Value y;
     
         public AMD64TestMemoryOp(Kind kind, AMD64AddressValue x, Value y, LIRFrameState state) {
    -        super(kind, x, state);
    +        super(TYPE, kind, x, state);
             this.y = y;
             this.state = state;
         }
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java
    --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,14 +28,17 @@
     import com.oracle.graal.api.meta.*;
     import com.oracle.graal.asm.amd64.*;
     import com.oracle.graal.compiler.common.*;
    +import com.oracle.graal.lir.*;
     import com.oracle.graal.lir.asm.*;
     
    -public class AMD64TestOp extends AMD64LIRInstruction {
    +public final class AMD64TestOp extends AMD64LIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64TestOp.class);
     
         @Use({REG}) protected Value x;
         @Use({REG, STACK, CONST}) protected Value y;
     
         public AMD64TestOp(Value x, Value y) {
    +        super(TYPE);
             this.x = x;
             this.y = y;
         }
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -40,6 +40,7 @@
      */
     @Opcode("ZAP_REGISTER")
     public final class AMD64ZapRegistersOp extends AMD64LIRInstruction implements SaveRegistersOp {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64ZapRegistersOp.class);
     
         /**
          * The registers that are zapped.
    @@ -52,6 +53,7 @@
         @Use({CONST}) protected JavaConstant[] zapValues;
     
         public AMD64ZapRegistersOp(Register[] zappedRegisters, JavaConstant[] zapValues) {
    +        super(TYPE);
             this.zappedRegisters = zappedRegisters;
             this.zapValues = zapValues;
         }
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,8 @@
     import com.oracle.graal.lir.*;
     import com.oracle.graal.lir.LIRInstruction.OperandFlag;
     
    -public class SPARCAddressValue extends CompositeValue {
    +public final class SPARCAddressValue extends CompositeValue {
    +    public static final CompositeValueClass TYPE = CompositeValueClass.create(SPARCAddressValue.class);
     
         private static final long serialVersionUID = -3583286416638228207L;
     
    @@ -44,7 +45,7 @@
         }
     
         public SPARCAddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index, int displacement) {
    -        super(kind);
    +        super(TYPE, kind);
             assert isIllegal(index) || displacement == 0;
             this.base = base;
             this.index = index;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -62,13 +62,15 @@
         /**
          * Unary operation with separate source and destination operand.
          */
    -    public static class Unary2Op extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final class Unary2Op extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(Unary2Op.class);
     
             @Opcode private final SPARCArithmetic opcode;
             @Def({REG, HINT}) protected AllocatableValue result;
             @Use({REG}) protected AllocatableValue x;
     
             public Unary2Op(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.result = result;
                 this.x = x;
    @@ -84,7 +86,8 @@
          * Binary operation with two operands. The first source operand is combined with the
          * destination. The second source operand must be a register.
          */
    -    public static class BinaryRegReg extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final class BinaryRegReg extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryRegReg.class);
     
             @Opcode private final SPARCArithmetic opcode;
             @Def({REG, HINT}) protected Value result;
    @@ -97,6 +100,7 @@
             }
     
             public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.result = result;
                 this.x = x;
    @@ -119,7 +123,8 @@
         /**
          * Binary operation with single source/destination operand and one constant.
          */
    -    public static class BinaryRegConst extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final class BinaryRegConst extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BinaryRegConst.class);
     
             @Opcode private final SPARCArithmetic opcode;
             @Def({REG, HINT}) protected AllocatableValue result;
    @@ -132,6 +137,7 @@
             }
     
             public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, Value x, JavaConstant y, LIRFrameState state) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.result = result;
                 this.x = x;
    @@ -154,7 +160,8 @@
         /**
          * Special LIR instruction as it requires a bunch of scratch registers.
          */
    -    public static class RemOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final class RemOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(RemOp.class);
     
             @Opcode private final SPARCArithmetic opcode;
             @Def({REG}) protected Value result;
    @@ -165,6 +172,7 @@
             @State protected LIRFrameState state;
     
             public RemOp(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state, LIRGeneratorTool gen) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.result = result;
                 this.x = x;
    @@ -189,7 +197,8 @@
         /**
          * Calculates the product and condition code for long multiplication of long values.
          */
    -    public static class SPARCLMulccOp extends SPARCLIRInstruction {
    +    public static final class SPARCLMulccOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCLMulccOp.class);
             @Def({REG}) protected Value result;
             @Alive({REG}) protected Value x;
             @Alive({REG}) protected Value y;
    @@ -197,6 +206,7 @@
             @Temp({REG}) protected Value scratch2;
     
             public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) {
    +            super(TYPE);
                 this.result = result;
                 this.x = x;
                 this.y = y;
    @@ -841,7 +851,8 @@
             }
         }
     
    -    public static class MulHighOp extends SPARCLIRInstruction {
    +    public static final class MulHighOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MulHighOp.class);
     
             @Opcode private final SPARCArithmetic opcode;
             @Def({REG}) public AllocatableValue result;
    @@ -850,6 +861,7 @@
             @Temp({REG}) public AllocatableValue scratch;
     
             public MulHighOp(SPARCArithmetic opcode, AllocatableValue x, AllocatableValue y, AllocatableValue result, AllocatableValue scratch) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.x = x;
                 this.y = y;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,8 @@
      * Emits code which compares two arrays of the same length.
      */
     @Opcode("ARRAY_EQUALS")
    -public class SPARCArrayEqualsOp extends SPARCLIRInstruction {
    +public final class SPARCArrayEqualsOp extends SPARCLIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCArrayEqualsOp.class);
     
         private final Kind kind;
         private final int arrayBaseOffset;
    @@ -67,6 +68,7 @@
         @Temp({REG}) protected Value temp5;
     
         public SPARCArrayEqualsOp(LIRGeneratorTool tool, Kind kind, Value result, Value array1, Value array2, Value length) {
    +        super(TYPE);
             this.kind = kind;
     
             Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass();
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -35,7 +35,8 @@
     import com.oracle.graal.lir.asm.*;
     import com.oracle.graal.lir.gen.*;
     
    -public class SPARCBitManipulationOp extends SPARCLIRInstruction {
    +public final class SPARCBitManipulationOp extends SPARCLIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBitManipulationOp.class);
     
         public enum IntrinsicOpcode {
             IPOPCNT,
    @@ -51,6 +52,7 @@
         @Temp({REG}) protected Value scratch;
     
         public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input, LIRGeneratorTool gen) {
    +        super(TYPE);
             this.opcode = opcode;
             this.result = result;
             this.input = input;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,8 @@
      * Emits a breakpoint.
      */
     @Opcode("BREAKPOINT")
    -public class SPARCBreakpointOp extends SPARCLIRInstruction {
    +public final class SPARCBreakpointOp extends SPARCLIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBreakpointOp.class);
     
         // historical - from hotspot src/cpu/sparc/vm
         //  promises that the system will not use traps 16-31
    @@ -46,6 +47,7 @@
         @Use({REG, STACK}) protected Value[] parameters;
     
         public SPARCBreakpointOp(Value[] parameters) {
    +        super(TYPE);
             this.parameters = parameters;
         }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,7 +35,8 @@
     import com.oracle.graal.lir.gen.*;
     
     @Opcode("BSWAP")
    -public class SPARCByteSwapOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +public final class SPARCByteSwapOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCByteSwapOp.class);
     
         @Def({REG, HINT}) protected Value result;
         @Use({REG}) protected Value input;
    @@ -43,6 +44,7 @@
         @Use({STACK}) protected StackSlotValue tmpSlot;
     
         public SPARCByteSwapOp(LIRGeneratorTool tool, Value result, Value input) {
    +        super(TYPE);
             this.result = result;
             this.input = input;
             this.tmpSlot = tool.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(Kind.Long));
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,15 @@
     public class SPARCCall {
     
         public abstract static class CallOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CallOp.class);
     
             @Def({REG, ILLEGAL}) protected Value result;
             @Use({REG, STACK}) protected Value[] parameters;
             @Temp protected Value[] temps;
             @State protected LIRFrameState state;
     
    -        public CallOp(Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    +        protected CallOp(LIRInstructionClass c, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    +            super(c);
                 this.result = result;
                 this.parameters = parameters;
                 this.state = state;
    @@ -58,27 +60,32 @@
         }
     
         public abstract static class MethodCallOp extends CallOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MethodCallOp.class);
     
             protected final ResolvedJavaMethod callTarget;
     
    -        public MethodCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    -            super(result, parameters, temps, state);
    +        protected MethodCallOp(LIRInstructionClass c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    +            super(c, result, parameters, temps, state);
                 this.callTarget = callTarget;
             }
     
         }
     
         @Opcode("CALL_DIRECT")
    -    public static class DirectCallOp extends MethodCallOp /* implements SPARCDelayedControlTransfer */{
    +    public abstract static class DirectCallOp extends MethodCallOp /*
    +                                                                    * implements
    +                                                                    * SPARCDelayedControlTransfer
    +                                                                    */{
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(DirectCallOp.class);
             private boolean emitted = false;
             private int before = -1;
     
    -        public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    -            super(callTarget, result, parameters, temps, state);
    +        public DirectCallOp(LIRInstructionClass c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    +            super(c, callTarget, result, parameters, temps, state);
             }
     
             @Override
    -        public final void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
    +        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
                 if (!emitted) {
                     emitCallPrefixCode(crb, masm);
                     directCall(crb, masm, callTarget, null, true, state);
    @@ -118,12 +125,14 @@
         }
     
         @Opcode("CALL_INDIRECT")
    -    public static class IndirectCallOp extends MethodCallOp {
    +    public abstract static class IndirectCallOp extends MethodCallOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(IndirectCallOp.class);
     
             @Use({REG}) protected Value targetAddress;
     
    -        public IndirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) {
    -            super(callTarget, result, parameters, temps, state);
    +        protected IndirectCallOp(LIRInstructionClass c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress,
    +                        LIRFrameState state) {
    +            super(c, callTarget, result, parameters, temps, state);
                 this.targetAddress = targetAddress;
             }
     
    @@ -140,11 +149,12 @@
         }
     
         public abstract static class ForeignCallOp extends CallOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ForeignCallOp.class);
     
             protected final ForeignCallLinkage callTarget;
     
    -        public ForeignCallOp(ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    -            super(result, parameters, temps, state);
    +        public ForeignCallOp(LIRInstructionClass c, ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    +            super(c, result, parameters, temps, state);
                 this.callTarget = callTarget;
             }
     
    @@ -155,10 +165,11 @@
         }
     
         @Opcode("NEAR_FOREIGN_CALL")
    -    public static class DirectNearForeignCallOp extends ForeignCallOp {
    +    public static final class DirectNearForeignCallOp extends ForeignCallOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(DirectNearForeignCallOp.class);
     
             public DirectNearForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    -            super(linkage, result, parameters, temps, state);
    +            super(TYPE, linkage, result, parameters, temps, state);
             }
     
             @Override
    @@ -168,10 +179,11 @@
         }
     
         @Opcode("FAR_FOREIGN_CALL")
    -    public static class DirectFarForeignCallOp extends ForeignCallOp {
    +    public static final class DirectFarForeignCallOp extends ForeignCallOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(DirectFarForeignCallOp.class);
     
             public DirectFarForeignCallOp(ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
    -            super(callTarget, result, parameters, temps, state);
    +            super(TYPE, callTarget, result, parameters, temps, state);
             }
     
             @Override
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -41,13 +41,15 @@
         FCMP,
         DCMP;
     
    -    public static class CompareOp extends SPARCLIRInstruction {
    +    public static final class CompareOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompareOp.class);
     
             @Opcode private final SPARCCompare opcode;
             @Use({REG}) protected Value x;
             @Use({REG, CONST}) protected Value y;
     
             public CompareOp(SPARCCompare opcode, Value x, Value y) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.x = x;
                 this.y = y;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,11 +51,13 @@
     
     public class SPARCControlFlow {
     
    -    public static class ReturnOp extends SPARCLIRInstruction implements BlockEndOp {
    +    public static final class ReturnOp extends SPARCLIRInstruction implements BlockEndOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ReturnOp.class);
     
             @Use({REG, ILLEGAL}) protected Value x;
     
             public ReturnOp(Value x) {
    +            super(TYPE);
                 this.x = x;
             }
     
    @@ -71,7 +73,8 @@
             }
         }
     
    -    public static class CompareBranchOp extends SPARCLIRInstruction implements BlockEndOp, SPARCDelayedControlTransfer {
    +    public static final class CompareBranchOp extends SPARCLIRInstruction implements BlockEndOp, SPARCDelayedControlTransfer {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompareBranchOp.class);
     
             private final SPARCCompare opcode;
             @Use({REG}) protected Value x;
    @@ -92,6 +95,7 @@
     
             public CompareBranchOp(SPARCCompare opcode, Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind, boolean unorderedIsTrue,
                             double trueDestinationProbability) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.x = x;
                 this.y = y;
    @@ -325,7 +329,8 @@
             }
         }
     
    -    public static class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
    +    public static final class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BranchOp.class);
             protected final ConditionFlag conditionFlag;
             protected final LabelRef trueDestination;
             protected final LabelRef falseDestination;
    @@ -333,6 +338,7 @@
             protected final double trueDestinationProbability;
     
             public BranchOp(ConditionFlag conditionFlag, LabelRef trueDestination, LabelRef falseDestination, Kind kind, double trueDestinationProbability) {
    +            super(TYPE);
                 this.trueDestination = trueDestination;
                 this.falseDestination = falseDestination;
                 this.kind = kind;
    @@ -383,7 +389,8 @@
             return true;
         }
     
    -    public static class StrategySwitchOp extends SPARCLIRInstruction implements BlockEndOp {
    +    public static final class StrategySwitchOp extends SPARCLIRInstruction implements BlockEndOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StrategySwitchOp.class);
             @Use({CONST}) protected JavaConstant[] keyConstants;
             private final LabelRef[] keyTargets;
             private LabelRef defaultTarget;
    @@ -392,6 +399,7 @@
             private final SwitchStrategy strategy;
     
             public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
    +            super(TYPE);
                 this.strategy = strategy;
                 this.keyConstants = strategy.keyConstants;
                 this.keyTargets = keyTargets;
    @@ -443,7 +451,8 @@
             }
         }
     
    -    public static class TableSwitchOp extends SPARCLIRInstruction implements BlockEndOp {
    +    public static final class TableSwitchOp extends SPARCLIRInstruction implements BlockEndOp {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TableSwitchOp.class);
     
             private final int lowKey;
             private final LabelRef defaultTarget;
    @@ -452,6 +461,7 @@
             @Temp protected Value scratch;
     
             public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) {
    +            super(TYPE);
                 this.lowKey = lowKey;
                 this.defaultTarget = defaultTarget;
                 this.targets = targets;
    @@ -514,7 +524,8 @@
         }
     
         @Opcode("CMOVE")
    -    public static class CondMoveOp extends SPARCLIRInstruction {
    +    public static final class CondMoveOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CondMoveOp.class);
     
             private final Kind kind;
     
    @@ -526,6 +537,7 @@
             private final CC cc;
     
             public CondMoveOp(Kind kind, Variable result, CC cc, ConditionFlag condition, Value trueValue, Value falseValue) {
    +            super(TYPE);
                 this.kind = kind;
                 this.result = result;
                 this.condition = condition;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -35,7 +35,7 @@
      *
      * 
      *   Base       Contents
    - * 
    + *
      *            :                                :  -----
      *   caller   | incoming overflow argument n   |    ^
      *   frame    :     ...                        :    | positive
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,12 +30,13 @@
     import com.oracle.graal.lir.StandardOp.JumpOp;
     import com.oracle.graal.lir.asm.*;
     
    -public class SPARCJumpOp extends JumpOp implements SPARCDelayedControlTransfer {
    +public final class SPARCJumpOp extends JumpOp implements SPARCDelayedControlTransfer {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCJumpOp.class);
         private boolean emitDone = false;
         private int delaySlotPosition = -1;
     
         public SPARCJumpOp(LabelRef destination) {
    -        super(destination);
    +        super(TYPE, destination);
         }
     
         public void emitControlTransfer(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,13 @@
     /**
      * Convenience class to provide SPARCMacroAssembler for the {@link #emitCode} method.
      */
    -public abstract class SPARCLIRInstruction extends LIRInstructionBase {
    +public abstract class SPARCLIRInstruction extends LIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCLIRInstruction.class);
    +
    +    protected SPARCLIRInstruction(LIRInstructionClass c) {
    +        super(c);
    +    }
    +
         protected SPARCDelayedControlTransfer delayedControlTransfer = SPARCDelayedControlTransfer.DUMMY;
     
         @Override
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,7 +30,8 @@
     import com.oracle.graal.lir.*;
     import com.oracle.graal.lir.asm.*;
     
    -public class SPARCMathIntrinsicOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +public final class SPARCMathIntrinsicOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCMathIntrinsicOp.class);
     
         public enum IntrinsicOpcode {
             SQRT,
    @@ -47,6 +48,7 @@
         @Use protected Value input;
     
         public SPARCMathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) {
    +        super(TYPE);
             this.opcode = opcode;
             this.result = result;
             this.input = input;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,11 +45,13 @@
     
         @Opcode("MOVE_TOREG")
         public static class MoveToRegOp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveToRegOp.class);
     
             @Def({REG, HINT}) protected AllocatableValue result;
             @Use({REG, STACK, CONST}) protected Value input;
     
             public MoveToRegOp(AllocatableValue result, Value input) {
    +            super(TYPE);
                 this.result = result;
                 this.input = input;
             }
    @@ -71,12 +73,14 @@
         }
     
         @Opcode("MOVE_FROMREG")
    -    public static class MoveFromRegOp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
    +    public static final class MoveFromRegOp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveFromRegOp.class);
     
             @Def({REG, STACK}) protected AllocatableValue result;
             @Use({REG, CONST, HINT}) protected Value input;
     
             public MoveFromRegOp(AllocatableValue result, Value input) {
    +            super(TYPE);
                 this.result = result;
                 this.input = input;
             }
    @@ -101,14 +105,15 @@
          * Move between floating-point and general purpose register domain (WITHOUT VIS3).
          */
         @Opcode("MOVE")
    -    public static class MoveFpGp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
    +    public static final class MoveFpGp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveFpGp.class);
     
             @Def({REG}) protected AllocatableValue result;
             @Use({REG}) protected AllocatableValue input;
             @Use({STACK}) protected StackSlotValue temp;
     
             public MoveFpGp(AllocatableValue result, AllocatableValue input, StackSlotValue temp) {
    -            super();
    +            super(TYPE);
                 this.result = result;
                 this.input = input;
                 this.temp = temp;
    @@ -195,13 +200,14 @@
          * Move between floating-point and general purpose register domain (WITH VIS3).
          */
         @Opcode("MOVE")
    -    public static class MoveFpGpVIS3 extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
    +    public static final class MoveFpGpVIS3 extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MoveFpGpVIS3.class);
     
             @Def({REG}) protected AllocatableValue result;
             @Use({REG}) protected AllocatableValue input;
     
             public MoveFpGpVIS3(AllocatableValue result, AllocatableValue input) {
    -            super();
    +            super(TYPE);
                 this.result = result;
                 this.input = input;
             }
    @@ -248,12 +254,14 @@
         }
     
         public abstract static class MemOp extends SPARCLIRInstruction implements ImplicitNullCheck {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MemOp.class);
     
             protected final Kind kind;
             @Use({COMPOSITE}) protected SPARCAddressValue address;
             @State protected LIRFrameState state;
     
    -        public MemOp(Kind kind, SPARCAddressValue address, LIRFrameState state) {
    +        public MemOp(LIRInstructionClass c, Kind kind, SPARCAddressValue address, LIRFrameState state) {
    +            super(c);
                 this.kind = kind;
                 this.address = address;
                 this.state = state;
    @@ -275,12 +283,13 @@
             }
         }
     
    -    public static class LoadOp extends MemOp implements SPARCTailDelayedLIRInstruction {
    +    public static final class LoadOp extends MemOp implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadOp.class);
     
             @Def({REG}) protected AllocatableValue result;
     
             public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state) {
    -            super(kind, address, state);
    +            super(TYPE, kind, address, state);
                 this.result = result;
             }
     
    @@ -327,12 +336,14 @@
             }
         }
     
    -    public static class LoadAddressOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final class LoadAddressOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadAddressOp.class);
     
             @Def({REG}) protected AllocatableValue result;
             @Use({COMPOSITE, UNINITIALIZED}) protected SPARCAddressValue addressValue;
     
             public LoadAddressOp(AllocatableValue result, SPARCAddressValue address) {
    +            super(TYPE);
                 this.result = result;
                 this.addressValue = address;
             }
    @@ -344,12 +355,14 @@
             }
         }
     
    -    public static class LoadDataAddressOp extends SPARCLIRInstruction {
    +    public static final class LoadDataAddressOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadDataAddressOp.class);
     
             @Def({REG}) protected AllocatableValue result;
             private final byte[] data;
     
             public LoadDataAddressOp(AllocatableValue result, byte[] data) {
    +            super(TYPE);
                 this.result = result;
                 this.data = data;
             }
    @@ -364,11 +377,13 @@
             }
         }
     
    -    public static class MembarOp extends SPARCLIRInstruction {
    +    public static final class MembarOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MembarOp.class);
     
             private final int barriers;
     
             public MembarOp(final int barriers) {
    +            super(TYPE);
                 this.barriers = barriers;
             }
     
    @@ -378,12 +393,14 @@
             }
         }
     
    -    public static class NullCheckOp extends SPARCLIRInstruction implements NullCheck, SPARCTailDelayedLIRInstruction {
    +    public static final class NullCheckOp extends SPARCLIRInstruction implements NullCheck, SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(NullCheckOp.class);
     
             @Use({REG}) protected AllocatableValue input;
             @State protected LIRFrameState state;
     
             public NullCheckOp(Variable input, LIRFrameState state) {
    +            super(TYPE);
                 this.input = input;
                 this.state = state;
             }
    @@ -405,7 +422,8 @@
         }
     
         @Opcode("CAS")
    -    public static class CompareAndSwapOp extends SPARCLIRInstruction {
    +    public static final class CompareAndSwapOp extends SPARCLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
     
             @Def({REG, HINT}) protected AllocatableValue result;
             @Alive({REG}) protected AllocatableValue address;
    @@ -413,6 +431,7 @@
             @Use({REG}) protected AllocatableValue newValue;
     
             public CompareAndSwapOp(AllocatableValue result, AllocatableValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
    +            super(TYPE);
                 this.result = result;
                 this.address = address;
                 this.cmpValue = cmpValue;
    @@ -426,12 +445,14 @@
             }
         }
     
    -    public static class StackLoadAddressOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +    public static final class StackLoadAddressOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StackLoadAddressOp.class);
     
             @Def({REG}) protected AllocatableValue result;
             @Use({STACK, UNINITIALIZED}) protected StackSlotValue slot;
     
             public StackLoadAddressOp(AllocatableValue result, StackSlotValue address) {
    +            super(TYPE);
                 this.result = result;
                 this.slot = address;
             }
    @@ -462,11 +483,12 @@
         }
     
         public static class StoreOp extends MemOp implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StoreOp.class);
     
             @Use({REG}) protected AllocatableValue input;
     
             public StoreOp(Kind kind, SPARCAddressValue address, AllocatableValue input, LIRFrameState state) {
    -            super(kind, address, state);
    +            super(TYPE, kind, address, state);
                 this.input = input;
             }
     
    @@ -511,12 +533,13 @@
             }
         }
     
    -    public static class StoreConstantOp extends MemOp implements SPARCTailDelayedLIRInstruction {
    +    public static final class StoreConstantOp extends MemOp implements SPARCTailDelayedLIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StoreConstantOp.class);
     
             protected final JavaConstant input;
     
             public StoreConstantOp(Kind kind, SPARCAddressValue address, JavaConstant input, LIRFrameState state) {
    -            super(kind, address, state);
    +            super(TYPE, kind, address, state);
                 this.input = input;
                 if (!input.isDefaultForKind()) {
                     throw GraalInternalError.shouldNotReachHere("Can only store null constants to memory");
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -40,6 +40,7 @@
      */
     @Opcode("SAVE_REGISTER")
     public class SPARCSaveRegistersOp extends SPARCLIRInstruction implements SaveRegistersOp {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCSaveRegistersOp.class);
         public static final Register RETURN_REGISTER_STORAGE = SPARC.d62;
         /**
          * The registers (potentially) saved by this operation.
    @@ -64,6 +65,7 @@
          * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned}
          */
         public SPARCSaveRegistersOp(Register[] savedRegisters, StackSlotValue[] savedRegisterLocations, boolean supportsRemove) {
    +        super(TYPE);
             assert Arrays.asList(savedRegisterLocations).stream().allMatch(ValueUtil::isVirtualStackSlot);
             this.savedRegisters = savedRegisters;
             this.slots = savedRegisterLocations;
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java
    --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,14 +29,17 @@
     import com.oracle.graal.api.meta.*;
     import com.oracle.graal.asm.sparc.*;
     import com.oracle.graal.compiler.common.*;
    +import com.oracle.graal.lir.*;
     import com.oracle.graal.lir.asm.*;
     
     public class SPARCTestOp extends SPARCLIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCTestOp.class);
     
         @Use({REG}) protected Value x;
         @Use({REG, CONST}) protected Value y;
     
         public SPARCTestOp(Value x, Value y) {
    +        super(TYPE);
             this.x = x;
             this.y = y;
         }
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java
    --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,12 +39,13 @@
     public class CompositeValueReplacementTest1 {
     
         private static class NestedCompositeValue extends CompositeValue {
    +        public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class);
     
             private static final long serialVersionUID = -8804214200173503527L;
             @Component({REG, OperandFlag.ILLEGAL}) protected Value value;
     
             public NestedCompositeValue(Value value) {
    -            super(LIRKind.Illegal);
    +            super(TYPE, LIRKind.Illegal);
                 this.value = value;
             }
     
    @@ -94,11 +95,13 @@
     
         }
     
    -    private static class TestOp extends LIRInstructionBase {
    +    private static final class TestOp extends LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class);
     
             @Use({COMPOSITE}) protected NestedCompositeValue compValue;
     
             public TestOp(NestedCompositeValue compValue) {
    +            super(TYPE);
                 this.compValue = compValue;
             }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java
    --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -40,12 +40,13 @@
     public class CompositeValueReplacementTest2 {
     
         private static class NestedCompositeValue extends CompositeValue {
    +        public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class);
     
             private static final long serialVersionUID = -8804214200173503527L;
             @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values;
     
             public NestedCompositeValue(Value value) {
    -            super(LIRKind.Illegal);
    +            super(TYPE, LIRKind.Illegal);
                 this.values = new Value[]{value};
             }
     
    @@ -95,11 +96,13 @@
     
         }
     
    -    private static class TestOp extends LIRInstructionBase {
    +    private static final class TestOp extends LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class);
     
             @Use({COMPOSITE}) protected NestedCompositeValue compValue;
     
             public TestOp(NestedCompositeValue compValue) {
    +            super(TYPE);
                 this.compValue = compValue;
             }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java
    --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -40,12 +40,13 @@
     public class CompositeValueReplacementTest3 {
     
         private static class NestedCompositeValue extends CompositeValue {
    +        public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class);
     
             private static final long serialVersionUID = -8804214200173503527L;
             @Component({REG, OperandFlag.ILLEGAL}) protected Value value;
     
             public NestedCompositeValue(Value value) {
    -            super(LIRKind.Illegal);
    +            super(TYPE, LIRKind.Illegal);
                 this.value = value;
             }
     
    @@ -95,11 +96,13 @@
     
         }
     
    -    private static class TestOp extends LIRInstructionBase {
    +    private static final class TestOp extends LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class);
     
             @Use({COMPOSITE}) protected NestedCompositeValue compValue;
     
             public TestOp(NestedCompositeValue compValue) {
    +            super(TYPE);
                 this.compValue = compValue;
             }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java
    --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -40,12 +40,13 @@
     public class CompositeValueReplacementTest4 {
     
         private static class NestedCompositeValue extends CompositeValue {
    +        public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class);
     
             private static final long serialVersionUID = -8804214200173503527L;
             @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values;
     
             public NestedCompositeValue(Value value) {
    -            super(LIRKind.Illegal);
    +            super(TYPE, LIRKind.Illegal);
                 this.values = new Value[]{value};
             }
     
    @@ -95,11 +96,13 @@
     
         }
     
    -    private static class TestOp extends LIRInstructionBase {
    +    private static class TestOp extends LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class);
     
             @Use({COMPOSITE}) protected NestedCompositeValue compValue;
     
             public TestOp(NestedCompositeValue compValue) {
    +            super(TYPE);
                 this.compValue = compValue;
             }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java
    --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,12 +37,13 @@
     public class ValuePositionTest1 {
     
         private static class NestedCompositeValue extends CompositeValue {
    +        public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class);
     
             private static final long serialVersionUID = -8804214200173503527L;
             @Component({REG, OperandFlag.ILLEGAL}) protected Value value;
     
             public NestedCompositeValue(Value value) {
    -            super(LIRKind.Illegal);
    +            super(TYPE, LIRKind.Illegal);
                 this.value = value;
             }
     
    @@ -86,11 +87,13 @@
             }
         }
     
    -    private static class TestOp extends LIRInstructionBase {
    +    private static final class TestOp extends LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class);
     
             @Use({COMPOSITE}) protected NestedCompositeValue compValue;
     
             public TestOp(NestedCompositeValue compValue) {
    +            super(TYPE);
                 this.compValue = compValue;
             }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java
    --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,14 @@
     public class ValuePositionTest2 {
     
         private static class NestedCompositeValue extends CompositeValue {
    +        public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class);
     
             private static final long serialVersionUID = -2243948303328857965L;
             @Component({REG, OperandFlag.ILLEGAL}) protected Value value1;
             @Component({REG, OperandFlag.ILLEGAL}) protected Value value2;
     
             public NestedCompositeValue(Value value1, Value value2) {
    -            super(LIRKind.Illegal);
    +            super(TYPE, LIRKind.Illegal);
                 this.value1 = value1;
                 this.value2 = value2;
             }
    @@ -88,11 +89,13 @@
             }
         }
     
    -    private static class TestOp extends LIRInstructionBase {
    +    private static class TestOp extends LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class);
     
             @Use({COMPOSITE}) protected NestedCompositeValue compValue;
     
             public TestOp(NestedCompositeValue compValue) {
    +            super(TYPE);
                 this.compValue = compValue;
             }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest3.java
    --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest3.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest3.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,6 +38,7 @@
     public class ValuePositionTest3 {
     
         public static final class TestAddressValue extends CompositeValue {
    +        public static final CompositeValueClass TYPE = CompositeValueClass.create(TestAddressValue.class);
     
             private static final long serialVersionUID = -2679790860680123026L;
     
    @@ -49,7 +50,7 @@
             }
     
             public TestAddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index) {
    -            super(kind);
    +            super(TYPE, kind);
                 this.base = base;
                 this.index = index;
             }
    @@ -99,11 +100,13 @@
     
         }
     
    -    private static class TestOp extends LIRInstructionBase {
    +    private static class TestOp extends LIRInstruction {
    +        public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class);
     
             @Use({COMPOSITE}) protected Value value;
     
             public TestOp(Value value) {
    +            super(TYPE);
                 this.value = value;
             }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -44,14 +44,15 @@
             OperandFlag[] value() default OperandFlag.REG;
         }
     
    -    private final CompositeValueClass valueClass;
    +    private final CompositeValueClass valueClass;
     
         private static final DebugMetric COMPOSITE_VALUE_COUNT = Debug.metric("CompositeValues");
     
    -    public CompositeValue(LIRKind kind) {
    +    public CompositeValue(CompositeValueClass c, LIRKind kind) {
             super(kind);
             COMPOSITE_VALUE_COUNT.increment();
    -        valueClass = CompositeValueClass.get(getClass());
    +        valueClass = c;
    +        assert c.getClazz() == this.getClass();
         }
     
         final CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
    @@ -81,7 +82,7 @@
             return false;
         }
     
    -    CompositeValueClass getValueClass() {
    +    CompositeValueClass getValueClass() {
             return valueClass;
         }
     
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -38,30 +38,17 @@
      * such fields.
      * 
      */
    -public class CompositeValueClass extends LIRIntrospection {
    -
    -    public static final CompositeValueClass get(Class c) {
    -        CompositeValueClass clazz = (CompositeValueClass) allClasses.get(c);
    -        if (clazz != null) {
    -            return clazz;
    -        }
    +public class CompositeValueClass extends LIRIntrospection {
     
    -        // We can have a race of multiple threads creating the LIRInstructionClass at the same time.
    -        // However, only one will be put into the map, and this is the one returned by all threads.
    -        clazz = new CompositeValueClass(c);
    -        CompositeValueClass oldClazz = (CompositeValueClass) allClasses.putIfAbsent(c, clazz);
    -        if (oldClazz != null) {
    -            return oldClazz;
    -        } else {
    -            return clazz;
    -        }
    +    public static final  CompositeValueClass create(Class c) {
    +        return new CompositeValueClass<>(c);
         }
     
    -    public CompositeValueClass(Class clazz) {
    +    public CompositeValueClass(Class clazz) {
             this(clazz, new FieldsScanner.DefaultCalcOffset());
         }
     
    -    public CompositeValueClass(Class clazz, FieldsScanner.CalcOffset calcOffset) {
    +    public CompositeValueClass(Class clazz, FieldsScanner.CalcOffset calcOffset) {
             super(clazz);
     
             CompositeValueFieldsScanner vfs = new CompositeValueFieldsScanner(calcOffset);
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java
    --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -35,18 +35,18 @@
     /**
      * This class performs basic optimizations on the control flow graph after LIR generation.
      */
    -public final class ControlFlowOptimizer extends LIRLowTierPhase {
    +public final class ControlFlowOptimizer extends PostAllocationOptimizationPhase {
     
         /**
          * Performs control flow optimizations on the given LIR graph.
          */
         @Override
    -    protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) {
    +    protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) {
             LIR lir = lirGenRes.getLIR();
             new Optimizer(lir).deleteEmptyBlocks(codeEmittingOrder);
         }
     
    -    private static final class Optimizer> {
    +    private static final class Optimizer> {
     
             private final LIR lir;
     
    @@ -97,7 +97,7 @@
                     if (canDeleteBlock(block)) {
                         // adjust successor and predecessor lists
                         B other = block.getSuccessors().iterator().next();
    -                    for (AbstractBlock pred : block.getPredecessors()) {
    +                    for (AbstractBlockBase pred : block.getPredecessors()) {
                             Collections.replaceAll(pred.getSuccessors(), block, other);
                         }
                         for (int i = 0; i < other.getPredecessorCount(); i++) {
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java
    --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -48,17 +48,17 @@
      * Because this optimization works best when a block contains only a few moves, it has a huge impact
      * on the number of blocks that are totally empty.
      */
    -public final class EdgeMoveOptimizer extends LIRLowTierPhase {
    +public final class EdgeMoveOptimizer extends PostAllocationOptimizationPhase {
     
         @Override
    -    protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) {
    +    protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) {
             LIR ir = lirGenRes.getLIR();
             Optimizer optimizer = new Optimizer(ir);
     
    -        List> blockList = ir.linearScanOrder();
    +        List> blockList = ir.linearScanOrder();
             // ignore the first block in the list (index 0 is not processed)
             for (int i = blockList.size() - 1; i >= 1; i--) {
    -            AbstractBlock block = blockList.get(i);
    +            AbstractBlockBase block = blockList.get(i);
     
                 if (block.getPredecessorCount() > 1) {
                     optimizer.optimizeMovesAtBlockEnd(block);
    @@ -106,8 +106,8 @@
              * Moves the longest {@linkplain #same common} subsequence at the end all predecessors of
              * {@code block} to the start of {@code block}.
              */
    -        private void optimizeMovesAtBlockEnd(AbstractBlock block) {
    -            for (AbstractBlock pred : block.getPredecessors()) {
    +        private void optimizeMovesAtBlockEnd(AbstractBlockBase block) {
    +            for (AbstractBlockBase pred : block.getPredecessors()) {
                     if (pred == block) {
                         // currently we can't handle this correctly.
                         return;
    @@ -121,7 +121,7 @@
                 assert numPreds > 1 : "do not call otherwise";
     
                 // setup a list with the LIR instructions of all predecessors
    -            for (AbstractBlock pred : block.getPredecessors()) {
    +            for (AbstractBlockBase pred : block.getPredecessors()) {
                     assert pred != null;
                     assert ir.getLIRforBlock(pred) != null;
                     List predInstructions = ir.getLIRforBlock(pred);
    @@ -176,7 +176,7 @@
              * {@code block} to the end of {@code block} just prior to the branch instruction ending
              * {@code block}.
              */
    -        private void optimizeMovesAtBlockBegin(AbstractBlock block) {
    +        private void optimizeMovesAtBlockBegin(AbstractBlockBase block) {
     
                 edgeInstructionSeqences.clear();
                 int numSux = block.getSuccessorCount();
    @@ -206,7 +206,7 @@
                 int insertIdx = instructions.size() - 1;
     
                 // setup a list with the lir-instructions of all successors
    -            for (AbstractBlock sux : block.getSuccessors()) {
    +            for (AbstractBlockBase sux : block.getSuccessors()) {
                     List suxInstructions = ir.getLIRforBlock(sux);
     
                     assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label";
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FullInfopointOp.java
    --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FullInfopointOp.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FullInfopointOp.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -29,13 +29,15 @@
      * Emits an infopoint (only mark the position).
      */
     @Opcode("INFOPOINT")
    -public class FullInfopointOp extends LIRInstructionBase {
    +public final class FullInfopointOp extends LIRInstruction {
    +    public static final LIRInstructionClass TYPE = LIRInstructionClass.create(FullInfopointOp.class);
     
         @State protected LIRFrameState state;
     
         private final InfopointReason reason;
     
         public FullInfopointOp(LIRFrameState state, InfopointReason reason) {
    +        super(TYPE);
             this.state = state;
             this.reason = reason;
         }
    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java
    --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -24,7 +24,6 @@
     
     import java.util.*;
     
    -import com.oracle.graal.api.meta.*;
     import com.oracle.graal.compiler.common.cfg.*;
     import com.oracle.graal.lir.StandardOp.BlockEndOp;
     import com.oracle.graal.lir.StandardOp.LabelOp;
    @@ -40,32 +39,25 @@
         /**
          * The linear-scan ordered list of blocks.
          */
    -    private final List> linearScanOrder;
    +    private final List> linearScanOrder;
     
         /**
          * The order in which the code is emitted.
          */
    -    private final List> codeEmittingOrder;
    +    private final List> codeEmittingOrder;
     
         private int firstVariableNumber;
     
         private int numVariables;
     
    -    private SpillMoveFactory spillMoveFactory;
    -
         private final BlockMap> lirInstructions;
     
    -    public interface SpillMoveFactory {
    -
    -        LIRInstruction createMove(AllocatableValue result, Value input);
    -    }
    -
         private boolean hasArgInCallerFrame;
     
         /**
          * Creates a new LIR instance for the specified compilation.
          */
    -    public LIR(AbstractControlFlowGraph cfg, List> linearScanOrder, List> codeEmittingOrder) {
    +    public LIR(AbstractControlFlowGraph cfg, List> linearScanOrder, List> codeEmittingOrder) {
             this.cfg = cfg;
             this.codeEmittingOrder = codeEmittingOrder;
             this.linearScanOrder = linearScanOrder;
    @@ -80,7 +72,7 @@
          * Determines if any instruction in the LIR has debug info associated with it.
          */
         public boolean hasDebugInfo() {
    -        for (AbstractBlock b : linearScanOrder()) {
    +        for (AbstractBlockBase b : linearScanOrder()) {
                 for (LIRInstruction op : getLIRforBlock(b)) {
                     if (op.hasState()) {
                         return true;
    @@ -90,15 +82,11 @@
             return false;
         }
     
    -    public SpillMoveFactory getSpillMoveFactory() {
    -        return spillMoveFactory;
    -    }
    -
    -    public List getLIRforBlock(AbstractBlock block) {
    +    public List getLIRforBlock(AbstractBlockBase block) {
             return lirInstructions.get(block);
         }
     
    -    public void setLIRforBlock(AbstractBlock block, List list) {
    +    public void setLIRforBlock(AbstractBlockBase block, List list) {
             assert getLIRforBlock(block) == null : "lir instruction list should only be initialized once";
             lirInstructions.put(block, list);
         }
    @@ -108,11 +96,11 @@
          *
          * @return the blocks in linear scan order
          */
    -    public List> linearScanOrder() {
    +    public List> linearScanOrder() {
             return linearScanOrder;
         }
     
    -    public List> codeEmittingOrder() {
    +    public List> codeEmittingOrder() {
             return codeEmittingOrder;
         }
     
    @@ -166,7 +154,7 @@
          */
         public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 3;
     
    -    public static boolean verifyBlock(LIR lir, AbstractBlock block) {
    +    public static boolean verifyBlock(LIR lir, AbstractBlockBase block) {
             List ops = lir.getLIRforBlock(block);
             if (ops.size() == 0) {
                 return false;
    @@ -190,12 +178,12 @@
             return true;
         }
     
    -    public static boolean verifyBlocks(LIR lir, List> blocks) {
    -        for (AbstractBlock block : blocks) {
    -            for (AbstractBlock sux : block.getSuccessors()) {
    +    public static boolean verifyBlocks(LIR lir, List> blocks) {
    +        for (AbstractBlockBase block : blocks) {
    +            for (AbstractBlockBase sux : block.getSuccessors()) {
                     assert blocks.contains(sux) : "missing successor from: " + block + "to: " + sux;
                 }
    -            for (AbstractBlock pred : block.getPredecessors()) {
    +            for (AbstractBlockBase pred : block.getPredecessors()) {
                     assert blocks.contains(pred) : "missing predecessor from: " + block + "to: " + pred;
                 }
                 if (!verifyBlock(lir, block)) {
    @@ -205,13 +193,9 @@
             return true;
         }
     
    -    public void setSpillMoveFactory(SpillMoveFactory spillMoveFactory) {
    -        this.spillMoveFactory = spillMoveFactory;
    -    }
    -
         public void resetLabels() {
     
    -        for (AbstractBlock block : codeEmittingOrder()) {
    +        for (AbstractBlockBase block : codeEmittingOrder()) {
                 for (LIRInstruction inst : lirInstructions.get(block)) {
                     if (inst instanceof LabelOp) {
                         ((LabelOp) inst).getLabel().reset();
    diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Mar 02 19:11:22 2015 +0100
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
      * 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,24 +22,27 @@
      */
     package com.oracle.graal.lir;
     
    -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
    +import java.lang.annotation.*;
    +import java.util.*;
     
    -import java.lang.annotation.*;
    +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
    +import static com.oracle.graal.lir.LIRInstruction.OperandMode.*;
     
     import com.oracle.graal.api.code.*;
     import com.oracle.graal.api.meta.*;
    +import com.oracle.graal.debug.*;
     import com.oracle.graal.lir.asm.*;
     
     /**
    - * The {@code LIRInstruction} interface definition.
    + * The base class for an {@code LIRInstruction}.
      */
    -public interface LIRInstruction {
    -    Value[] NO_OPERANDS = {};
    +public abstract class LIRInstruction {
    +    public static final Value[] NO_OPERANDS = {};
     
         /**
          * Constants denoting how a LIR instruction uses an operand.
          */
    -    enum OperandMode {
    +    public enum OperandMode {
             /**
              * The value must have been defined before. It is alive before the instruction until the
              * beginning of the instruction, but not necessarily throughout the instruction. A register
    @@ -72,41 +75,41 @@
     
         @Retention(RetentionPolicy.RUNTIME)
         @Target(ElementType.FIELD)
    -    static @interface Use {
    +    public static @interface Use {
     
    -        OperandFlag[] value() default REG;
    +        OperandFlag[] value() default OperandFlag.REG;
         }
     
         @Retention(RetentionPolicy.RUNTIME)
         @Target(ElementType.FIELD)
    -    static @interface Alive {
    +    public static @interface Alive {
     
    -        OperandFlag[] value() default REG;
    +        OperandFlag[] value() default OperandFlag.REG;
         }
     
         @Retention(RetentionPolicy.RUNTIME)
         @Target(ElementType.FIELD)
    -    static @interface Temp {
    +    public static @interface Temp {
     
    -        OperandFlag[] value() default REG;
    +        OperandFlag[] value() default OperandFlag.REG;
         }
     
         @Retention(RetentionPolicy.RUNTIME)
         @Target(ElementType.FIELD)
    -    static @interface Def {
    +    public static @interface Def {
     
    -        OperandFlag[] value() default REG;
    +        OperandFlag[] value() default OperandFlag.REG;
         }
     
         @Retention(RetentionPolicy.RUNTIME)
         @Target(ElementType.FIELD)
    -    static @interface State {
    +    public static @interface State {
         }
     
         /**
          * Flags for an operand.
          */
    -    enum OperandFlag {
    +    public enum OperandFlag {
             /**
              * The value can be a {@link RegisterValue}.
              */
    @@ -145,115 +148,205 @@
             UNINITIALIZED,
         }
     
    -    void emitCode(CompilationResultBuilder crb);
    +    /**
    +     * For validity checking of the operand flags defined by instruction subclasses.
    +     */
    +    protected static final EnumMap> ALLOWED_FLAGS;
    +
    +    static {
    +        ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
    +        ALLOWED_FLAGS.put(OperandMode.USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED));
    +        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED));
    +        ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, COMPOSITE, CONST, ILLEGAL, HINT));
    +        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT));
    +    }
     
    -    int id();
    +    /**
    +     * The flags of the base and index value of an address.
    +     */
    +    protected static final EnumSet ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL);
    +
    +    private final LIRInstructionClass instructionClass;
     
    -    void setId(int id);
    +    /**
    +     * Instruction id for register allocation.
    +     */
    +    private int id;
    +
    +    private static final DebugMetric LIR_NODE_COUNT = Debug.metric("LIRNodes");
     
         /**
    -     * Gets the instruction name.
    +     * Constructs a new LIR instruction.
          */
    -    String name();
    +    public LIRInstruction(LIRInstructionClass c) {
    +        LIR_NODE_COUNT.increment();
    +        instructionClass = c;
    +        assert c.getClazz() == this.getClass();
    +        id = -1;
    +    }
     
    -    boolean hasOperands();
    +    public abstract void emitCode(CompilationResultBuilder crb);
    +
    +    public final int id() {
    +        return id;
    +    }
     
    -    boolean hasState();
    +    public final void setId(int id) {
    +        this.id = id;
    +    }
    +
    +    public final String name() {
    +        return instructionClass.getOpcode(this);
    +    }
     
    -    /**
    -     * Determines if this instruction destroys all caller-saved registers..
    -     */
    -    boolean destroysCallerSavedRegisters();
    +    public final boolean hasOperands() {
    +        return instructionClass.hasOperands() || hasState() || destroysCallerSavedRegisters();
    +    }
    +
    +    public final boolean hasState() {
    +        return instructionClass.hasState(this);
    +    }
    +
    +    public boolean destroysCallerSavedRegisters() {
    +        return false;
    +    }
     
         // ValuePositionProcedures
    -    void forEachInputPos(ValuePositionProcedure proc);
    +    public final void forEachInputPos(ValuePositionProcedure proc) {
    +        instructionClass.forEachUsePos(this, proc);
    +    }
     
    -    void forEachAlivePos(ValuePositionProcedure proc);
    +    public final void forEachAlivePos(ValuePositionProcedure proc) {
    +        instructionClass.forEachAlivePos(this, proc);
    +    }
     
    -    void forEachTempPos(ValuePositionProcedure proc);
    +    public final void forEachTempPos(ValuePositionProcedure proc) {
    +        instructionClass.forEachTempPos(this, proc);
    +    }
     
    -    void forEachOutputPos(ValuePositionProcedure proc);
    +    public final void forEachOutputPos(ValuePositionProcedure proc) {
    +        instructionClass.forEachDefPos(this, proc);
    +    }
     
         // InstructionValueProcedures
    -    void forEachInput(InstructionValueProcedure proc);
    +    public final void forEachInput(InstructionValueProcedure proc) {
    +        instructionClass.forEachUse(this, proc);
    +    }
     
    -    void forEachAlive(InstructionValueProcedure proc);
    +    public final void forEachAlive(InstructionValueProcedure proc) {
    +        instructionClass.forEachAlive(this, proc);
    +    }
     
    -    void forEachTemp(InstructionValueProcedure proc);
    +    public final void forEachTemp(InstructionValueProcedure proc) {
    +        instructionClass.forEachTemp(this, proc);
    +    }
     
    -    void forEachOutput(InstructionValueProcedure proc);
    +    public final void forEachOutput(InstructionValueProcedure proc) {
    +        instructionClass.forEachDef(this, proc);
    +    }
     
    -    void forEachState(InstructionValueProcedure proc);
    +    public final void forEachState(InstructionValueProcedure proc) {
    +        instructionClass.forEachState(this, proc);
    +    }
     
         // ValueProcedures
    -    void forEachInput(ValueProcedure proc);
    +    public final void forEachInput(ValueProcedure proc) {
    +        instructionClass.forEachUse(this, proc);
    +    }
     
    -    void forEachAlive(ValueProcedure proc);
    +    public final void forEachAlive(ValueProcedure proc) {
    +        instructionClass.forEachAlive(this, proc);
    +    }
     
    -    void forEachTemp(ValueProcedure proc);
    +    public final void forEachTemp(ValueProcedure proc) {
    +        instructionClass.forEachTemp(this, proc);
    +    }
     
    -    void forEachOutput(ValueProcedure proc);
    +    public final void forEachOutput(ValueProcedure proc) {
    +        instructionClass.forEachDef(this, proc);
    +    }
     
    -    void forEachState(ValueProcedure proc);
    +    public final void forEachState(ValueProcedure proc) {
    +        instructionClass.forEachState(this, proc);
    +    }
     
         // States
    -    void forEachState(InstructionStateProcedure proc);
    +    public final void forEachState(InstructionStateProcedure proc) {
    +        instructionClass.forEachState(this, proc);
    +    }
     
    -    void forEachState(StateProcedure proc);
    +    public final void forEachState(StateProcedure proc) {
    +        instructionClass.forEachState(this, proc);
    +    }
     
         // InstructionValueConsumers
    -    void visitEachInput(InstructionValueConsumer proc);
    +    public final void visitEachInput(InstructionValueConsumer proc) {
    +        instructionClass.forEachUse(this, proc);
    +    }
     
    -    void visitEachAlive(InstructionValueConsumer proc);
    +    public final void visitEachAlive(InstructionValueConsumer proc) {
    +        instructionClass.forEachAlive(this, proc);
    +    }
     
    -    void visitEachTemp(InstructionValueConsumer proc);
    +    public final void visitEachTemp(InstructionValueConsumer proc) {
    +        instructionClass.forEachTemp(this, proc);
    +    }
     
    -    void visitEachOutput(InstructionValueConsumer proc);
    +    public final void visitEachOutput(InstructionValueConsumer proc) {
    +        instructionClass.forEachDef(this, proc);
    +    }
     
    -    void visitEachState(InstructionValueConsumer proc);
    +    public final void visitEachState(InstructionValueConsumer proc) {
    +        instructionClass.forEachState(this, proc);
    +    }
     
         // ValueConsumers
    -    void visitEachInput(ValueConsumer proc);
    +    public final void visitEachInput(ValueConsumer proc) {
    +        instructionClass.forEachUse(this, proc);
    +    }
     
    -    void visitEachAlive(ValueConsumer proc);
    +    public final void visitEachAlive(ValueConsumer proc) {
    +        instructionClass.forEachAlive(this, proc);
    +    }
    +
    +    public final void visitEachTemp(ValueConsumer proc) {
    +        instructionClass.forEachTemp(this, proc);
    +    }
     
    -    void visitEachTemp(ValueConsumer proc);
    +    public final void visitEachOutput(ValueConsumer proc) {
    +        instructionClass.forEachDef(this, proc);
    +    }
     
    -    void visitEachOutput(ValueConsumer proc);
    +    public final void visitEachState(ValueConsumer proc) {
    +        instructionClass.forEachState(this, proc);
    +    }
     
    -    void visitEachState(ValueConsumer proc);
    +    @SuppressWarnings("unused")
    +    public final Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc) {
    +        return instructionClass.forEachRegisterHint(this, mode, proc);
    +    }
     
    -    /**
    -     * Iterates all register hints for the specified value, i.e., all preferred candidates for the
    -     * register to be assigned to the value.
    -     * 

    - * 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 - * value, the iteration is stopped and the value is returned by this method, i.e., - * clients can stop the iteration once a suitable hint has been found. - * @return The non-null value returned by the procedure, or null. - */ - Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc); + @SuppressWarnings("unused") + public final Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) { + return instructionClass.forEachRegisterHint(this, mode, proc); + } + + public void verify() { + } - /** - * @see #forEachRegisterHint(Value, OperandMode, InstructionValueProcedure) - * @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 - * value, the iteration is stopped and the value is returned by this method, i.e., - * clients can stop the iteration once a suitable hint has been found. - * @return The non-null value returned by the procedure, or null. - */ - Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc); + public final String toStringWithIdPrefix() { + if (id != -1) { + return String.format("%4d %s", id, toString()); + } + return " " + toString(); + } - String toStringWithIdPrefix(); + @Override + public String toString() { + return instructionClass.toString(this); + } - void verify(); - - LIRInstructionClass getLIRInstructionClass(); + public LIRInstructionClass getLIRInstructionClass() { + return instructionClass; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionBase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionBase.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,237 +0,0 @@ -/* - * 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 - * 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.lir; - -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import static com.oracle.graal.lir.LIRInstruction.OperandMode.*; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.lir.asm.*; - -/** - * The base class for an {@code LIRInstruction}. - */ -public abstract class LIRInstructionBase implements LIRInstruction { - - /** - * For validity checking of the operand flags defined by instruction subclasses. - */ - protected static final EnumMap> ALLOWED_FLAGS; - - static { - ALLOWED_FLAGS = new EnumMap<>(OperandMode.class); - ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED)); - ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED)); - ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, COMPOSITE, CONST, ILLEGAL, HINT)); - ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT)); - } - - /** - * The flags of the base and index value of an address. - */ - protected static final EnumSet ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL); - - private final LIRInstructionClass instructionClass; - - /** - * Instruction id for register allocation. - */ - private int id; - - private static final DebugMetric LIR_NODE_COUNT = Debug.metric("LIRNodes"); - - /** - * Constructs a new LIR instruction. - */ - public LIRInstructionBase() { - LIR_NODE_COUNT.increment(); - instructionClass = LIRInstructionClass.get(getClass()); - id = -1; - } - - public abstract void emitCode(CompilationResultBuilder crb); - - public final int id() { - return id; - } - - public final void setId(int id) { - this.id = id; - } - - public final String name() { - return instructionClass.getOpcode(this); - } - - public final boolean hasOperands() { - return instructionClass.hasOperands() || hasState() || destroysCallerSavedRegisters(); - } - - public final boolean hasState() { - return instructionClass.hasState(this); - } - - public boolean destroysCallerSavedRegisters() { - return false; - } - - // ValuePositionProcedures - public final void forEachInputPos(ValuePositionProcedure proc) { - instructionClass.forEachUsePos(this, proc); - } - - public final void forEachAlivePos(ValuePositionProcedure proc) { - instructionClass.forEachAlivePos(this, proc); - } - - public final void forEachTempPos(ValuePositionProcedure proc) { - instructionClass.forEachTempPos(this, proc); - } - - public final void forEachOutputPos(ValuePositionProcedure proc) { - instructionClass.forEachDefPos(this, proc); - } - - // InstructionValueProcedures - public final void forEachInput(InstructionValueProcedure proc) { - instructionClass.forEachUse(this, proc); - } - - public final void forEachAlive(InstructionValueProcedure proc) { - instructionClass.forEachAlive(this, proc); - } - - public final void forEachTemp(InstructionValueProcedure proc) { - instructionClass.forEachTemp(this, proc); - } - - public final void forEachOutput(InstructionValueProcedure proc) { - instructionClass.forEachDef(this, proc); - } - - public final void forEachState(InstructionValueProcedure proc) { - instructionClass.forEachState(this, proc); - } - - // ValueProcedures - public final void forEachInput(ValueProcedure proc) { - instructionClass.forEachUse(this, proc); - } - - public final void forEachAlive(ValueProcedure proc) { - instructionClass.forEachAlive(this, proc); - } - - public final void forEachTemp(ValueProcedure proc) { - instructionClass.forEachTemp(this, proc); - } - - public final void forEachOutput(ValueProcedure proc) { - instructionClass.forEachDef(this, proc); - } - - public final void forEachState(ValueProcedure proc) { - instructionClass.forEachState(this, proc); - } - - // States - public final void forEachState(InstructionStateProcedure proc) { - instructionClass.forEachState(this, proc); - } - - public final void forEachState(StateProcedure proc) { - instructionClass.forEachState(this, proc); - } - - // InstructionValueConsumers - public final void visitEachInput(InstructionValueConsumer proc) { - instructionClass.forEachUse(this, proc); - } - - public final void visitEachAlive(InstructionValueConsumer proc) { - instructionClass.forEachAlive(this, proc); - } - - public final void visitEachTemp(InstructionValueConsumer proc) { - instructionClass.forEachTemp(this, proc); - } - - public final void visitEachOutput(InstructionValueConsumer proc) { - instructionClass.forEachDef(this, proc); - } - - public final void visitEachState(InstructionValueConsumer proc) { - instructionClass.forEachState(this, proc); - } - - // ValueConsumers - public final void visitEachInput(ValueConsumer proc) { - instructionClass.forEachUse(this, proc); - } - - public final void visitEachAlive(ValueConsumer proc) { - instructionClass.forEachAlive(this, proc); - } - - public final void visitEachTemp(ValueConsumer proc) { - instructionClass.forEachTemp(this, proc); - } - - public final void visitEachOutput(ValueConsumer proc) { - instructionClass.forEachDef(this, proc); - } - - public final void visitEachState(ValueConsumer proc) { - instructionClass.forEachState(this, proc); - } - - public Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc) { - return instructionClass.forEachRegisterHint(this, mode, proc); - } - - public Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) { - return instructionClass.forEachRegisterHint(this, mode, proc); - } - - public void verify() { - } - - public final String toStringWithIdPrefix() { - if (id != -1) { - return String.format("%4d %s", id, toString()); - } - return " " + toString(); - } - - @Override - public String toString() { - return instructionClass.toString(this); - } - - public LIRInstructionClass getLIRInstructionClass() { - return instructionClass; - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,23 +31,10 @@ import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -public class LIRInstructionClass extends LIRIntrospection { - - public static final LIRInstructionClass get(Class c) { - LIRInstructionClass clazz = (LIRInstructionClass) allClasses.get(c); - if (clazz != null) { - return clazz; - } +public class LIRInstructionClass extends LIRIntrospection { - // We can have a race of multiple threads creating the LIRInstructionClass at the same time. - // However, only one will be put into the map, and this is the one returned by all threads. - clazz = new LIRInstructionClass(c); - LIRInstructionClass oldClazz = (LIRInstructionClass) allClasses.putIfAbsent(c, clazz); - if (oldClazz != null) { - return oldClazz; - } else { - return clazz; - } + public static final LIRInstructionClass create(Class c) { + return new LIRInstructionClass<>(c); } private static final Class INSTRUCTION_CLASS = LIRInstruction.class; @@ -62,11 +49,11 @@ private String opcodeConstant; private int opcodeIndex; - private LIRInstructionClass(Class clazz) { + private LIRInstructionClass(Class clazz) { this(clazz, new FieldsScanner.DefaultCalcOffset()); } - public LIRInstructionClass(Class clazz, FieldsScanner.CalcOffset calcOffset) { + public LIRInstructionClass(Class clazz, FieldsScanner.CalcOffset calcOffset) { super(clazz); assert INSTRUCTION_CLASS.isAssignableFrom(clazz); @@ -134,7 +121,7 @@ } opcodeField = null; - super.scan(clazz, LIRInstructionBase.class, false); + super.scan(clazz, LIRInstruction.class, false); if (opcodeConstant == null && opcodeField == null) { opcodeConstant = clazz.getSimpleName(); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,7 +35,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; -abstract class LIRIntrospection extends FieldIntrospection { +abstract class LIRIntrospection extends FieldIntrospection { private static final Class VALUE_CLASS = Value.class; private static final Class CONSTANT_CLASS = JavaConstant.class; @@ -44,7 +44,7 @@ private static final Class STACK_SLOT_CLASS = StackSlot.class; private static final Class VALUE_ARRAY_CLASS = Value[].class; - public LIRIntrospection(Class clazz) { + public LIRIntrospection(Class clazz) { super(clazz); } @@ -202,7 +202,7 @@ protected static void forEach(LIRInstruction inst, Values values, OperandMode mode, InstructionValueProcedure proc) { for (int i = 0; i < values.getCount(); i++) { - assert LIRInstructionBase.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); if (i < values.getDirectCount()) { Value value = values.getValue(inst, i); @@ -238,7 +238,7 @@ protected static CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, Values values, OperandMode mode, InstructionValueProcedure proc) { CompositeValue newCompValue = null; for (int i = 0; i < values.getCount(); i++) { - assert LIRInstructionBase.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); if (i < values.getDirectCount()) { Value value = values.getValue(obj, i); @@ -286,7 +286,7 @@ protected static void forEach(LIRInstruction inst, Object obj, Values values, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { for (int i = 0; i < values.getCount(); i++) { - assert LIRInstructionBase.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); if (i < values.getDirectCount()) { Value value = values.getValue(obj, i); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Mar 02 19:11:22 2015 +0100 @@ -46,11 +46,11 @@ private final BitSet[] blockLiveOut; private final Object[] variableDefinitions; - private BitSet liveOutFor(AbstractBlock block) { + private BitSet liveOutFor(AbstractBlockBase block) { return blockLiveOut[block.getId()]; } - private void setLiveOutFor(AbstractBlock block, BitSet liveOut) { + private void setLiveOutFor(AbstractBlockBase block, BitSet liveOut) { blockLiveOut[block.getId()] = liveOut; } @@ -91,7 +91,7 @@ private BitSet curVariablesLive; private Value[] curRegistersLive; - private AbstractBlock curBlock; + private AbstractBlockBase curBlock; private Object curInstruction; private BitSet curRegistersDefined; @@ -113,7 +113,7 @@ int maxRegisterNum = maxRegisterNum(); curRegistersDefined = new BitSet(); - for (AbstractBlock block : lir.linearScanOrder()) { + for (AbstractBlockBase block : lir.linearScanOrder()) { curBlock = block; curVariablesLive = new BitSet(); curRegistersLive = new Value[maxRegisterNum]; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java Mon Mar 02 19:11:22 2015 +0100 @@ -29,16 +29,17 @@ /** * LIR instructions such as {@link JumpOp} and {@link BranchOp} need to reference their target - * {@link AbstractBlock}. However, direct references are not possible since the control flow graph - * (and therefore successors lists) can be changed by optimizations - and fixing the instructions is - * error prone. Therefore, we represent an edge to block B from block A via the tuple {@code (A, + * {@link AbstractBlockBase}. However, direct references are not possible since the control flow + * graph (and therefore successors lists) can be changed by optimizations - and fixing the + * instructions is error prone. Therefore, we represent an edge to block B from block A via the + * tuple {@code (A, * successor-index-of-B)}. That is, indirectly by storing the index into the successor list of A. * Note therefore that the successor list cannot be re-ordered. */ public final class LabelRef { private final LIR lir; - private final AbstractBlock block; + private final AbstractBlockBase block; private final int suxIndex; /** @@ -48,7 +49,7 @@ * @param suxIndex The index of the successor. * @return The newly created label reference. */ - public static LabelRef forSuccessor(final LIR lir, final AbstractBlock block, final int suxIndex) { + public static LabelRef forSuccessor(final LIR lir, final AbstractBlockBase block, final int suxIndex) { return new LabelRef(lir, block, suxIndex); } @@ -58,17 +59,17 @@ * @param block The base block that contains the successor list. * @param suxIndex The index of the successor. */ - private LabelRef(final LIR lir, final AbstractBlock block, final int suxIndex) { + private LabelRef(final LIR lir, final AbstractBlockBase block, final int suxIndex) { this.lir = lir; this.block = block; this.suxIndex = suxIndex; } - public AbstractBlock getSourceBlock() { + public AbstractBlockBase getSourceBlock() { return block; } - public AbstractBlock getTargetBlock() { + public AbstractBlockBase getTargetBlock() { return block.getSuccessors().get(suxIndex); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,17 +31,17 @@ import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.phases.*; -public final class NullCheckOptimizer extends LIRLowTierPhase { +public final class NullCheckOptimizer extends PostAllocationOptimizationPhase { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { LIR ir = lirGenRes.getLIR(); - List> blocks = ir.codeEmittingOrder(); + List> blocks = ir.codeEmittingOrder(); NullCheckOptimizer.foldNullChecks(ir, blocks, target.implicitNullCheckLimit); } - private static void foldNullChecks(LIR ir, List> blocks, int implicitNullCheckLimit) { - for (AbstractBlock block : blocks) { + private static void foldNullChecks(LIR ir, List> blocks, int implicitNullCheckLimit) { + for (AbstractBlockBase block : blocks) { List list = ir.getLIRforBlock(block); if (!list.isEmpty()) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Mon Mar 02 19:11:22 2015 +0100 @@ -41,10 +41,10 @@ /** * Removes move instructions, where the destination value is already in place. */ -public final class RedundantMoveElimination extends LIRLowTierPhase { +public final class RedundantMoveElimination extends PostAllocationOptimizationPhase { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { Optimization redundantMoveElimination = new Optimization(); redundantMoveElimination.doOptimize(lirGenRes.getLIR(), lirGenRes.getFrameMap()); } @@ -87,7 +87,7 @@ private static final class Optimization { - Map, BlockData> blockData = CollectionsFactory.newMap(); + Map, BlockData> blockData = CollectionsFactory.newMap(); Register[] callerSaveRegs; @@ -142,7 +142,7 @@ private void initBlockData(LIR lir) { - List> blocks = lir.linearScanOrder(); + List> blocks = lir.linearScanOrder(); numRegs = 0; int maxStackLocations = COMPLEXITY_LIMIT / blocks.size(); @@ -151,7 +151,7 @@ * Search for relevant locations which can be optimized. These are register or stack * slots which occur as destinations of move instructions. */ - for (AbstractBlock block : blocks) { + for (AbstractBlockBase block : blocks) { List instructions = lir.getLIRforBlock(block); for (LIRInstruction op : instructions) { if (isEligibleMove(op)) { @@ -176,7 +176,7 @@ */ int numLocations = numRegs + stackIndices.size(); Debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size()); - for (AbstractBlock block : blocks) { + for (AbstractBlockBase block : blocks) { BlockData data = new BlockData(numLocations); blockData.put(block, data); } @@ -191,7 +191,7 @@ try (Indent indent = Debug.logAndIndent("solve data flow")) { - List> blocks = lir.linearScanOrder(); + List> blocks = lir.linearScanOrder(); int numIter = 0; @@ -205,7 +205,7 @@ changed = false; try (Indent indent2 = Debug.logAndIndent("new iteration")) { - for (AbstractBlock block : blocks) { + for (AbstractBlockBase block : blocks) { BlockData data = blockData.get(block); /* @@ -235,7 +235,7 @@ /* * Merge the states of predecessor blocks */ - for (AbstractBlock predecessor : block.getPredecessors()) { + for (AbstractBlockBase predecessor : block.getPredecessors()) { BlockData predData = blockData.get(predecessor); newState |= mergeState(data.entryState, predData.exitState, valueNum); } @@ -291,9 +291,9 @@ try (Indent indent = Debug.logAndIndent("eliminate moves")) { - List> blocks = lir.linearScanOrder(); + List> blocks = lir.linearScanOrder(); - for (AbstractBlock block : blocks) { + for (AbstractBlockBase block : blocks) { try (Indent indent2 = Debug.logAndIndent("eliminate moves in block %d", block.getId())) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,11 +26,13 @@ import com.oracle.graal.lir.asm.*; @Opcode("SIMPLE_INFOPOINT") -public class SimpleInfopointOp extends LIRInstructionBase { +public final class SimpleInfopointOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SimpleInfopointOp.class); private final InfopointReason reason; private final BytecodePosition position; public SimpleInfopointOp(InfopointReason reason, BytecodePosition position) { + super(TYPE); this.reason = reason; this.position = position; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Mon Mar 02 19:11:22 2015 +0100 @@ -44,23 +44,24 @@ * A block delimiter. Every well formed block must contain exactly one such operation and it * must be the last operation in the block. */ - public interface BlockEndOp extends LIRInstruction { + public interface BlockEndOp { } - public interface NullCheck extends LIRInstruction { + public interface NullCheck { Value getCheckedValue(); LIRFrameState getState(); } - public interface ImplicitNullCheck extends LIRInstruction { + public interface ImplicitNullCheck { boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit); } /** * LIR operation that defines the position of a label. */ - public static class LabelOp extends LIRInstructionBase { + public static final class LabelOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LabelOp.class); private static final Value[] NO_VALUES = new Value[0]; @@ -78,6 +79,7 @@ private final boolean align; public LabelOp(Label label, boolean align) { + super(TYPE); this.label = label; this.align = align; this.incomingValues = NO_VALUES; @@ -104,11 +106,17 @@ /** * LIR operation that is an unconditional jump to a {@link #destination()}. */ - public static class JumpOp extends LIRInstructionBase implements BlockEndOp { + public static class JumpOp extends LIRInstruction implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(JumpOp.class); private final LabelRef destination; public JumpOp(LabelRef destination) { + this(TYPE, destination); + } + + protected JumpOp(LIRInstructionClass c, LabelRef destination) { + super(c); this.destination = destination; } @@ -134,7 +142,7 @@ * Marker interface for a LIR operation that moves a value from {@link #getInput()} to * {@link #getResult()}. */ - public interface MoveOp extends LIRInstruction { + public interface MoveOp { Value getInput(); @@ -146,7 +154,7 @@ * {@linkplain #remove(Set) pruned} and a mapping from registers to the frame slots in which * they are saved can be {@linkplain #getMap(FrameMap) retrieved}. */ - public interface SaveRegistersOp extends LIRInstruction { + public interface SaveRegistersOp { /** * Determines if the {@link #remove(Set)} operation is supported for this object. @@ -178,19 +186,21 @@ * A LIR operation that does nothing. If the operation records its position, it can be * subsequently {@linkplain #replace(LIR, LIRInstruction) replaced}. */ - public static class NoOp extends LIRInstructionBase { + public static final class NoOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(NoOp.class); /** * The block in which this instruction is located. */ - final AbstractBlock block; + final AbstractBlockBase block; /** * The block index of this instruction. */ final int index; - public NoOp(AbstractBlock block, int index) { + public NoOp(AbstractBlockBase block, int index) { + super(TYPE); this.block = block; this.index = index; } @@ -208,11 +218,13 @@ } @Opcode("BLACKHOLE") - public static class BlackholeOp extends LIRInstructionBase { + public static final class BlackholeOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(BlackholeOp.class); @Use({REG, STACK}) private Value value; public BlackholeOp(Value value) { + super(TYPE); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,7 +31,7 @@ /** * This class encapsulates different strategies on how to generate code for switch instructions. - * + * * The {@link #getBestStrategy(double[], JavaConstant[], LabelRef[])} method can be used to get * strategy with the smallest average effort (average number of comparisons until a decision is * reached). The strategy returned by this method will have its averageEffort set, while a strategy @@ -43,7 +43,7 @@ /** * Generates a conditional or unconditional jump. The jump will be unconditional if * condition is null. If defaultTarget is true, then the jump will go the the default. - * + * * @param index Index of the value and the jump target (only used if defaultTarget == false) * @param condition The condition on which to jump (can be null) * @param defaultTarget true if the jump should go to the default target, false if index @@ -54,7 +54,7 @@ /** * Generates a conditional jump to the target with the specified index. The fall through * should go to the default target. - * + * * @param index Index of the value and the jump target * @param condition The condition on which to jump * @param canFallThrough true if this is the last instruction in the switch statement, to @@ -64,7 +64,7 @@ /** * Create a new label and generate a conditional jump to it. - * + * * @param index Index of the value and the jump target * @param condition The condition on which to jump * @return a new Label diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/IntervalWalker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/IntervalWalker.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/IntervalWalker.java Mon Mar 02 19:11:22 2015 +0100 @@ -104,63 +104,65 @@ private void walkTo(State state, int from) { assert state == State.Active || state == State.Inactive : "wrong state"; for (RegisterBinding binding : RegisterBinding.VALUES) { - Interval prevprev = null; - Interval prev = (state == State.Active) ? activeLists.get(binding) : inactiveLists.get(binding); - Interval next = prev; - while (next.currentFrom() <= from) { - Interval cur = next; - next = cur.next; + walkTo(state, from, binding); + } + } - boolean rangeHasChanged = false; - while (cur.currentTo() <= from) { - cur.nextRange(); - rangeHasChanged = true; - } + private void walkTo(State state, int from, RegisterBinding binding) { + Interval prevprev = null; + Interval prev = (state == State.Active) ? activeLists.get(binding) : inactiveLists.get(binding); + Interval next = prev; + while (next.currentFrom() <= from) { + Interval cur = next; + next = cur.next; - // also handle move from inactive list to active list - rangeHasChanged = rangeHasChanged || (state == State.Inactive && cur.currentFrom() <= from); + boolean rangeHasChanged = false; + while (cur.currentTo() <= from) { + cur.nextRange(); + rangeHasChanged = true; + } - if (rangeHasChanged) { - // remove cur from list - if (prevprev == null) { - if (state == State.Active) { - activeLists.set(binding, next); - } else { - inactiveLists.set(binding, next); - } + // also handle move from inactive list to active list + rangeHasChanged = rangeHasChanged || (state == State.Inactive && cur.currentFrom() <= from); + + if (rangeHasChanged) { + // remove cur from list + if (prevprev == null) { + if (state == State.Active) { + activeLists.set(binding, next); } else { - prevprev.next = next; + inactiveLists.set(binding, next); } - prev = next; - if (cur.currentAtEnd()) { - // move to handled state (not maintained as a list) - cur.state = State.Handled; - intervalMoved(cur, state, State.Handled); - } else if (cur.currentFrom() <= from) { + } else { + prevprev.next = next; + } + prev = next; + Interval.State newState; + if (cur.currentAtEnd()) { + // move to handled state (not maintained as a list) + newState = State.Handled; + cur.state = newState; + } else { + if (cur.currentFrom() <= from) { // sort into active list activeLists.addToListSortedByCurrentFromPositions(binding, cur); - cur.state = State.Active; - if (prev == cur) { - assert state == State.Active : "check"; - prevprev = prev; - prev = cur.next; - } - intervalMoved(cur, state, State.Active); + newState = State.Active; } else { // sort into inactive list inactiveLists.addToListSortedByCurrentFromPositions(binding, cur); - cur.state = State.Inactive; - if (prev == cur) { - assert state == State.Inactive : "check"; - prevprev = prev; - prev = cur.next; - } - intervalMoved(cur, state, State.Inactive); + newState = State.Inactive; } - } else { - prevprev = prev; - prev = cur.next; + cur.state = newState; + if (prev == cur) { + assert state == newState; + prevprev = prev; + prev = cur.next; + } } + intervalMoved(cur, state, newState); + } else { + prevprev = prev; + prev = cur.next; } } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java Mon Mar 02 19:11:22 2015 +0100 @@ -48,6 +48,7 @@ import com.oracle.graal.lir.alloc.lsra.Interval.SpillState; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; import com.oracle.graal.options.*; /** @@ -62,6 +63,7 @@ final LIRGenerationResult res; final LIR ir; final FrameMapBuilder frameMapBuilder; + final SpillMoveFactory spillMoveFactory; final RegisterAttributes[] registerAttributes; final Register[] registers; @@ -114,7 +116,7 @@ /** * List of blocks in linear-scan order. This is only correct as long as the CFG does not change. */ - final List> sortedBlocks; + final List> sortedBlocks; /** * Map from {@linkplain #operandNumber(Value) operand numbers} to intervals. @@ -145,11 +147,11 @@ LIRInstruction[] opIdToInstructionMap; /** - * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain AbstractBlock - * block} containing the instruction. Entries should be retrieved with {@link #blockForId(int)} - * as the id is not simply an index into this array. + * Map from an instruction {@linkplain LIRInstruction#id id} to the + * {@linkplain AbstractBlockBase block} containing the instruction. Entries should be retrieved + * with {@link #blockForId(int)} as the id is not simply an index into this array. */ - AbstractBlock[] opIdToBlockMap; + AbstractBlockBase[] opIdToBlockMap; /** * Bit set for each variable that is contained in each loop. @@ -161,10 +163,11 @@ */ private final int firstVariableNumber; - LinearScan(TargetDescription target, LIRGenerationResult res) { + LinearScan(TargetDescription target, LIRGenerationResult res, SpillMoveFactory spillMoveFactory) { this.target = target; this.res = res; this.ir = res.getLIR(); + this.spillMoveFactory = spillMoveFactory; this.frameMapBuilder = res.getFrameMapBuilder(); this.sortedBlocks = ir.linearScanOrder(); this.registerAttributes = frameMapBuilder.getRegisterConfig().getAttributesMap(); @@ -178,19 +181,23 @@ this.callKillsRegisters = this.frameMapBuilder.getRegisterConfig().areAllAllocatableRegistersCallerSaved(); } - int getFirstLirInstructionId(AbstractBlock block) { + int getFirstLirInstructionId(AbstractBlockBase block) { int result = ir.getLIRforBlock(block).get(0).id(); assert result >= 0; return result; } - int getLastLirInstructionId(AbstractBlock block) { + int getLastLirInstructionId(AbstractBlockBase block) { List instructions = ir.getLIRforBlock(block); int result = instructions.get(instructions.size() - 1).id(); assert result >= 0; return result; } + SpillMoveFactory getSpillMoveFactory() { + return spillMoveFactory; + } + public static boolean isVariableOrRegister(Value value) { return isVariable(value) || isRegister(value); } @@ -312,7 +319,7 @@ return sortedBlocks.size(); } - AbstractBlock blockAt(int index) { + AbstractBlockBase blockAt(int index) { return sortedBlocks.get(index); } @@ -388,7 +395,7 @@ * @param opId an instruction {@linkplain LIRInstruction#id id} * @return the block containing the instruction denoted by {@code opId} */ - AbstractBlock blockForId(int opId) { + AbstractBlockBase blockForId(int opId) { assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range"; return opIdToBlockMap[opIdToIndex(opId)]; } @@ -522,7 +529,7 @@ } LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { List instructions = ir.getLIRforBlock(block); int numInst = instructions.size(); @@ -571,7 +578,7 @@ assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + interval.spillState(); assert isStackSlotValue(toLocation) : "to operand must be a stack slot"; - insertionBuffer.append(j + 1, ir.getSpillMoveFactory().createMove(toLocation, fromLocation)); + insertionBuffer.append(j + 1, getSpillMoveFactory().createMove(toLocation, fromLocation)); Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); } @@ -627,17 +634,17 @@ // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node. int numInstructions = 0; - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { numInstructions += ir.getLIRforBlock(block).size(); } // initialize with correct length opIdToInstructionMap = new LIRInstruction[numInstructions]; - opIdToBlockMap = new AbstractBlock[numInstructions]; + opIdToBlockMap = new AbstractBlockBase[numInstructions]; int opId = 0; int index = 0; - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { blockData.put(block, new BlockData()); List instructions = ir.getLIRforBlock(block); @@ -672,7 +679,7 @@ intervalInLoop = new BitMap2D(operandSize(), numLoops()); // iterate all blocks - for (final AbstractBlock block : sortedBlocks) { + for (final AbstractBlockBase block : sortedBlocks) { try (Indent indent = Debug.logAndIndent("compute local live sets for block %d", block.getId())) { final BitSet liveGen = new BitSet(liveSize); @@ -763,7 +770,7 @@ } } - private void verifyInput(AbstractBlock block, BitSet liveKill, Value operand) { + private void verifyInput(AbstractBlockBase block, BitSet liveKill, Value operand) { // fixed intervals are never live at block boundaries, so // they need not be processed in live sets. // this is checked by these assertions to be sure about it. @@ -797,7 +804,7 @@ // iterate all blocks in reverse order for (int i = numBlocks - 1; i >= 0; i--) { - AbstractBlock block = blockAt(i); + AbstractBlockBase block = blockAt(i); BlockData blockSets = blockData.get(block); changeOccurredInBlock = false; @@ -808,7 +815,7 @@ liveOut.clear(); // block has successors if (n > 0) { - for (AbstractBlock successor : block.getSuccessors()) { + for (AbstractBlockBase successor : block.getSuccessors()) { liveOut.or(blockData.get(successor).liveIn); } } @@ -852,7 +859,7 @@ } // check that the liveIn set of the first block is empty - AbstractBlock startBlock = ir.getControlFlowGraph().getStartBlock(); + AbstractBlockBase startBlock = ir.getControlFlowGraph().getStartBlock(); if (blockData.get(startBlock).liveIn.cardinality() != 0) { if (DetailedAsserts.getValue()) { reportFailure(numBlocks); @@ -891,9 +898,9 @@ } try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) { - Deque> definedIn = new ArrayDeque<>(); - HashSet> usedIn = new HashSet<>(); - for (AbstractBlock block : sortedBlocks) { + Deque> definedIn = new ArrayDeque<>(); + HashSet> usedIn = new HashSet<>(); + for (AbstractBlockBase block : sortedBlocks) { if (blockData.get(block).liveGen.get(operandNum)) { usedIn.add(block); try (Indent indent3 = Debug.logAndIndent("used in block B%d", block.getId())) { @@ -920,9 +927,9 @@ int[] hitCount = new int[numBlocks]; while (!definedIn.isEmpty()) { - AbstractBlock block = definedIn.removeFirst(); + AbstractBlockBase block = definedIn.removeFirst(); usedIn.remove(block); - for (AbstractBlock successor : block.getSuccessors()) { + for (AbstractBlockBase successor : block.getSuccessors()) { if (successor.isLoopHeader()) { if (!block.isLoopEnd()) { definedIn.add(successor); @@ -935,7 +942,7 @@ } } try (Indent indent3 = Debug.logAndIndent("**** offending usages are in: ")) { - for (AbstractBlock block : usedIn) { + for (AbstractBlockBase block : usedIn) { Debug.log("B%d", block.getId()); } } @@ -950,7 +957,7 @@ private void verifyLiveness() { // check that fixed intervals are not live at block boundaries // (live set must be empty at fixed intervals) - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { for (int j = 0; j <= maxRegisterNumber(); j++) { assert !blockData.get(block).liveIn.get(j) : "liveIn set of fixed register must be empty"; assert !blockData.get(block).liveOut.get(j) : "liveOut set of fixed register must be empty"; @@ -1167,7 +1174,7 @@ // iterate all blocks in reverse order for (int i = blockCount() - 1; i >= 0; i--) { - AbstractBlock block = blockAt(i); + AbstractBlockBase block = blockAt(i); try (Indent indent2 = Debug.logAndIndent("handle block %d", block.getId())) { List instructions = ir.getLIRforBlock(block); @@ -1411,15 +1418,15 @@ throw new BailoutException("LinearScan: interval is null"); } - Interval intervalAtBlockBegin(AbstractBlock block, int operandNumber) { + Interval intervalAtBlockBegin(AbstractBlockBase block, int operandNumber) { return splitChildAtOpId(intervalFor(operandNumber), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF); } - Interval intervalAtBlockEnd(AbstractBlock block, int operandNumber) { + Interval intervalAtBlockEnd(AbstractBlockBase block, int operandNumber) { return splitChildAtOpId(intervalFor(operandNumber), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF); } - void resolveCollectMappings(AbstractBlock fromBlock, AbstractBlock toBlock, MoveResolver moveResolver) { + void resolveCollectMappings(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, MoveResolver moveResolver) { assert moveResolver.checkEmpty(); int numOperands = operandSize(); @@ -1440,7 +1447,7 @@ } } - void resolveFindInsertPos(AbstractBlock fromBlock, AbstractBlock toBlock, MoveResolver moveResolver) { + void resolveFindInsertPos(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, MoveResolver moveResolver) { if (fromBlock.getSuccessorCount() <= 1) { Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); @@ -1463,7 +1470,7 @@ // successor edges, blocks which are reached by switch statements // may have be more than one predecessor but it will be guaranteed // that all predecessors will be the same. - for (AbstractBlock predecessor : toBlock.getPredecessors()) { + for (AbstractBlockBase predecessor : toBlock.getPredecessors()) { assert fromBlock == predecessor : "all critical edges must be broken"; } } @@ -1484,7 +1491,7 @@ BitSet blockCompleted = new BitSet(numBlocks); BitSet alreadyResolved = new BitSet(numBlocks); - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { // check if block has only one predecessor and only one successor if (block.getPredecessorCount() == 1 && block.getSuccessorCount() == 1) { @@ -1494,8 +1501,8 @@ // check if block is empty (only label and branch) if (instructions.size() == 2) { - AbstractBlock pred = block.getPredecessors().iterator().next(); - AbstractBlock sux = block.getSuccessors().iterator().next(); + AbstractBlockBase pred = block.getPredecessors().iterator().next(); + AbstractBlockBase sux = block.getSuccessors().iterator().next(); // prevent optimization of two consecutive blocks if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) { @@ -1516,12 +1523,12 @@ } } - for (AbstractBlock fromBlock : sortedBlocks) { + for (AbstractBlockBase fromBlock : sortedBlocks) { if (!blockCompleted.get(fromBlock.getLinearScanNumber())) { alreadyResolved.clear(); alreadyResolved.or(blockCompleted); - for (AbstractBlock toBlock : fromBlock.getSuccessors()) { + for (AbstractBlockBase toBlock : fromBlock.getSuccessors()) { // check for duplicate edges between the same blocks (can happen with switch // blocks) @@ -1566,7 +1573,7 @@ if (opId != -1) { if (DetailedAsserts.getValue()) { - AbstractBlock block = blockForId(opId); + AbstractBlockBase block = blockForId(opId); if (block.getSuccessorCount() <= 1 && opId == getLastLirInstructionId(block)) { // check if spill moves could have been appended at the end of this block, but // before the branch instruction. So the split child information for this branch @@ -1639,7 +1646,7 @@ } int tempOpId = op.id(); OperandMode mode = OperandMode.USE; - AbstractBlock block = blockForId(tempOpId); + AbstractBlockBase 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 @@ -1723,7 +1730,7 @@ private void assignLocations() { try (Indent indent = Debug.logAndIndent("assign locations")) { - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { try (Indent indent2 = Debug.logAndIndent("assign locations in block B%d", block.getId())) { assignLocations(ir.getLIRforBlock(block)); } @@ -1811,8 +1818,8 @@ LIRInsertionBuffer[] insertionBuffers = new LIRInsertionBuffer[ir.linearScanOrder().size()]; for (Interval interval : intervals) { if (interval != null && interval.isSplitParent() && interval.spillState() == SpillState.SpillInDominator) { - AbstractBlock defBlock = blockForId(interval.spillDefinitionPos()); - AbstractBlock spillBlock = null; + AbstractBlockBase defBlock = blockForId(interval.spillDefinitionPos()); + AbstractBlockBase spillBlock = null; Interval firstSpillChild = null; try (Indent indent = Debug.logAndIndent("interval %s (%s)", interval, defBlock)) { for (Interval splitChild : interval.getSplitChildren()) { @@ -1823,7 +1830,7 @@ assert firstSpillChild.from() < splitChild.from(); } // iterate all blocks where the interval has use positions - for (AbstractBlock splitBlock : blocksForInterval(splitChild)) { + for (AbstractBlockBase splitBlock : blocksForInterval(splitChild)) { if (dominates(defBlock, splitBlock)) { Debug.log("Split interval %s, block %s", splitChild, splitBlock); if (spillBlock == null) { @@ -1851,7 +1858,7 @@ */ assert firstSpillChild != null; if (!defBlock.equals(spillBlock) && spillBlock.equals(blockForId(firstSpillChild.from()))) { - AbstractBlock dom = spillBlock.getDominator(); + AbstractBlockBase dom = spillBlock.getDominator(); Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); spillBlock = dom; } @@ -1875,7 +1882,7 @@ // insert spill move AllocatableValue fromLocation = interval.getSplitChildAtOpId(spillOpId, OperandMode.DEF, this).location(); AllocatableValue toLocation = canonicalSpillOpr(interval); - LIRInstruction move = ir.getSpillMoveFactory().createMove(toLocation, fromLocation); + LIRInstruction move = getSpillMoveFactory().createMove(toLocation, fromLocation); move.setId(DOMINATOR_SPILL_MOVE_ID); /* * We can use the insertion buffer directly because we always insert @@ -1903,20 +1910,20 @@ } /** - * Iterate over all {@link AbstractBlock blocks} of an interval. + * Iterate over all {@link AbstractBlockBase blocks} of an interval. */ - private class IntervalBlockIterator implements Iterator> { + private class IntervalBlockIterator implements Iterator> { Range range; - AbstractBlock block; + AbstractBlockBase block; public IntervalBlockIterator(Interval interval) { range = interval.first(); block = blockForId(range.from); } - public AbstractBlock next() { - AbstractBlock currentBlock = block; + public AbstractBlockBase next() { + AbstractBlockBase currentBlock = block; int nextBlockIndex = block.getLinearScanNumber() + 1; if (nextBlockIndex < sortedBlocks.size()) { block = sortedBlocks.get(nextBlockIndex); @@ -1939,17 +1946,17 @@ } } - private Iterable> blocksForInterval(Interval interval) { - return new Iterable>() { - public Iterator> iterator() { + private Iterable> blocksForInterval(Interval interval) { + return new Iterable>() { + public Iterator> iterator() { return new IntervalBlockIterator(interval); } }; } - private static AbstractBlock moveSpillOutOfLoop(AbstractBlock defBlock, AbstractBlock spillBlock) { + private static AbstractBlockBase moveSpillOutOfLoop(AbstractBlockBase defBlock, AbstractBlockBase spillBlock) { int defLoopDepth = defBlock.getLoopDepth(); - for (AbstractBlock block = spillBlock.getDominator(); !defBlock.equals(block); block = block.getDominator()) { + for (AbstractBlockBase block = spillBlock.getDominator(); !defBlock.equals(block); block = block.getDominator()) { assert block != null : "spill block not dominated by definition block?"; if (block.getLoopDepth() <= defLoopDepth) { assert block.getLoopDepth() == defLoopDepth : "Cannot spill an interval outside of the loop where it is defined!"; @@ -1970,7 +1977,7 @@ try (Indent indent2 = Debug.logAndIndent("Basic Blocks")) { for (int i = 0; i < blockCount(); i++) { - AbstractBlock block = blockAt(i); + AbstractBlockBase block = blockAt(i); Debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); } } @@ -2103,7 +2110,7 @@ otherIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1); IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals); - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { List instructions = ir.getLIRforBlock(block); for (int j = 0; j < instructions.size(); j++) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,13 +27,14 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; import com.oracle.graal.lir.phases.*; -public final class LinearScanPhase extends LIRMidTierPhase { +public final class LinearScanPhase extends AllocationPhase { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { - new LinearScan(target, lirGenRes).allocate(); + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + new LinearScan(target, lirGenRes, spillMoveFactory).allocate(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java Mon Mar 02 19:11:22 2015 +0100 @@ -63,11 +63,11 @@ return allocator.blockCount(); } - AbstractBlock blockAt(int idx) { + AbstractBlockBase blockAt(int idx) { return allocator.blockAt(idx); } - AbstractBlock blockOfOpWithId(int opId) { + AbstractBlockBase blockOfOpWithId(int opId) { return allocator.blockForId(opId); } @@ -239,7 +239,7 @@ // optimized away later in assignRegNums int opId = (operandId + 1) & ~1; - AbstractBlock opBlock = allocator.blockForId(opId); + AbstractBlockBase opBlock = allocator.blockForId(opId); assert opId > 0 && allocator.blockForId(opId - 2) == opBlock : "cannot insert move at block boundary"; // calculate index of instruction inside instruction list of current block @@ -263,7 +263,7 @@ moveResolver.addMapping(srcIt, dstIt); } - int findOptimalSplitPos(AbstractBlock minBlock, AbstractBlock maxBlock, int maxSplitPos) { + int findOptimalSplitPos(AbstractBlockBase minBlock, AbstractBlockBase maxBlock, int maxSplitPos) { int fromBlockNr = minBlock.getLinearScanNumber(); int toBlockNr = maxBlock.getLinearScanNumber(); @@ -280,7 +280,7 @@ int minLoopDepth = maxBlock.getLoopDepth(); for (int i = toBlockNr - 1; i >= fromBlockNr; i--) { - AbstractBlock cur = blockAt(i); + AbstractBlockBase cur = blockAt(i); if (cur.getLoopDepth() < minLoopDepth) { // block with lower loop-depth found . split at the end of this block @@ -308,13 +308,13 @@ // beginning of a block, then minSplitPos is also a possible split position. // Use the block before as minBlock, because then minBlock.lastLirInstructionId() + 2 == // minSplitPos - AbstractBlock minBlock = allocator.blockForId(minSplitPos - 1); + AbstractBlockBase minBlock = allocator.blockForId(minSplitPos - 1); // reason for using maxSplitPos - 1: otherwise there would be an assert on failure // when an interval ends at the end of the last block of the method // (in this case, maxSplitPos == allocator().maxLirOpId() + 2, and there is no // block at this opId) - AbstractBlock maxBlock = allocator.blockForId(maxSplitPos - 1); + AbstractBlockBase maxBlock = allocator.blockForId(maxSplitPos - 1); assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; if (minBlock == maxBlock) { @@ -352,7 +352,7 @@ // Desired result: uses tagged as shouldHaveRegister inside a loop cause // a reloading // of the interval (normally, only mustHaveRegister causes a reloading) - AbstractBlock loopBlock = allocator.blockForId(loopEndPos); + AbstractBlockBase loopBlock = allocator.blockForId(loopEndPos); Debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between"; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,6 +35,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; import com.oracle.graal.lir.phases.*; import com.oracle.graal.options.*; @@ -42,7 +43,7 @@ * Mark all live references for a frame state. The frame state use this information to build the OOP * maps. */ -public final class LocationMarker extends LIRMidTierPhase { +public final class LocationMarker extends AllocationPhase { public static class Options { // @formatter:off @@ -52,7 +53,7 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build(); } @@ -72,19 +73,19 @@ } private void build() { - Deque> worklist = new ArrayDeque<>(); + Deque> worklist = new ArrayDeque<>(); for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) { worklist.add(lir.getControlFlowGraph().getBlocks().get(i)); } - for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { liveInMap.put(block, frameMap.initReferenceMap(true)); } while (!worklist.isEmpty()) { - AbstractBlock block = worklist.poll(); + AbstractBlockBase block = worklist.poll(); processBlock(block, worklist); } // finish states - for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { List instructions = lir.getLIRforBlock(block); for (int i = instructions.size() - 1; i >= 0; i--) { LIRInstruction inst = instructions.get(i); @@ -97,7 +98,7 @@ /** * Merge outSet with in-set of successors. */ - private boolean updateOutBlock(AbstractBlock block) { + private boolean updateOutBlock(AbstractBlockBase block) { ReferenceMap union = frameMap.initReferenceMap(true); block.getSuccessors().forEach(succ -> union.updateUnion(liveInMap.get(succ))); ReferenceMap outSet = liveOutMap.get(block); @@ -109,7 +110,7 @@ return false; } - private void processBlock(AbstractBlock block, Deque> worklist) { + private void processBlock(AbstractBlockBase block, Deque> worklist) { if (updateOutBlock(block)) { try (Indent indent = Debug.logAndIndent("handle block %s", block)) { BlockClosure closure = new BlockClosure(liveOutMap.get(block).clone()); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/MoveResolver.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/MoveResolver.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/MoveResolver.java Mon Mar 02 19:11:22 2015 +0100 @@ -203,7 +203,7 @@ AllocatableValue fromOpr = fromInterval.operand; AllocatableValue toOpr = toInterval.operand; - insertionBuffer.append(insertIdx, allocator.ir.getSpillMoveFactory().createMove(toOpr, fromOpr)); + insertionBuffer.append(insertIdx, allocator.getSpillMoveFactory().createMove(toOpr, fromOpr)); Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); } @@ -213,7 +213,7 @@ assert insertIdx != -1 : "must setup insert position first"; AllocatableValue toOpr = toInterval.operand; - insertionBuffer.append(insertIdx, allocator.ir.getSpillMoveFactory().createMove(toOpr, fromOpr)); + insertionBuffer.append(insertIdx, allocator.getSpillMoveFactory().createMove(toOpr, fromOpr)); Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/OptimizingLinearScanWalker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/OptimizingLinearScanWalker.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/OptimizingLinearScanWalker.java Mon Mar 02 19:11:22 2015 +0100 @@ -71,14 +71,14 @@ @Override void walk() { try (Scope s = Debug.scope("OptimizingLinearScanWalker")) { - for (AbstractBlock block : allocator.sortedBlocks) { + for (AbstractBlockBase block : allocator.sortedBlocks) { optimizeBlock(block); } } super.walk(); } - private void optimizeBlock(AbstractBlock block) { + private void optimizeBlock(AbstractBlockBase block) { if (block.getPredecessorCount() == 1) { int nextBlock = allocator.getFirstLirInstructionId(block); try (Scope s1 = Debug.scope("LSRAOptimization")) { @@ -114,7 +114,7 @@ } } - private boolean optimize(int currentPos, AbstractBlock currentBlock, Interval currentInterval, RegisterBinding binding) { + private boolean optimize(int currentPos, AbstractBlockBase currentBlock, Interval currentInterval, RegisterBinding binding) { // BEGIN initialize and sanity checks assert currentBlock != null : "block must not be null"; assert currentInterval != null : "interval must not be null"; @@ -136,7 +136,7 @@ assert currentLocation != null : "active intervals must have a location assigned!"; // get predecessor stuff - AbstractBlock predecessorBlock = currentBlock.getPredecessors().get(0); + AbstractBlockBase predecessorBlock = currentBlock.getPredecessors().get(0); int predEndId = allocator.getLastLirInstructionId(predecessorBlock); Interval predecessorInterval = currentInterval.getIntervalCoveringOpId(predEndId); assert predecessorInterval != null : "variable not live at the end of the only predecessor! " + predecessorBlock + " -> " + currentBlock + " interval: " + currentInterval; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/Range.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/Range.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/Range.java Mon Mar 02 19:11:22 2015 +0100 @@ -50,7 +50,7 @@ /** * Creates a new range. - * + * * @param from the start of the range, inclusive * @param to the end of the range, exclusive * @param next link to the next range in a linked list diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/RegisterVerifier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/RegisterVerifier.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/RegisterVerifier.java Mon Mar 02 19:11:22 2015 +0100 @@ -41,7 +41,7 @@ final class RegisterVerifier { LinearScan allocator; - List> workList; // all blocks that must be processed + List> workList; // all blocks that must be processed ArrayMap savedStates; // saved information of previous check // simplified access to methods of LinearScan @@ -55,15 +55,15 @@ } // accessors - Interval[] stateForBlock(AbstractBlock block) { + Interval[] stateForBlock(AbstractBlockBase block) { return savedStates.get(block.getId()); } - void setStateForBlock(AbstractBlock block, Interval[] savedState) { + void setStateForBlock(AbstractBlockBase block, Interval[] savedState) { savedStates.put(block.getId(), savedState); } - void addToWorkList(AbstractBlock block) { + void addToWorkList(AbstractBlockBase block) { if (!workList.contains(block)) { workList.add(block); } @@ -76,7 +76,7 @@ } - void verify(AbstractBlock start) { + void verify(AbstractBlockBase start) { // setup input registers (method arguments) for first block Interval[] inputState = new Interval[stateSize()]; setStateForBlock(start, inputState); @@ -84,14 +84,14 @@ // main loop for verification do { - AbstractBlock block = workList.get(0); + AbstractBlockBase block = workList.get(0); workList.remove(0); processBlock(block); } while (!workList.isEmpty()); } - private void processBlock(AbstractBlock block) { + private void processBlock(AbstractBlockBase block) { try (Indent indent = Debug.logAndIndent("processBlock B%d", block.getId())) { // must copy state because it is modified Interval[] inputState = copy(stateForBlock(block)); @@ -110,13 +110,13 @@ processOperations(allocator.ir.getLIRforBlock(block), inputState); // iterate all successors - for (AbstractBlock succ : block.getSuccessors()) { + for (AbstractBlockBase succ : block.getSuccessors()) { processSuccessor(succ, inputState); } } } - private void processSuccessor(AbstractBlock block, Interval[] inputState) { + private void processSuccessor(AbstractBlockBase block, Interval[] inputState) { Interval[] savedState = stateForBlock(block); if (savedState != null) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Mon Mar 02 19:11:22 2015 +0100 @@ -330,7 +330,7 @@ */ public boolean isSuccessorEdge(LabelRef edge) { assert lir != null; - List> order = lir.codeEmittingOrder(); + List> order = lir.codeEmittingOrder(); assert order.get(currentBlockIndex) == edge.getSourceBlock(); return currentBlockIndex < order.size() - 1 && order.get(currentBlockIndex + 1) == edge.getTargetBlock(); } @@ -344,7 +344,7 @@ this.lir = lir; this.currentBlockIndex = 0; frameContext.enter(this); - for (AbstractBlock b : lir.codeEmittingOrder()) { + for (AbstractBlockBase b : lir.codeEmittingOrder()) { emitBlock(b); currentBlockIndex++; } @@ -352,7 +352,7 @@ this.currentBlockIndex = 0; } - private void emitBlock(AbstractBlock block) { + private void emitBlock(AbstractBlockBase block) { if (Debug.isDumpEnabled()) { blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRValueUtil.*; +import static com.oracle.graal.lir.phases.LIRPhase.Options.*; import java.util.*; @@ -47,17 +48,17 @@ * a constant, which is potentially scheduled into a block with high probability, with one or more * definitions in blocks with a lower probability. */ -public final class ConstantLoadOptimization extends LIRHighTierPhase { +public final class ConstantLoadOptimization extends PreAllocationOptimizationPhase { public static class Options { // @formatter:off @Option(help = "Enable constant load optimization.", type = OptionType.Debug) - public static final OptionValue LIROptConstantLoadOptimization = new OptionValue<>(true); + public static final NestedBooleanOptionValue LIROptConstantLoadOptimization = new NestedBooleanOptionValue(LIROptimization, true); // @formatter:on } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRGeneratorTool lirGen) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRGeneratorTool lirGen) { new Optimization(lirGenRes.getLIR(), lirGen).apply(); } @@ -135,7 +136,7 @@ assert !operand.equals(var) : "constant usage through variable in frame state " + var; } }; - for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { for (LIRInstruction inst : lir.getLIRforBlock(block)) { // set instruction id to the index in the lir instruction list inst.visitEachState(stateConsumer); @@ -152,7 +153,7 @@ } private void addUsageToBlockMap(UseEntry entry) { - AbstractBlock block = entry.getBlock(); + AbstractBlockBase block = entry.getBlock(); List list = blockMap.get(block); if (list == null) { list = new ArrayList<>(); @@ -164,7 +165,7 @@ /** * Collects def-use information for a {@code block}. */ - private void analyzeBlock(AbstractBlock block) { + private void analyzeBlock(AbstractBlockBase block) { try (Indent indent = Debug.logAndIndent("Block: %s", block)) { InstructionValueConsumer loadConsumer = (instruction, value, mode, flags) -> { @@ -195,14 +196,13 @@ } }; - ValuePositionProcedure useProcedure = (instruction, position) -> { - Value value = position.get(instruction); + InstructionValueConsumer useConsumer = (instruction, value, mode, flags) -> { if (isVariable(value)) { Variable var = (Variable) value; if (!phiConstants.get(var.index)) { DefUseTree tree = map.get(var); if (tree != null) { - tree.addUsage(block, instruction, position); + tree.addUsage(block, instruction, value); Debug.log("usage of %s : %s", var, instruction); } } @@ -214,8 +214,8 @@ // set instruction id to the index in the lir instruction list inst.setId(opId++); inst.visitEachOutput(loadConsumer); - inst.forEachInputPos(useProcedure); - inst.forEachAlivePos(useProcedure); + inst.forEachInput(useConsumer); + inst.forEachAlive(useConsumer); } } @@ -267,17 +267,17 @@ Debug.dump(constTree, "ConstantTree for " + tree.getVariable()); } - private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlock startBlock) { - Deque> worklist = new ArrayDeque<>(); + private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlockBase startBlock) { + Deque> worklist = new ArrayDeque<>(); worklist.add(startBlock); while (!worklist.isEmpty()) { - AbstractBlock block = worklist.pollLast(); + AbstractBlockBase block = worklist.pollLast(); if (constTree.get(Flags.CANDIDATE, block)) { constTree.set(Flags.MATERIALIZE, block); // create and insert load insertLoad(tree.getConstant(), tree.getVariable().getLIRKind(), block, constTree.getCost(block).getUsages()); } else { - for (AbstractBlock dominated : block.getDominated()) { + for (AbstractBlockBase dominated : block.getDominated()) { if (constTree.isMarked(dominated)) { worklist.addLast(dominated); } @@ -286,18 +286,18 @@ } } - private void insertLoad(JavaConstant constant, LIRKind kind, AbstractBlock block, List usages) { + private void insertLoad(JavaConstant constant, LIRKind kind, AbstractBlockBase block, List usages) { assert usages != null && usages.size() > 0 : String.format("No usages %s %s %s", constant, block, usages); // create variable Variable variable = lirGen.newVariable(kind); // create move - LIRInstruction move = lir.getSpillMoveFactory().createMove(variable, constant); + LIRInstruction move = lirGen.getSpillMoveFactory().createMove(variable, constant); // insert instruction getInsertionBuffer(block).append(1, move); Debug.log("new move (%s) and inserted in block %s", move, block); // update usages for (UseEntry u : usages) { - u.getPosition().set(u.getInstruction(), variable); + u.setValue(variable); Debug.log("patched instruction %s", u.getInstruction()); } } @@ -306,7 +306,7 @@ * Inserts the constant loads created in {@link #createConstantTree} and deletes the * original definition. */ - private void rewriteBlock(AbstractBlock block) { + private void rewriteBlock(AbstractBlockBase block) { // insert moves LIRInsertionBuffer buffer = insertionBuffers.get(block); if (buffer != null) { @@ -331,13 +331,13 @@ } private void deleteInstruction(DefUseTree tree) { - AbstractBlock block = tree.getBlock(); + AbstractBlockBase block = tree.getBlock(); LIRInstruction instruction = tree.getInstruction(); Debug.log("deleting instruction %s from block %s", instruction, block); lir.getLIRforBlock(block).set(instruction.id(), null); } - private LIRInsertionBuffer getInsertionBuffer(AbstractBlock block) { + private LIRInsertionBuffer getInsertionBuffer(AbstractBlockBase block) { LIRInsertionBuffer insertionBuffer = insertionBuffers.get(block); if (insertionBuffer == null) { insertionBuffer = new LIRInsertionBuffer(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java Mon Mar 02 19:11:22 2015 +0100 @@ -99,7 +99,7 @@ tree.forEach(u -> getOrInitList(u.getBlock()).add(u)); } - private List getOrInitList(AbstractBlock block) { + private List getOrInitList(AbstractBlockBase block) { List list = blockMap.get(block); if (list == null) { list = new ArrayList<>(); @@ -108,7 +108,7 @@ return list; } - public List getUsages(AbstractBlock block) { + public List getUsages(AbstractBlockBase block) { List list = blockMap.get(block); if (list == null) { return Collections.emptyList(); @@ -120,7 +120,7 @@ * Returns the cost object associated with {@code block}. If there is none, a new cost object is * created. */ - NodeCost getOrInitCost(AbstractBlock block) { + NodeCost getOrInitCost(AbstractBlockBase block) { NodeCost cost = getCost(block); if (cost == null) { cost = new NodeCost(block.probability(), blockMap.get(block), 1); @@ -145,7 +145,7 @@ } @Override - public void forEachPropertyPair(AbstractBlock block, BiConsumer action) { + public void forEachPropertyPair(AbstractBlockBase block, BiConsumer action) { if (get(Flags.SUBTREE, block) && (block.getDominator() == null || !get(Flags.SUBTREE, block.getDominator()))) { action.accept("hasDefinition", "true"); } @@ -156,7 +156,7 @@ return stream(Flags.SUBTREE).count(); } - public AbstractBlock getStartBlock() { + public AbstractBlockBase getStartBlock() { return stream(Flags.SUBTREE).findFirst().get(); } @@ -164,15 +164,15 @@ stream(Flags.USAGE).forEach(block -> setDominatorPath(Flags.SUBTREE, block)); } - public boolean isMarked(AbstractBlock block) { + public boolean isMarked(AbstractBlockBase block) { return get(Flags.SUBTREE, block); } - public boolean isLeafBlock(AbstractBlock block) { + public boolean isLeafBlock(AbstractBlockBase block) { return block.getDominated().stream().noneMatch(this::isMarked); } - public void setSolution(AbstractBlock block) { + public void setSolution(AbstractBlockBase block) { set(Flags.MATERIALIZE, block); } @@ -180,7 +180,7 @@ return getBlocks().size(); } - public void traverseTreeWhileTrue(AbstractBlock block, Predicate> action) { + public void traverseTreeWhileTrue(AbstractBlockBase block, Predicate> action) { assert block != null : "block must not be null!"; if (action.test(block)) { block.getDominated().stream().filter(this::isMarked).forEach(dominated -> traverseTreeWhileTrue(dominated, action)); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTreeAnalyzer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTreeAnalyzer.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTreeAnalyzer.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,7 +37,7 @@ private final ConstantTree tree; private final BitSet visited; - public static NodeCost analyze(ConstantTree tree, AbstractBlock startBlock) { + public static NodeCost analyze(ConstantTree tree, AbstractBlockBase startBlock) { try (Scope s = Debug.scope("ConstantTreeAnalyzer")) { ConstantTreeAnalyzer analyzer = new ConstantTreeAnalyzer(tree); analyzer.analyzeBlocks(startBlock); @@ -60,11 +60,11 @@ * * @param startBlock The start block of the dominator subtree. */ - private void analyzeBlocks(AbstractBlock startBlock) { - Deque> worklist = new ArrayDeque<>(); + private void analyzeBlocks(AbstractBlockBase startBlock) { + Deque> worklist = new ArrayDeque<>(); worklist.offerLast(startBlock); while (!worklist.isEmpty()) { - AbstractBlock block = worklist.pollLast(); + AbstractBlockBase block = worklist.pollLast(); try (Indent i = Debug.logAndIndent(3, "analyze: %s", block)) { assert block != null : "worklist is empty!"; assert isMarked(block) : "Block not part of the dominator tree: " + block; @@ -79,7 +79,7 @@ // if not yet visited (and not a leaf block) process all children first! Debug.log(3, "not marked"); worklist.offerLast(block); - List> children = block.getDominated(); + List> children = block.getDominated(); children.forEach(child -> filteredPush(worklist, child)); visited.set(block.getId()); } else { @@ -97,15 +97,15 @@ * * @param block The block to be processed. */ - private void process(AbstractBlock block) { + private void process(AbstractBlockBase block) { List usages = new ArrayList<>(); double bestCost = 0; int numMat = 0; - List> children = block.getDominated(); + List> children = block.getDominated(); assert children.stream().anyMatch(this::isMarked) : "no children? should have called leafCost(): " + block; // collect children costs - for (AbstractBlock child : children) { + for (AbstractBlockBase child : children) { if (isMarked(child)) { NodeCost childCost = tree.getCost(child); assert childCost != null : "Child with null cost? block: " + child; @@ -151,23 +151,23 @@ return probabilityBlock * Math.pow(0.9, numMat - 1) < probabilityChildren; } - private void filteredPush(Deque> worklist, AbstractBlock block) { + private void filteredPush(Deque> worklist, AbstractBlockBase block) { if (isMarked(block)) { Debug.log(3, "adding %s to the worklist", block); worklist.offerLast(block); } } - private void leafCost(AbstractBlock block) { + private void leafCost(AbstractBlockBase block) { tree.set(Flags.CANDIDATE, block); tree.getOrInitCost(block); } - private boolean isMarked(AbstractBlock block) { + private boolean isMarked(AbstractBlockBase block) { return tree.isMarked(block); } - private boolean isLeafBlock(AbstractBlock block) { + private boolean isLeafBlock(AbstractBlockBase block) { return tree.isLeafBlock(block); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,10 +35,10 @@ */ class DefUseTree { private final LIRInstruction instruction; - private final AbstractBlock block; + private final AbstractBlockBase block; private final List uses; - public DefUseTree(LIRInstruction instruction, AbstractBlock block) { + public DefUseTree(LIRInstruction instruction, AbstractBlockBase block) { assert instruction instanceof MoveOp : "Not a MoveOp: " + instruction; this.instruction = instruction; this.block = block; @@ -57,7 +57,7 @@ return instruction; } - public AbstractBlock getBlock() { + public AbstractBlockBase getBlock() { return block; } @@ -66,8 +66,8 @@ return "DefUseTree [" + instruction + "|" + block + "," + uses + "]"; } - public void addUsage(AbstractBlock b, LIRInstruction inst, ValuePosition position) { - uses.add(new UseEntry(b, inst, position)); + public void addUsage(AbstractBlockBase b, LIRInstruction inst, Value value) { + uses.add(new UseEntry(b, inst, value)); } public int usageCount() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,34 +31,44 @@ */ class UseEntry { - private final AbstractBlock block; + private final AbstractBlockBase block; private final LIRInstruction instruction; - private final ValuePosition position; + private final Value value; - public UseEntry(AbstractBlock block, LIRInstruction instruction, ValuePosition position) { + public UseEntry(AbstractBlockBase block, LIRInstruction instruction, Value value) { this.block = block; this.instruction = instruction; - this.position = position; + this.value = value; } public LIRInstruction getInstruction() { return instruction; } - public AbstractBlock getBlock() { + public AbstractBlockBase getBlock() { return block; } - public ValuePosition getPosition() { - return position; + public void setValue(Value newValue) { + replaceValue(instruction, value, newValue); + } + + private static void replaceValue(LIRInstruction op, Value oldValue, Value newValue) { + ValueProcedure proc = (value, mode, flags) -> value.identityEquals(oldValue) ? newValue : value; + op.forEachAlive(proc); + op.forEachInput(proc); + op.forEachOutput(proc); + op.forEachTemp(proc); + op.forEachState(proc); } public Value getValue() { - return position.get(instruction); + return value; } @Override public String toString() { return "Use[" + getValue() + ":" + instruction + ":" + block + "]"; } + } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMapBuilderImpl.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMapBuilderImpl.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMapBuilderImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -117,7 +117,7 @@ InstructionValueConsumer verifySlots = (LIRInstruction op, Value value, OperandMode mode, EnumSet flags) -> { assert !isVirtualStackSlot(value) : String.format("Instruction %s contains a virtual stack slot %s", op, value); }; - for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { lir.getLIRforBlock(block).forEach(op -> { op.visitEachInput(verifySlots); op.visitEachAlive(verifySlots); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Mon Mar 02 19:11:22 2015 +0100 @@ -60,7 +60,7 @@ private final CodeGenProviders providers; private final CallingConvention cc; - private AbstractBlock currentBlock; + private AbstractBlockBase currentBlock; private LIRGenerationResult res; @@ -186,7 +186,7 @@ res.getLIR().getLIRforBlock(currentBlock).add(op); } - public boolean hasBlockEnd(AbstractBlock block) { + public boolean hasBlockEnd(AbstractBlockBase block) { List ops = getResult().getLIR().getLIRforBlock(block); if (ops.size() == 0) { return false; @@ -194,7 +194,7 @@ return ops.get(ops.size() - 1) instanceof BlockEndOp; } - public final void doBlockStart(AbstractBlock block) { + public final void doBlockStart(AbstractBlockBase block) { if (Options.PrintIRWithLIR.getValue()) { TTY.print(block.toString()); } @@ -212,7 +212,7 @@ } } - public final void doBlockEnd(AbstractBlock block) { + public final void doBlockEnd(AbstractBlockBase block) { if (Options.TraceLIRGeneratorLevel.getValue() >= 1) { TTY.println("END Generating LIR for block B" + block.getId()); @@ -226,7 +226,7 @@ } public void emitIncomingValues(Value[] params) { - ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params); + ((LabelOp) res.getLIR().getLIRforBlock(getCurrentBlock()).get(0)).setIncomingValues(params); } public abstract void emitJump(LabelRef label); @@ -379,14 +379,10 @@ } } - public AbstractBlock getCurrentBlock() { + public AbstractBlockBase getCurrentBlock() { return currentBlock; } - void setCurrentBlock(AbstractBlock block) { - currentBlock = block; - } - public LIRGenerationResult getResult() { return res; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,6 +32,11 @@ public interface LIRGeneratorTool extends ArithmeticLIRGenerator { + public interface SpillMoveFactory { + + LIRInstruction createMove(AllocatableValue result, Value input); + } + CodeGenProviders getProviders(); TargetDescription target(); @@ -42,15 +47,17 @@ ForeignCallsProvider getForeignCalls(); - AbstractBlock getCurrentBlock(); + AbstractBlockBase getCurrentBlock(); LIRGenerationResult getResult(); - boolean hasBlockEnd(AbstractBlock block); + boolean hasBlockEnd(AbstractBlockBase block); + + SpillMoveFactory getSpillMoveFactory(); - void doBlockStart(AbstractBlock block); + void doBlockStart(AbstractBlockBase block); - void doBlockEnd(AbstractBlock block); + void doBlockEnd(AbstractBlockBase block); Value emitLoadConstant(LIRKind kind, Constant constant); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.lir.phases; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.*; + +public abstract class AllocationPhase extends LIRPhase { + + public static final class AllocationContext { + private final SpillMoveFactory spillMoveFactory; + + public AllocationContext(SpillMoveFactory spillMoveFactory) { + this.spillMoveFactory = spillMoveFactory; + } + } + + @Override + protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, AllocationContext context) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.spillMoveFactory); + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + SpillMoveFactory spillMoveFactory); + +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationStage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationStage.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.lir.phases; + +import com.oracle.graal.lir.alloc.lsra.*; +import com.oracle.graal.lir.phases.AllocationPhase.*; +import com.oracle.graal.lir.stackslotalloc.*; + +public class AllocationStage extends LIRPhaseSuite { + public AllocationStage() { + appendPhase(new LinearScanPhase()); + + // build frame map + if (LSStackSlotAllocator.Options.LIROptLSStackSlotAllocator.getValue()) { + appendPhase(new LSStackSlotAllocator()); + } else { + appendPhase(new SimpleStackSlotAllocator()); + } + // currently we mark locations only if we do register allocation + appendPhase(new LocationMarker()); + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTier.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * 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.lir.phases; - -import com.oracle.graal.lir.constopt.*; -import com.oracle.graal.lir.phases.LIRHighTierPhase.*; - -public class LIRHighTier extends LIRPhaseSuite { - public LIRHighTier() { - if (ConstantLoadOptimization.Options.LIROptConstantLoadOptimization.getValue()) { - appendPhase(new ConstantLoadOptimization()); - } - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTierPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTierPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * 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.lir.phases; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.gen.*; - -public abstract class LIRHighTierPhase extends LIRPhase { - - public static final class LIRHighTierContext { - private final LIRGeneratorTool lirGen; - - public LIRHighTierContext(LIRGeneratorTool lirGen) { - this.lirGen = lirGen; - } - - } - - @Override - protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRHighTierContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.lirGen); - } - - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRGeneratorTool lirGen); - -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTier.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * 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.lir.phases; - -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.phases.LIRLowTierPhase.*; -import com.oracle.graal.options.*; - -public class LIRLowTier extends LIRPhaseSuite { - public static class Options { - // @formatter:off - @Option(help = "", type = OptionType.Debug) - public static final OptionValue LIROptEdgeMoveOptimizer = new OptionValue<>(true); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue LIROptControlFlowOptmizer = new OptionValue<>(true); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue LIROptRedundantMoveElimination = new OptionValue<>(true); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue LIROptNullCheckOptimizer = new OptionValue<>(true); - // @formatter:on - } - - public LIRLowTier() { - if (Options.LIROptEdgeMoveOptimizer.getValue()) { - appendPhase(new EdgeMoveOptimizer()); - } - if (Options.LIROptControlFlowOptmizer.getValue()) { - appendPhase(new ControlFlowOptimizer()); - } - if (Options.LIROptRedundantMoveElimination.getValue()) { - appendPhase(new RedundantMoveElimination()); - } - if (Options.LIROptNullCheckOptimizer.getValue()) { - appendPhase(new NullCheckOptimizer()); - } - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTierPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTierPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * 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.lir.phases; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.gen.*; - -public abstract class LIRLowTierPhase extends LIRPhase { - - public static final class LIRLowTierContext { - } - - @Override - protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRLowTierContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder); - } - - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); - -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTier.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * 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.lir.phases; - -import com.oracle.graal.lir.alloc.lsra.*; -import com.oracle.graal.lir.phases.LIRMidTierPhase.*; -import com.oracle.graal.lir.stackslotalloc.*; - -public class LIRMidTier extends LIRPhaseSuite { - public LIRMidTier() { - appendPhase(new LinearScanPhase()); - - // build frame map - if (LSStackSlotAllocator.Options.LIROptLSStackSlotAllocator.getValue()) { - appendPhase(new LSStackSlotAllocator()); - } else { - appendPhase(new SimpleStackSlotAllocator()); - } - // currently we mark locations only if we do register allocation - appendPhase(new LocationMarker()); - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTierPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTierPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * 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.lir.phases; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.gen.*; - -public abstract class LIRMidTierPhase extends LIRPhase { - - public static final class LIRMidTierContext { - } - - @Override - protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRMidTierContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder); - } - - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); - -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.debug.internal.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.options.*; /** * Base class for all {@link LIR low-level} phases. Subclasses should be stateless. There will be @@ -40,6 +41,13 @@ */ public abstract class LIRPhase { + public static class Options { + // @formatter:off + @Option(help = "Enable LIR level optimiztations.", type = OptionType.Debug) + public static final OptionValue LIROptimization = new OptionValue<>(true); + // @formatter:on + } + private static final int PHASE_DUMP_LEVEL = 2; private CharSequence name; @@ -73,22 +81,24 @@ memUseTracker = Debug.memUseTracker("LIRPhaseMemUse_%s", getClass()); } - public final > void apply(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context) { + public final > void apply(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context) { apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, true); } - public final > void apply(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context, boolean dumpLIR) { - try (TimerCloseable a = timer.start(); Scope s = Debug.scope(getName(), this); Closeable c = memUseTracker.start()) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context); - if (dumpLIR && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) { - Debug.dump(PHASE_DUMP_LEVEL, lirGenRes.getLIR(), "After phase %s", getName()); + public final > void apply(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context, boolean dumpLIR) { + try (Scope s = Debug.scope(getName(), this)) { + try (TimerCloseable a = timer.start(); Closeable c = memUseTracker.start()) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context); + if (dumpLIR && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) { + Debug.dump(PHASE_DUMP_LEVEL, lirGenRes.getLIR(), "After phase %s", getName()); + } } } catch (Throwable e) { throw Debug.handle(e); } } - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context); + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context); protected CharSequence createName() { String className = LIRPhase.this.getClass().getName(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java Mon Mar 02 19:11:22 2015 +0100 @@ -69,7 +69,7 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context) { for (LIRPhase phase : phases) { phase.apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,54 +25,54 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.gen.*; -import com.oracle.graal.lir.phases.LIRHighTierPhase.LIRHighTierContext; -import com.oracle.graal.lir.phases.LIRLowTierPhase.LIRLowTierContext; -import com.oracle.graal.lir.phases.LIRMidTierPhase.LIRMidTierContext; +import com.oracle.graal.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; +import com.oracle.graal.lir.phases.AllocationPhase.AllocationContext; public class LIRSuites { - private final LIRPhaseSuite highTier; - private final LIRPhaseSuite midTier; - private final LIRPhaseSuite lowTier; + private final LIRPhaseSuite preAllocOptStage; + private final LIRPhaseSuite allocStage; + private final LIRPhaseSuite postAllocStage; - public LIRSuites(LIRPhaseSuite highTier, LIRPhaseSuite midTier, LIRPhaseSuite lowTier) { - this.highTier = highTier; - this.midTier = midTier; - this.lowTier = lowTier; + public LIRSuites(LIRPhaseSuite preAllocOptStage, LIRPhaseSuite allocStage, LIRPhaseSuite postAllocStage) { + this.preAllocOptStage = preAllocOptStage; + this.allocStage = allocStage; + this.postAllocStage = postAllocStage; } /** - * {@link LIRHighTierPhase}s are executed between {@link LIR} generation and register - * allocation. + * {@link PreAllocationOptimizationPhase}s are executed between {@link LIR} generation and + * register allocation. *

    - * {@link LIRHighTierPhase Implementers} can create new {@link LIRGeneratorTool#newVariable - * variables}, {@link LIRGenerationResult#getFrameMap stack slots} and - * {@link LIRGenerationResult#getFrameMapBuilder virtual stack slots}. + * {@link PreAllocationOptimizationPhase Implementers} can create new + * {@link LIRGeneratorTool#newVariable variables}, {@link LIRGenerationResult#getFrameMap stack + * slots} and {@link LIRGenerationResult#getFrameMapBuilder virtual stack slots}. */ - public LIRPhaseSuite getHighTier() { - return highTier; + public LIRPhaseSuite getPreAllocationOptimizationStage() { + return preAllocOptStage; } /** - * {@link LIRMidTierPhase}s are responsible for register allocation and translating + * {@link AllocationPhase}s are responsible for register allocation and translating * {@link VirtualStackSlot}s into {@link StackSlot}s. *

    - * After the {@link LIRMidTier} there should be no more {@link Variable}s and + * After the {@link AllocationStage} there should be no more {@link Variable}s and * {@link VirtualStackSlot}s. */ - public LIRPhaseSuite getMidTier() { - return midTier; + public LIRPhaseSuite getAllocationStage() { + return allocStage; } /** - * {@link LIRLowTierPhase}s are executed after register allocation and before machine code - * generation. + * {@link PostAllocationOptimizationPhase}s are executed after register allocation and before + * machine code generation. *

    - * A {@link LIRLowTierPhase} must not introduce new {@link Variable}s, {@link VirtualStackSlot}s - * or {@link StackSlot}s. + * A {@link PostAllocationOptimizationPhase} must not introduce new {@link Variable}s, + * {@link VirtualStackSlot}s or {@link StackSlot}s. */ - public LIRPhaseSuite getLowTier() { - return lowTier; + public LIRPhaseSuite getPostAllocationOptimizationStage() { + return postAllocStage; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.lir.phases; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.gen.*; + +public abstract class PostAllocationOptimizationPhase extends LIRPhase { + + public static final class PostAllocationOptimizationContext { + } + + @Override + protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + PostAllocationOptimizationContext context) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder); + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); + +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.lir.phases; + +import static com.oracle.graal.lir.phases.LIRPhase.Options.*; + +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.*; +import com.oracle.graal.options.*; + +public class PostAllocationOptimizationStage extends LIRPhaseSuite { + public static class Options { + // @formatter:off + @Option(help = "", type = OptionType.Debug) + public static final NestedBooleanOptionValue LIROptEdgeMoveOptimizer = new NestedBooleanOptionValue(LIROptimization, true); + @Option(help = "", type = OptionType.Debug) + public static final NestedBooleanOptionValue LIROptControlFlowOptmizer = new NestedBooleanOptionValue(LIROptimization, true); + @Option(help = "", type = OptionType.Debug) + public static final NestedBooleanOptionValue LIROptRedundantMoveElimination = new NestedBooleanOptionValue(LIROptimization, true); + @Option(help = "", type = OptionType.Debug) + public static final NestedBooleanOptionValue LIROptNullCheckOptimizer = new NestedBooleanOptionValue(LIROptimization, true); + // @formatter:on + } + + public PostAllocationOptimizationStage() { + if (Options.LIROptEdgeMoveOptimizer.getValue()) { + appendPhase(new EdgeMoveOptimizer()); + } + if (Options.LIROptControlFlowOptmizer.getValue()) { + appendPhase(new ControlFlowOptimizer()); + } + if (Options.LIROptRedundantMoveElimination.getValue()) { + appendPhase(new RedundantMoveElimination()); + } + if (Options.LIROptNullCheckOptimizer.getValue()) { + appendPhase(new NullCheckOptimizer()); + } + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PreAllocationOptimizationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PreAllocationOptimizationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.lir.phases; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.gen.*; + +public abstract class PreAllocationOptimizationPhase extends LIRPhase { + + public static final class PreAllocationOptimizationContext { + private final LIRGeneratorTool lirGen; + + public PreAllocationOptimizationContext(LIRGeneratorTool lirGen) { + this.lirGen = lirGen; + } + + } + + @Override + protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + PreAllocationOptimizationContext context) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.lirGen); + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRGeneratorTool lirGen); + +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PreAllocationOptimizationStage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PreAllocationOptimizationStage.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.lir.phases; + +import com.oracle.graal.lir.constopt.*; +import com.oracle.graal.lir.phases.PreAllocationOptimizationPhase.*; + +public class PreAllocationOptimizationStage extends LIRPhaseSuite { + public PreAllocationOptimizationStage() { + if (ConstantLoadOptimization.Options.LIROptConstantLoadOptimization.getValue()) { + appendPhase(new ConstantLoadOptimization()); + } + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java Mon Mar 02 19:11:22 2015 +0100 @@ -65,15 +65,15 @@ * virtual stack slots. */ Set build() { - Deque> worklist = new ArrayDeque<>(); + Deque> worklist = new ArrayDeque<>(); for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) { worklist.add(lir.getControlFlowGraph().getBlocks().get(i)); } - for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { liveInMap.put(block, new BitSet(stackSlotMap.length)); } while (!worklist.isEmpty()) { - AbstractBlock block = worklist.poll(); + AbstractBlockBase block = worklist.poll(); processBlock(block, worklist); } return usePos; @@ -82,7 +82,7 @@ /** * Merge outSet with in-set of successors. */ - private boolean updateOutBlock(AbstractBlock block) { + private boolean updateOutBlock(AbstractBlockBase block) { BitSet union = new BitSet(stackSlotMap.length); block.getSuccessors().forEach(succ -> union.or(liveInMap.get(succ))); BitSet outSet = liveOutMap.get(block); @@ -94,7 +94,7 @@ return false; } - private void processBlock(AbstractBlock block, Deque> worklist) { + private void processBlock(AbstractBlockBase block, Deque> worklist) { if (updateOutBlock(block)) { try (Indent indent = Debug.logAndIndent("handle block %s", block)) { List instructions = lir.getLIRforBlock(block); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.lir.stackslotalloc; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.phases.LIRPhase.Options.LIROptimization; import java.util.*; import java.util.function.*; @@ -38,6 +39,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; import com.oracle.graal.lir.phases.*; import com.oracle.graal.options.*; @@ -51,12 +53,12 @@ * {@link OperandFlag#UNINITIALIZED}. Otherwise the stack slot might be reused and its content * destroyed. */ -public final class LSStackSlotAllocator extends LIRMidTierPhase implements StackSlotAllocator { +public final class LSStackSlotAllocator extends AllocationPhase implements StackSlotAllocator { public static class Options { // @formatter:off @Option(help = "Use linear scan stack slot allocation.", type = OptionType.Debug) - public static final OptionValue LIROptLSStackSlotAllocator = new OptionValue<>(true); + public static final NestedBooleanOptionValue LIROptLSStackSlotAllocator = new NestedBooleanOptionValue(LIROptimization, true); // @formatter:on } @@ -68,7 +70,7 @@ private static final DebugTimer AssignSlotsTimer = Debug.timer("LSStackSlotAllocator[AssignSlots]"); @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { lirGenRes.buildFrameMap(this); } @@ -84,7 +86,7 @@ private final StackInterval[] stackSlotMap; private final PriorityQueue unhandled; private final PriorityQueue active; - private final List> sortedBlocks; + private final List> sortedBlocks; private final int maxOpId; private Allocator(LIR lir, FrameMapBuilderTool frameMapBuilder) { @@ -149,10 +151,10 @@ * * @return The id of the last operation. */ - private static int numberInstructions(LIR lir, List> sortedBlocks) { + private static int numberInstructions(LIR lir, List> sortedBlocks) { int opId = 0; int index = 0; - for (AbstractBlock block : sortedBlocks) { + for (AbstractBlockBase block : sortedBlocks) { List instructions = lir.getLIRforBlock(block); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,12 +34,13 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; import com.oracle.graal.lir.phases.*; -public class SimpleStackSlotAllocator extends LIRMidTierPhase implements StackSlotAllocator { +public class SimpleStackSlotAllocator extends AllocationPhase implements StackSlotAllocator { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { lirGenRes.buildFrameMap(this); } @@ -75,7 +76,7 @@ } return value; }; - for (AbstractBlock block : res.getLIR().getControlFlowGraph().getBlocks()) { + for (AbstractBlockBase block : res.getLIR().getControlFlowGraph().getBlocks()) { try (Indent indent0 = Debug.logAndIndent("block: %s", block)) { for (LIRInstruction inst : res.getLIR().getLIRforBlock(block)) { try (Indent indent1 = Debug.logAndIndent("Inst: %d: %s", inst.id(), inst)) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Mon Mar 02 19:11:22 2015 +0100 @@ -175,13 +175,13 @@ negated = true; } LogicNode ifTest = ifNode.condition(); - if (!(ifTest instanceof IntegerLessThanNode)) { + if (!(ifTest instanceof IntegerLessThanNode) && !(ifTest instanceof IntegerEqualsNode)) { if (ifTest instanceof IntegerBelowNode) { Debug.log("Ignored potential Counted loop at %s with |<|", loopBegin); } return false; } - IntegerLessThanNode lessThan = (IntegerLessThanNode) ifTest; + CompareNode lessThan = (CompareNode) ifTest; Condition condition = null; InductionVariable iv = null; ValueNode limit = null; @@ -198,6 +198,9 @@ limit = lessThan.getY(); } } + if (iv != null && iv.isConstantStride() && iv.constantStride() != 1 && !(ifTest instanceof IntegerLessThanNode)) { + return false; + } if (condition == null) { return false; } @@ -206,6 +209,24 @@ } boolean oneOff = false; switch (condition) { + case EQ: + return false; + case NE: { + IntegerStamp initStamp = (IntegerStamp) iv.initNode().stamp(); + IntegerStamp limitStamp = (IntegerStamp) limit.stamp(); + if (iv.direction() == Direction.Up) { + if (initStamp.upperBound() > limitStamp.lowerBound()) { + return false; + } + } else { + assert iv.direction() == Direction.Down; + if (initStamp.lowerBound() < limitStamp.upperBound()) { + return false; + } + } + oneOff = true; + break; + } case LE: oneOff = true; // fall through case LT: diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Mar 02 19:11:22 2015 +0100 @@ -312,9 +312,9 @@ if (newEarlyExit == null) { continue; } - AbstractMergeNode merge = graph.add(new MergeNode()); - AbstractEndNode originalEnd = graph.add(new EndNode()); - AbstractEndNode newEnd = graph.add(new EndNode()); + MergeNode merge = graph.add(new MergeNode()); + EndNode originalEnd = graph.add(new EndNode()); + EndNode newEnd = graph.add(new EndNode()); merge.addForwardEnd(originalEnd); merge.addForwardEnd(newEnd); loopEarlyExit.setNext(originalEnd); @@ -332,7 +332,7 @@ * VirtualState nodes contained in the old exit's state may be shared by other * dominated VirtualStates. Those dominated virtual states need to see the * proxy->phi update that are applied below. - * + * * We now update the original fragment's nodes accordingly: */ originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node)); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Mon Mar 02 19:11:22 2015 +0100 @@ -293,14 +293,14 @@ private AbstractBeginNode mergeEnds() { assert isDuplicate(); - List endsToMerge = new LinkedList<>(); + List endsToMerge = new LinkedList<>(); // map peel exits to the corresponding loop exits Map reverseEnds = CollectionsFactory.newMap(); LoopBeginNode loopBegin = original().loop().loopBegin(); for (LoopEndNode le : loopBegin.loopEnds()) { AbstractEndNode duplicate = getDuplicatedNode(le); if (duplicate != null) { - endsToMerge.add(duplicate); + endsToMerge.add((EndNode) duplicate); reverseEnds.put(duplicate, le); } } @@ -323,7 +323,7 @@ duplicateState = state.duplicateWithVirtualState(); newExitMerge.setStateAfter(duplicateState); } - for (AbstractEndNode end : endsToMerge) { + for (EndNode end : endsToMerge) { newExitMerge.addForwardEnd(end); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Mon Mar 02 19:11:22 2015 +0100 @@ -68,6 +68,8 @@ LoopFragmentWhole originalLoop = loop.whole(); StructuredGraph graph = firstNode.graph(); + loop.loopBegin().incrementUnswitches(); + // create new control split out of loop ControlSplitNode newControlSplit = (ControlSplitNode) firstNode.copyWithInputs(); originalLoop.entryPoint().replaceAtPredecessor(newControlSplit); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopUnswitchingPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopUnswitchingPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopUnswitchingPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -43,7 +43,7 @@ do { unswitched = false; final LoopsData dataUnswitch = new LoopsData(graph); - for (LoopEx loop : dataUnswitch.loops()) { + for (LoopEx loop : dataUnswitch.outerFirst()) { if (LoopPolicies.shouldTryUnswitch(loop)) { List controlSplits = LoopTransformations.findUnswitchable(loop); if (controlSplits != null) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java --- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java Mon Mar 02 19:11:22 2015 +0100 @@ -133,6 +133,18 @@ // NodeInfo.class.getSimpleName()); // continue; } + boolean found = false; + for (Element e : typeElement.getEnclosedElements()) { + if (e.getKind() == ElementKind.FIELD) { + if (e.getSimpleName().toString().equals("TYPE")) { + found = true; + break; + } + } + } + if (!found) { + errorMessage(element, "%s annotated class must have a field named TYPE", NodeInfo.class.getSimpleName()); + } if (!typeElement.equals(verifier.Node) && !modifiers.contains(Modifier.ABSTRACT)) { verifier.verify(typeElement); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,17 +33,18 @@ import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.util.*; @NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor}) public abstract class AbstractBeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType { - public AbstractBeginNode() { - super(StampFactory.forVoid()); + public static final NodeClass TYPE = NodeClass.create(AbstractBeginNode.class); + + protected AbstractBeginNode(NodeClass c) { + this(c, StampFactory.forVoid()); } - public AbstractBeginNode(Stamp stamp) { - super(stamp); + protected AbstractBeginNode(NodeClass c, Stamp stamp) { + super(c, stamp); } @Override @@ -62,8 +63,13 @@ } public static AbstractBeginNode prevBegin(FixedNode from) { - for (AbstractBeginNode begin : GraphUtil.predecessorIterable(from).filter(AbstractBeginNode.class)) { - return begin; + Node next = from; + while (next != null) { + if (next instanceof AbstractBeginNode) { + AbstractBeginNode begin = (AbstractBeginNode) next; + return begin; + } + next = next.predecessor(); } return null; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,14 +36,11 @@ @NodeInfo public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode.DeoptBefore { + public static final NodeClass TYPE = NodeClass.create(AbstractDeoptimizeNode.class); @OptionalInput(InputType.State) FrameState stateBefore; - public AbstractDeoptimizeNode() { - super(StampFactory.forVoid()); - } - - public AbstractDeoptimizeNode(FrameState stateBefore) { - super(StampFactory.forVoid()); + protected AbstractDeoptimizeNode(NodeClass c, FrameState stateBefore) { + super(c, StampFactory.forVoid()); this.stateBefore = stateBefore; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,8 +32,10 @@ @NodeInfo public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable { - protected AbstractEndNode() { - super(StampFactory.forVoid()); + public static final NodeClass TYPE = NodeClass.create(AbstractEndNode.class); + + protected AbstractEndNode(NodeClass c) { + super(c, StampFactory.forVoid()); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.extended.*; @@ -32,6 +33,7 @@ @NodeInfo public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(AbstractFixedGuardNode.class); @Input(InputType.Condition) protected LogicNode condition; protected final DeoptimizationReason reason; protected final DeoptimizationAction action; @@ -46,8 +48,8 @@ condition = x; } - protected AbstractFixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { - super(StampFactory.forVoid()); + protected AbstractFixedGuardNode(NodeClass c, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { + super(c, StampFactory.forVoid()); this.action = action; this.negated = negated; this.condition = condition; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +23,18 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; @NodeInfo public abstract class AbstractLocalNode extends FloatingNode { + public static final NodeClass TYPE = NodeClass.create(AbstractLocalNode.class); protected final int index; - public AbstractLocalNode(int index, Stamp stamp) { - super(stamp); + protected AbstractLocalNode(NodeClass c, int index, Stamp stamp) { + super(c, stamp); this.index = index; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; @@ -32,11 +33,13 @@ @NodeInfo public abstract class AbstractMemoryCheckpoint extends AbstractStateSplit implements MemoryCheckpoint { - protected AbstractMemoryCheckpoint(Stamp stamp) { - super(stamp); + public static final NodeClass TYPE = NodeClass.create(AbstractMemoryCheckpoint.class); + + protected AbstractMemoryCheckpoint(NodeClass c, Stamp stamp) { + this(c, stamp, null); } - protected AbstractMemoryCheckpoint(Stamp stamp, FrameState stateAfter) { - super(stamp, stateAfter); + protected AbstractMemoryCheckpoint(NodeClass c, Stamp stamp, FrameState stateAfter) { + super(c, stamp, stateAfter); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -39,21 +39,24 @@ */ @NodeInfo(allowedUsageTypes = {InputType.Association}) public abstract class AbstractMergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable { - protected AbstractMergeNode() { + public static final NodeClass TYPE = NodeClass.create(AbstractMergeNode.class); + + protected AbstractMergeNode(NodeClass c) { + super(c); } - @Input(InputType.Association) protected NodeInputList ends = new NodeInputList<>(this); + @Input(InputType.Association) protected NodeInputList ends = new NodeInputList<>(this); @Override public void generate(NodeLIRBuilderTool gen) { gen.visitMerge(this); } - public int forwardEndIndex(AbstractEndNode end) { + public int forwardEndIndex(EndNode end) { return ends.indexOf(end); } - public void addForwardEnd(AbstractEndNode end) { + public void addForwardEnd(EndNode end) { ends.add(end); } @@ -61,12 +64,12 @@ return ends.size(); } - public AbstractEndNode forwardEndAt(int index) { + public EndNode forwardEndAt(int index) { return ends.get(index); } @Override - public NodeIterable cfgPredecessors() { + public NodeIterable cfgPredecessors() { return ends; } @@ -110,7 +113,7 @@ ends.clear(); } - public NodeInputList forwardEnds() { + public NodeInputList forwardEnds() { return ends; } @@ -119,7 +122,7 @@ } public int phiPredecessorIndex(AbstractEndNode pred) { - return forwardEndIndex(pred); + return forwardEndIndex((EndNode) pred); } public AbstractEndNode phiPredecessorAt(int index) { @@ -173,8 +176,9 @@ if (merge instanceof LoopBeginNode) { newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge)); } else { - newEnd = graph().add(new EndNode()); - merge.addForwardEnd(newEnd); + EndNode tmpEnd = graph().add(new EndNode()); + merge.addForwardEnd(tmpEnd); + newEnd = tmpEnd; } for (PhiNode phi : merge.phis()) { ValueNode v = phi.valueAt(origLoopEnd); @@ -210,8 +214,8 @@ } ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result(); - List endNodes = forwardEnds().snapshot(); - for (AbstractEndNode end : endNodes) { + List endNodes = forwardEnds().snapshot(); + for (EndNode end : endNodes) { ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end))); if (tool != null) { tool.addToWorkList(end.predecessor()); @@ -219,7 +223,7 @@ end.replaceAtPredecessor(newReturn); } GraphUtil.killCFG(this); - for (AbstractEndNode end : endNodes) { + for (EndNode end : endNodes) { end.safeDelete(); } for (PhiNode phi : phis) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; /** @@ -31,6 +32,7 @@ @NodeInfo public abstract class AbstractStateSplit extends FixedWithNextNode implements StateSplit { + public static final NodeClass TYPE = NodeClass.create(AbstractStateSplit.class); @OptionalInput(InputType.State) protected FrameState stateAfter; public FrameState stateAfter() { @@ -47,12 +49,12 @@ return true; } - public AbstractStateSplit(Stamp stamp) { - super(stamp); + protected AbstractStateSplit(NodeClass c, Stamp stamp) { + this(c, stamp, null); } - public AbstractStateSplit(Stamp stamp, FrameState stateAfter) { - super(stamp); + protected AbstractStateSplit(NodeClass c, Stamp stamp, FrameState stateAfter) { + super(c, stamp); this.stateAfter = stateAfter; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,17 +23,20 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; @NodeInfo public final class BeginNode extends AbstractBeginNode { + public static final NodeClass TYPE = NodeClass.create(BeginNode.class); + public BeginNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } public BeginNode(Stamp stamp) { - super(stamp); + super(TYPE, stamp); } public static AbstractBeginNode begin(FixedNode with) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; /** @@ -35,13 +36,15 @@ @NodeInfo public abstract class BeginStateSplitNode extends AbstractBeginNode implements StateSplit { + public static final NodeClass TYPE = NodeClass.create(BeginStateSplitNode.class); @OptionalInput(InputType.State) protected FrameState stateAfter; - public BeginStateSplitNode() { + protected BeginStateSplitNode(NodeClass c) { + super(c); } - protected BeginStateSplitNode(Stamp stamp) { - super(stamp); + protected BeginStateSplitNode(NodeClass c, Stamp stamp) { + super(c, stamp); } public FrameState stateAfter() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @@ -29,6 +30,7 @@ @NodeInfo public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Binary { + public static final NodeClass TYPE = NodeClass.create(BinaryOpLogicNode.class); @Input protected ValueNode x; @Input protected ValueNode y; @@ -40,7 +42,8 @@ return y; } - public BinaryOpLogicNode(ValueNode x, ValueNode y) { + public BinaryOpLogicNode(NodeClass c, ValueNode x, ValueNode y) { + super(c); assert x != null && y != null && x.getKind() == y.getKind(); this.x = x; this.y = y; @@ -55,4 +58,29 @@ @Override public void generate(NodeLIRBuilderTool gen) { } + + /** + * Ensure a canonical ordering of inputs for commutative nodes to improve GVN results. Order the + * inputs by increasing {@link Node#id} and call {@link Graph#findDuplicate(Node)} on the node + * if it's currently in a graph. + * + * @return the original node or another node with the same inputs, ignoring ordering. + */ + @SuppressWarnings("deprecation") + public LogicNode maybeCommuteInputs() { + assert this instanceof BinaryCommutative; + if (x.getId() > y.getId()) { + ValueNode tmp = x; + x = y; + y = tmp; + if (graph() != null) { + // See if this node already exists + LogicNode duplicate = graph().findDuplicate(this); + if (duplicate != null) { + return duplicate; + } + } + } + return this; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -48,10 +48,11 @@ @NodeInfo public final class BreakpointNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(BreakpointNode.class); @Input NodeInputList arguments; public BreakpointNode(ValueNode[] arguments) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.arguments = new NodeInputList<>(this, arguments); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,6 +32,8 @@ @NodeInfo(allowedUsageTypes = {InputType.Extension}) public abstract class CallTargetNode extends ValueNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(CallTargetNode.class); + public enum InvokeKind { Interface(false), Special(true), @@ -65,15 +67,15 @@ protected ResolvedJavaMethod targetMethod; protected InvokeKind invokeKind; - public CallTargetNode(ValueNode[] arguments, ResolvedJavaMethod targetMethod, InvokeKind invokeKind) { - super(StampFactory.forVoid()); + protected CallTargetNode(NodeClass c, ValueNode[] arguments, ResolvedJavaMethod targetMethod, InvokeKind invokeKind) { + super(c, StampFactory.forVoid()); this.targetMethod = targetMethod; this.invokeKind = invokeKind; this.arguments = new NodeInputList<>(this, arguments); } - public CallTargetNode(List arguments, ResolvedJavaMethod targetMethod, InvokeKind invokeKind) { - super(StampFactory.forVoid()); + protected CallTargetNode(NodeClass c, List arguments, ResolvedJavaMethod targetMethod, InvokeKind invokeKind) { + super(c, StampFactory.forVoid()); this.targetMethod = targetMethod; this.invokeKind = invokeKind; this.arguments = new NodeInputList<>(this, arguments); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,6 +32,7 @@ @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard}) public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(ConditionAnchorNode.class); @Input(InputType.Condition) LogicNode condition; protected boolean negated; @@ -40,7 +41,7 @@ } public ConditionAnchorNode(LogicNode condition, boolean negated) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.negated = negated; this.condition = condition; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -41,6 +41,7 @@ @NodeInfo(shortName = "Const", nameTemplate = "Const({p#rawvalue})") public final class ConstantNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(ConstantNode.class); private static final DebugMetric ConstantNodes = Debug.metric("ConstantNodes"); protected final Constant value; @@ -56,7 +57,7 @@ * @param value the constant */ public ConstantNode(Constant value, Stamp stamp) { - super(stamp); + super(TYPE, stamp); assert stamp != null && isCompatible(value, stamp); this.value = value; ConstantNodes.increment(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,12 +23,14 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; @NodeInfo public abstract class ControlSinkNode extends FixedNode { + public static final NodeClass TYPE = NodeClass.create(ControlSinkNode.class); - public ControlSinkNode(Stamp stamp) { - super(stamp); + protected ControlSinkNode(NodeClass c, Stamp stamp) { + super(c, stamp); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,9 +32,10 @@ */ @NodeInfo public abstract class ControlSplitNode extends FixedNode implements IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(ControlSplitNode.class); - public ControlSplitNode(Stamp stamp) { - super(stamp); + protected ControlSplitNode(NodeClass c, Stamp stamp) { + super(c, stamp); } public abstract double probability(AbstractBeginNode successor); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,23 +23,27 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable { + public static final int DEFAULT_DEBUG_ID = 0; + public static final NodeClass TYPE = NodeClass.create(DeoptimizeNode.class); protected final DeoptimizationAction action; protected final DeoptimizationReason reason; protected final int debugId; protected final JavaConstant speculation; public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) { - this(action, reason, 0, JavaConstant.NULL_POINTER, null); + this(action, reason, DEFAULT_DEBUG_ID, JavaConstant.NULL_POINTER, null); } public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, JavaConstant speculation, FrameState stateBefore) { - super(stateBefore); + super(TYPE, stateBefore); assert action != null; assert reason != null; assert speculation.getKind() == Kind.Object; @@ -62,14 +66,23 @@ tool.getLowerer().lower(this, tool); } + @SuppressWarnings("deprecation") + public int getDebugId() { + int deoptDebugId = debugId; + if (deoptDebugId == DEFAULT_DEBUG_ID && (Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod())) { + deoptDebugId = this.getId(); + } + return deoptDebugId; + } + @Override public void generate(NodeLIRBuilderTool gen) { - gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, gen.state(this)); + gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, getDebugId()), speculation, gen.state(this)); } @Override public ValueNode getActionAndReason(MetaAccessProvider metaAccess) { - return ConstantNode.forConstant(metaAccess.encodeDeoptActionAndReason(action, reason, debugId), metaAccess, graph()); + return ConstantNode.forConstant(metaAccess.encodeDeoptActionAndReason(action, reason, getDebugId()), metaAccess, graph()); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,19 +23,21 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; @NodeInfo public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore { + public static final NodeClass TYPE = NodeClass.create(DeoptimizingFixedWithNextNode.class); @OptionalInput(InputType.State) protected FrameState stateBefore; - public DeoptimizingFixedWithNextNode(Stamp stamp) { - super(stamp); + protected DeoptimizingFixedWithNextNode(NodeClass c, Stamp stamp) { + super(c, stamp); } - public DeoptimizingFixedWithNextNode(Stamp stamp, FrameState stateBefore) { - super(stamp); + protected DeoptimizingFixedWithNextNode(NodeClass c, Stamp stamp, FrameState stateBefore) { + super(c, stamp); this.stateBefore = stateBefore; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,13 +27,17 @@ 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.nodeinfo.*; @NodeInfo -public class DirectCallTargetNode extends LoweredCallTargetNode { +public abstract class DirectCallTargetNode extends LoweredCallTargetNode { + + public static final NodeClass TYPE = NodeClass.create(DirectCallTargetNode.class); - public DirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { - super(arguments, returnStamp, signature, target, callType, invokeKind); + protected DirectCallTargetNode(NodeClass c, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, + CallingConvention.Type callType, InvokeKind invokeKind) { + super(c, arguments, returnStamp, signature, target, callType, invokeKind); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; /** @@ -31,11 +32,14 @@ @NodeInfo public class DispatchBeginNode extends BeginStateSplitNode { + public static final NodeClass TYPE = NodeClass.create(DispatchBeginNode.class); + public DispatchBeginNode() { + super(TYPE); } - public DispatchBeginNode(Stamp stamp) { - super(stamp); + protected DispatchBeginNode(NodeClass c, Stamp stamp) { + super(c, stamp); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,10 +30,12 @@ @NodeInfo public final class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Lowerable, Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(DynamicDeoptimizeNode.class); @Input ValueNode actionAndReason; @Input ValueNode speculation; public DynamicDeoptimizeNode(ValueNode actionAndReason, ValueNode speculation) { + super(TYPE, null); this.actionAndReason = actionAndReason; this.speculation = speculation; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,11 +22,15 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; @NodeInfo(allowedUsageTypes = {InputType.Association}) -public class EndNode extends AbstractEndNode { +public final class EndNode extends AbstractEndNode { + public static final NodeClass TYPE = NodeClass.create(EndNode.class); + public EndNode() { + super(TYPE); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +34,10 @@ */ @NodeInfo(allowedUsageTypes = {InputType.Association}) public final class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(EntryMarkerNode.class); public EntryMarkerNode() { + super(TYPE); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,13 +31,14 @@ @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard}) public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(FixedGuardNode.class); public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { this(condition, deoptReason, action, false); } public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { - super(condition, deoptReason, action, negated); + super(TYPE, condition, deoptReason, action, negated); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,13 +23,15 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; @NodeInfo public abstract class FixedNode extends ValueNode { + public static final NodeClass TYPE = NodeClass.create(FixedNode.class); - public FixedNode(Stamp stamp) { - super(stamp); + protected FixedNode(NodeClass c, Stamp stamp) { + super(c, stamp); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; /** @@ -31,6 +32,7 @@ */ @NodeInfo public abstract class FixedWithNextNode extends FixedNode { + public static final NodeClass TYPE = NodeClass.create(FixedWithNextNode.class); @Successor protected FixedNode next; @@ -43,8 +45,8 @@ next = x; } - public FixedWithNextNode(Stamp stamp) { - super(stamp); + public FixedWithNextNode(NodeClass c, Stamp stamp) { + super(c, stamp); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,21 +23,23 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @NodeInfo public abstract class FloatingAnchoredNode extends FloatingNode { + public static final NodeClass TYPE = NodeClass.create(FloatingAnchoredNode.class); @Input(InputType.Anchor) protected AnchoringNode anchor; - public FloatingAnchoredNode(Stamp stamp) { - super(stamp); + public FloatingAnchoredNode(NodeClass c, Stamp stamp) { + super(c, stamp); } - public FloatingAnchoredNode(Stamp stamp, AnchoringNode anchor) { - super(stamp); + public FloatingAnchoredNode(NodeClass c, Stamp stamp, AnchoringNode anchor) { + super(c, stamp); this.anchor = anchor; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,21 +23,23 @@ package com.oracle.graal.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @NodeInfo public abstract class FloatingGuardedNode extends FloatingNode implements GuardedNode { + public static final NodeClass TYPE = NodeClass.create(FloatingGuardedNode.class); @OptionalInput(InputType.Guard) protected GuardingNode guard; - public FloatingGuardedNode(Stamp stamp) { - super(stamp); + protected FloatingGuardedNode(NodeClass c, Stamp stamp) { + super(c, stamp); } - public FloatingGuardedNode(Stamp stamp, GuardingNode guard) { - super(stamp); + protected FloatingGuardedNode(NodeClass c, Stamp stamp, GuardingNode guard) { + super(c, stamp); this.guard = guard; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Mon Mar 02 19:11:22 2015 +0100 @@ -41,7 +41,8 @@ * This can be used as debug or deoptimization information. */ @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}") -public class FrameState extends VirtualState implements IterableNodeType { +public final class FrameState extends VirtualState implements IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(FrameState.class); private static final DebugMetric METRIC_FRAMESTATE_COUNT = Debug.metric("FrameStateCount"); @@ -76,6 +77,7 @@ public FrameState(FrameState outerFrameState, ResolvedJavaMethod method, int bci, int localsSize, int stackSize, int lockSize, boolean rethrowException, boolean duringCall, List monitorIds, List virtualObjectMappings) { + super(TYPE); assert stackSize >= 0; this.outerFrameState = outerFrameState; this.method = method; @@ -249,14 +251,20 @@ * changed to newBci. */ private FrameState duplicateModified(int newBci, boolean newRethrowException, boolean newDuringCall, Kind popKind, ValueNode... pushedValues) { - ArrayList copy = new ArrayList<>(values.subList(0, localsSize + stackSize)); - if (popKind != Kind.Void) { - if (stackAt(stackSize() - 1) == null) { + ArrayList copy; + if (newRethrowException && !rethrowException && popKind == Kind.Void) { + assert popKind == Kind.Void; + copy = new ArrayList<>(values.subList(0, localsSize)); + } else { + copy = new ArrayList<>(values.subList(0, localsSize + stackSize)); + if (popKind != Kind.Void) { + if (stackAt(stackSize() - 1) == null) { + copy.remove(copy.size() - 1); + } + ValueNode lastSlot = copy.get(copy.size() - 1); + assert lastSlot.getKind().getStackKind() == popKind.getStackKind(); copy.remove(copy.size() - 1); } - ValueNode lastSlot = copy.get(copy.size() - 1); - assert lastSlot.getKind().getStackKind() == popKind.getStackKind(); - copy.remove(copy.size() - 1); } for (ValueNode node : pushedValues) { copy.add(node); @@ -267,7 +275,7 @@ int newStackSize = copy.size() - localsSize; copy.addAll(values.subList(localsSize + stackSize, values.size())); - assert checkStackDepth(bci, stackSize, duringCall, newBci, newStackSize, newDuringCall); + assert checkStackDepth(bci, stackSize, duringCall, rethrowException, newBci, newStackSize, newDuringCall, newRethrowException); return graph().add(new FrameState(outerFrameState(), method, newBci, copy, localsSize, newStackSize, newRethrowException, newDuringCall, monitorIds, virtualObjectMappings)); } @@ -275,7 +283,7 @@ * Perform a few sanity checks on the transformation of the stack state. The current expectation * is that a stateAfter is being transformed into a stateDuring, so the stack depth may change. */ - private boolean checkStackDepth(int oldBci, int oldStackSize, boolean oldDuringCall, int newBci, int newStackSize, boolean newDuringCall) { + private boolean checkStackDepth(int oldBci, int oldStackSize, boolean oldDuringCall, boolean oldRethrowException, int newBci, int newStackSize, boolean newDuringCall, boolean newRethrowException) { /* * It would be nice to have a complete check of the shape of the FrameState based on a * dataflow of the bytecodes but for now just check for obvious expression stack depth @@ -288,7 +296,7 @@ } byte newCode = codes[newBci]; if (oldBci == newBci) { - assert oldStackSize == newStackSize || oldDuringCall != newDuringCall : "bci is unchanged, stack depth shouldn't change"; + assert oldStackSize == newStackSize || oldDuringCall != newDuringCall || oldRethrowException != newRethrowException : "bci is unchanged, stack depth shouldn't change"; } else { byte oldCode = codes[oldBci]; assert Bytecodes.lengthOf(newCode) + newBci == oldBci || Bytecodes.lengthOf(oldCode) + oldBci == newBci : "expecting roll back or forward"; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @@ -30,11 +31,12 @@ * Nodes of this type are inserted into the graph to denote points of interest to debugging. */ @NodeInfo -public class FullInfopointNode extends InfopointNode implements LIRLowerable, NodeWithState { +public final class FullInfopointNode extends InfopointNode implements LIRLowerable, NodeWithState { + public static final NodeClass TYPE = NodeClass.create(FullInfopointNode.class); @Input(InputType.State) FrameState state; public FullInfopointNode(InfopointReason reason, FrameState state) { - super(reason); + super(TYPE, reason); this.state = state; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -44,6 +44,7 @@ @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard}) public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(GuardNode.class); @Input(InputType.Condition) protected LogicNode condition; protected final DeoptimizationReason reason; protected JavaConstant speculation; @@ -51,7 +52,11 @@ protected boolean negated; public GuardNode(LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, JavaConstant speculation) { - super(StampFactory.forVoid(), anchor); + this(TYPE, condition, anchor, reason, action, negated, speculation); + } + + protected GuardNode(NodeClass c, LogicNode condition, AnchoringNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, JavaConstant speculation) { + super(c, StampFactory.forVoid(), anchor); this.condition = condition; this.reason = reason; this.action = action; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,17 +31,18 @@ * Guard {@link PhiNode}s merge guard dependencies at control flow merges. */ @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard}) -public class GuardPhiNode extends PhiNode implements GuardingNode { +public final class GuardPhiNode extends PhiNode implements GuardingNode { + public static final NodeClass TYPE = NodeClass.create(GuardPhiNode.class); @OptionalInput(InputType.Guard) NodeInputList values; public GuardPhiNode(AbstractMergeNode merge) { - super(StampFactory.forVoid(), merge); + super(TYPE, StampFactory.forVoid(), merge); this.values = new NodeInputList<>(this); } public GuardPhiNode(AbstractMergeNode merge, ValueNode[] values) { - super(StampFactory.forVoid(), merge); + super(TYPE, StampFactory.forVoid(), merge); this.values = new NodeInputList<>(this, values); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -29,12 +29,13 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(allowedUsageTypes = {InputType.Guard}) -public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable { +public final class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(GuardProxyNode.class); @Input(InputType.Guard) GuardingNode value; public GuardProxyNode(GuardingNode value, AbstractBeginNode proxyPoint) { - super(StampFactory.forVoid(), proxyPoint); + super(TYPE, StampFactory.forVoid(), proxyPoint); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,13 +37,14 @@ * A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}. */ @NodeInfo -public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy { +public final class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(GuardedValueNode.class); @Input ValueNode object; protected final Stamp piStamp; public GuardedValueNode(ValueNode object, GuardingNode guard, Stamp stamp) { - super(stamp, guard); + super(TYPE, stamp, guard); this.object = object; this.piStamp = stamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -42,6 +42,7 @@ @NodeInfo(nameTemplate = "GuardingPi(!={p#negated}) {p#reason/s}") public final class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, Canonicalizable, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(GuardingPiNode.class); @Input ValueNode object; @Input(InputType.Condition) LogicNode condition; protected final DeoptimizationReason reason; @@ -89,7 +90,7 @@ } public GuardingPiNode(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) { - super(stamp); + super(TYPE, stamp); assert stamp != null; this.piStamp = stamp; this.object = object; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes; -import static com.oracle.graal.graph.Edges.Type.*; - import java.util.*; import com.oracle.graal.api.meta.*; @@ -47,7 +45,8 @@ * of a comparison. */ @NodeInfo -public class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable { +public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(IfNode.class); private static final DebugMetric CORRECTED_PROBABILITIES = Debug.metric("CorrectedProbabilities"); @@ -70,7 +69,7 @@ } public IfNode(LogicNode condition, AbstractBeginNode trueSuccessor, AbstractBeginNode falseSuccessor, double trueSuccessorProbability) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.condition = condition; this.falseSuccessor = falseSuccessor; this.trueSuccessor = trueSuccessor; @@ -95,6 +94,10 @@ return falseSuccessor; } + public double getTrueSuccessorProbability() { + return this.trueSuccessorProbability; + } + public void setTrueSuccessor(AbstractBeginNode node) { updatePredecessor(trueSuccessor, node); trueSuccessor = node; @@ -234,16 +237,16 @@ if (trueSucc instanceof BeginNode && falseSucc instanceof BeginNode && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) { FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next(); FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); - NodeClass nodeClass = trueNext.getNodeClass(); + NodeClass nodeClass = trueNext.getNodeClass(); if (trueNext.getClass() == falseNext.getClass()) { - if (nodeClass.getEdges(Inputs).areEqualIn(trueNext, falseNext) && trueNext.valueEquals(falseNext)) { + if (nodeClass.getInputEdges().areEqualIn(trueNext, falseNext) && trueNext.valueEquals(falseNext)) { falseNext.replaceAtUsages(trueNext); graph().removeFixed(falseNext); GraphUtil.unlinkFixedNode(trueNext); graph().addBeforeFixed(this, trueNext); for (Node usage : trueNext.usages().snapshot()) { if (usage.isAlive()) { - NodeClass usageNodeClass = usage.getNodeClass(); + NodeClass usageNodeClass = usage.getNodeClass(); if (usageNodeClass.valueNumberable() && !usageNodeClass.isLeafNode()) { Node newNode = graph().findDuplicate(usage); if (newNode != null) { @@ -365,6 +368,16 @@ return false; } + private static final class MutableProfiledType { + final ResolvedJavaType type; + double probability; + + public MutableProfiledType(ResolvedJavaType type, double probability) { + this.type = type; + this.probability = probability; + } + } + private static boolean prepareForSwap(ConstantReflectionProvider constantReflection, LogicNode a, LogicNode b, double probabilityA, double probabilityB) { if (a instanceof InstanceOfNode) { InstanceOfNode instanceOfA = (InstanceOfNode) a; @@ -382,44 +395,8 @@ 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(); - JavaTypeProfile profileB = instanceOfB.profile(); - Debug.log("Can swap instanceof for types %s and %s", instanceOfA.type(), instanceOfB.type()); - JavaTypeProfile newProfile = null; - if (profileA != null && profileB != null) { - double remainder = 1.0; - ArrayList profiledTypes = new ArrayList<>(); - for (ProfiledType type : profileB.getTypes()) { - if (instanceOfB.type().isAssignableFrom(type.getType())) { - // Do not add to profile. - } else { - ProfiledType newType = new ProfiledType(type.getType(), Math.min(1.0, type.getProbability() * (1.0 - probabilityA) / (1.0 - probabilityB))); - profiledTypes.add(newType); - remainder -= newType.getProbability(); - } - } - - for (ProfiledType type : profileA.getTypes()) { - if (instanceOfA.type().isAssignableFrom(type.getType())) { - ProfiledType newType = new ProfiledType(type.getType(), Math.min(1.0, type.getProbability() / (1.0 - probabilityB))); - profiledTypes.add(newType); - remainder -= newType.getProbability(); - } - } - Collections.sort(profiledTypes); - - if (remainder < 0.0) { - // Can happen due to round-off errors. - remainder = 0.0; - } - newProfile = new JavaTypeProfile(profileB.getNullSeen(), remainder, profiledTypes.toArray(new ProfiledType[profiledTypes.size()])); - Debug.log("First profile: %s", profileA); - Debug.log("Original second profile: %s", profileB); - Debug.log("New second profile: %s", newProfile); - } - instanceOfB.setProfile(profileA); - instanceOfA.setProfile(newProfile); + swapInstanceOfProfiles(probabilityA, probabilityB, instanceOfA, instanceOfB); return true; } } @@ -476,6 +453,116 @@ return false; } + /** + * Arbitrary fraction of not recorded types that we'll guess are sub-types of B. + * + * This is is used because we can not check if the unrecorded types are sub-types of B or not. + */ + private static final double NOT_RECORDED_SUBTYPE_B = 0.5; + + /** + * If the not-recorded fraction of types for the new profile of instanceOfA is + * above this threshold, no profile is used for this instanceof after the swap. + * + * The idea is that the reconstructed profile would contain too much unknowns to be of any use. + */ + private static final double NOT_RECORDED_CUTOFF = 0.4; + + /** + * Tries to reconstruct profiles for the swapped instanceof checks. + * + * The tested types must be mutually exclusive. + */ + private static void swapInstanceOfProfiles(double probabilityA, double probabilityB, InstanceOfNode instanceOfA, InstanceOfNode instanceOfB) { + JavaTypeProfile profileA = instanceOfA.profile(); + JavaTypeProfile profileB = instanceOfB.profile(); + + JavaTypeProfile newProfileA = null; + JavaTypeProfile newProfileB = null; + if (profileA != null || profileB != null) { + List newProfiledTypesA = new ArrayList<>(); + List newProfiledTypesB = new ArrayList<>(); + double totalProbabilityA = 0.0; + double totalProbabilityB = 0.0; + double newNotRecordedA = 0.0; + double newNotRecordedB = 0.0; + TriState nullSeen = TriState.UNKNOWN; + if (profileA != null) { + for (ProfiledType profiledType : profileA.getTypes()) { + newProfiledTypesB.add(new MutableProfiledType(profiledType.getType(), profiledType.getProbability())); + totalProbabilityB += profiledType.getProbability(); + if (!instanceOfB.type().isAssignableFrom(profiledType.getType())) { + double typeProbabilityA = profiledType.getProbability() / (1 - probabilityB); + newProfiledTypesA.add(new MutableProfiledType(profiledType.getType(), typeProbabilityA)); + totalProbabilityA += typeProbabilityA; + } + } + newNotRecordedB += profileA.getNotRecordedProbability(); + newNotRecordedA += NOT_RECORDED_SUBTYPE_B * profileA.getNotRecordedProbability() / (1 - probabilityB); + nullSeen = profileA.getNullSeen(); + } + int searchA = newProfiledTypesA.size(); + int searchB = newProfiledTypesB.size(); + if (profileB != null) { + for (ProfiledType profiledType : profileB.getTypes()) { + double typeProbabilityB = profiledType.getProbability() * (1 - probabilityA); + appendOrMerge(profiledType.getType(), typeProbabilityB, searchB, newProfiledTypesB); + totalProbabilityB += typeProbabilityB; + if (!instanceOfB.type().isAssignableFrom(profiledType.getType())) { + double typeProbabilityA = typeProbabilityB / (1 - probabilityB); + appendOrMerge(profiledType.getType(), typeProbabilityA, searchA, newProfiledTypesA); + totalProbabilityA += typeProbabilityA; + } + } + newNotRecordedB += profileB.getNotRecordedProbability() * (1 - probabilityA); + newNotRecordedA += NOT_RECORDED_SUBTYPE_B * profileB.getNotRecordedProbability() * (1 - probabilityA) / (1 - probabilityB); + nullSeen = TriState.merge(nullSeen, profileB.getNullSeen()); + } + totalProbabilityA += newNotRecordedA; + totalProbabilityB += newNotRecordedB; + + if (newNotRecordedA / NOT_RECORDED_SUBTYPE_B > NOT_RECORDED_CUTOFF) { + // too much unknown + newProfileA = null; + } else { + newProfileA = makeProfile(totalProbabilityA, newNotRecordedA, newProfiledTypesA, nullSeen); + } + newProfileB = makeProfile(totalProbabilityB, newNotRecordedB, newProfiledTypesB, nullSeen); + } + + instanceOfB.setProfile(newProfileB); + instanceOfA.setProfile(newProfileA); + } + + private static JavaTypeProfile makeProfile(double totalProbability, double notRecorded, List profiledTypes, TriState nullSeen) { + // protect against NaNs and empty profiles + if (totalProbability > 0.0) { + // normalize + ProfiledType[] profiledTypesArray = new ProfiledType[profiledTypes.size()]; + int i = 0; + for (MutableProfiledType profiledType : profiledTypes) { + profiledTypesArray[i++] = new ProfiledType(profiledType.type, profiledType.probability / totalProbability); + } + + // sort + Arrays.sort(profiledTypesArray); + + return new JavaTypeProfile(nullSeen, notRecorded / totalProbability, profiledTypesArray); + } + return null; + } + + private static void appendOrMerge(ResolvedJavaType type, double probability, int searchUntil, List list) { + for (int i = 0; i < searchUntil; i++) { + MutableProfiledType profiledType = list.get(i); + if (profiledType.type.equals(type)) { + profiledType.probability += probability; + return; + } + } + list.add(new MutableProfiledType(type, probability)); + } + private static boolean valuesDistinct(ConstantReflectionProvider constantReflection, ValueNode a, ValueNode b) { if (a.isConstant() && b.isConstant()) { Boolean equal = constantReflection.constantEquals(a.asConstant(), b.asConstant()); @@ -516,7 +603,6 @@ * Multiple phis but merging same values for true and false, so simply delete * the path */ - tool.addToWorkList(condition()); removeThroughFalseBranch(tool); return true; } else if (distinct == 1) { @@ -559,6 +645,9 @@ AbstractBeginNode trueBegin = trueSuccessor(); graph().removeSplitPropagate(this, trueBegin, tool); tool.addToWorkList(trueBegin); + if (condition().isAlive() && condition().hasNoUsages()) { + GraphUtil.killWithUnusedFloatingInputs(condition()); + } } private ConditionalNode canonicalizeConditionalCascade(ValueNode trueValue, ValueNode falseValue) { @@ -663,7 +752,7 @@ MergeNode falseMerge = null; assert merge.stateAfter() == null; - for (AbstractEndNode end : merge.forwardEnds().snapshot()) { + for (EndNode end : merge.forwardEnds().snapshot()) { Node value = phi.valueAt(end); Node result = null; if (condition() instanceof Canonicalizable.Binary) { @@ -819,7 +908,7 @@ } } - List mergePredecessors = merge.cfgPredecessors().snapshot(); + List mergePredecessors = merge.cfgPredecessors().snapshot(); assert phi.valueCount() == merge.forwardEndCount(); Constant[] xs = constantValues(compare.getX(), merge, false); @@ -833,8 +922,8 @@ return false; } - List falseEnds = new ArrayList<>(mergePredecessors.size()); - List trueEnds = new ArrayList<>(mergePredecessors.size()); + List falseEnds = new ArrayList<>(mergePredecessors.size()); + List trueEnds = new ArrayList<>(mergePredecessors.size()); Map phiValues = CollectionsFactory.newMap(mergePredecessors.size()); AbstractBeginNode oldFalseSuccessor = falseSuccessor(); @@ -843,9 +932,9 @@ setFalseSuccessor(null); setTrueSuccessor(null); - Iterator ends = mergePredecessors.iterator(); + Iterator ends = mergePredecessors.iterator(); for (int i = 0; i < xs.length; i++) { - AbstractEndNode end = ends.next(); + EndNode end = ends.next(); phiValues.put(end, phi.valueAt(end)); if (compare.condition().foldCondition(xs[i], ys[i], tool.getConstantReflection(), compare.unorderedIsTrue())) { trueEnds.add(end); @@ -975,7 +1064,7 @@ * @param oldMerge the merge being removed * @param phiValues the values of the phi at the merge, keyed by the merge ends */ - private void connectEnds(List ends, Map phiValues, AbstractBeginNode successor, AbstractMergeNode oldMerge, SimplifierTool tool) { + private void connectEnds(List ends, Map phiValues, AbstractBeginNode successor, AbstractMergeNode oldMerge, SimplifierTool tool) { if (!ends.isEmpty()) { if (ends.size() == 1) { AbstractEndNode end = ends.get(0); @@ -989,7 +1078,7 @@ PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(), newMerge)); - for (AbstractEndNode end : ends) { + for (EndNode end : ends) { newPhi.addInput(phiValues.get(end)); newMerge.addForwardEnd(end); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +27,18 @@ 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.nodeinfo.*; @NodeInfo -public class IndirectCallTargetNode extends LoweredCallTargetNode { +public abstract class IndirectCallTargetNode extends LoweredCallTargetNode { + public static final NodeClass TYPE = NodeClass.create(IndirectCallTargetNode.class); @Input protected ValueNode computedAddress; - public IndirectCallTargetNode(ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, - InvokeKind invokeKind) { - super(arguments, returnStamp, signature, target, callType, invokeKind); + protected IndirectCallTargetNode(NodeClass c, ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, + ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { + super(c, arguments, returnStamp, signature, target, callType, invokeKind); this.computedAddress = computedAddress; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,14 +24,16 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; @NodeInfo public abstract class InfopointNode extends FixedWithNextNode { + public static final NodeClass TYPE = NodeClass.create(InfopointNode.class); protected final InfopointReason reason; - public InfopointNode(InfopointReason reason) { - super(StampFactory.forVoid()); + public InfopointNode(NodeClass c, InfopointReason reason) { + super(c, StampFactory.forVoid()); this.reason = reason; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ * The {@code InvokeNode} represents all kinds of method calls. */ @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory}) -public class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single { +public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(InvokeNode.class); @Input(InputType.Extension) CallTargetNode callTarget; @OptionalInput(InputType.State) FrameState stateDuring; @@ -51,7 +52,7 @@ } public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) { - super(stamp); + super(TYPE, stamp); this.callTarget = callTarget; this.bci = bci; this.polymorphic = false; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory}) -public class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable { +public final class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(InvokeWithExceptionNode.class); private static final double EXCEPTION_PROBA = 1e-5; @@ -49,7 +50,7 @@ protected double exceptionProbability; public InvokeWithExceptionNode(CallTargetNode callTarget, AbstractBeginNode exceptionEdge, int bci) { - super(callTarget.returnStamp()); + super(TYPE, callTarget.returnStamp()); this.exceptionEdge = exceptionEdge; this.bci = bci; this.callTarget = callTarget; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +23,18 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single { +public final class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(KillingBeginNode.class); protected LocationIdentity locationIdentity; public KillingBeginNode(LocationIdentity locationIdentity) { + super(TYPE); this.locationIdentity = locationIdentity; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +30,13 @@ * The {@code LogicConstantNode} represents a boolean constant. */ @NodeInfo(nameTemplate = "{p#value}") -public class LogicConstantNode extends LogicNode implements LIRLowerable { +public final class LogicConstantNode extends LogicNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(LogicConstantNode.class); protected final boolean value; public LogicConstantNode(boolean value) { - super(); + super(TYPE); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; @@ -29,25 +30,45 @@ * Logic node that negates its argument. */ @NodeInfo -public class LogicNegationNode extends LogicNode implements Canonicalizable.Unary { +public final class LogicNegationNode extends LogicNode implements Canonicalizable.Unary { + public static final NodeClass TYPE = NodeClass.create(LogicNegationNode.class); @Input(InputType.Condition) LogicNode value; public LogicNegationNode(LogicNode value) { + super(TYPE); this.value = value; } + public static LogicNode create(LogicNode value) { + LogicNode synonym = findSynonym(value); + if (synonym != null) { + return synonym; + } + return new LogicNegationNode(value); + } + + private static LogicNode findSynonym(LogicNode value) { + if (value instanceof LogicConstantNode) { + LogicConstantNode logicConstantNode = (LogicConstantNode) value; + return LogicConstantNode.forBoolean(!logicConstantNode.getValue()); + } else if (value instanceof LogicNegationNode) { + return ((LogicNegationNode) value).getValue(); + } + return null; + } + public LogicNode getValue() { return value; } @Override public LogicNode canonical(CanonicalizerTool tool, LogicNode forValue) { - if (forValue instanceof LogicNegationNode) { - return ((LogicNegationNode) forValue).getValue(); - } else { - return this; + LogicNode synonym = findSynonym(forValue); + if (synonym != null) { + return synonym; } + return this; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,14 +25,17 @@ import static com.oracle.graal.nodeinfo.InputType.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.calc.*; @NodeInfo(allowedUsageTypes = {Condition}) public abstract class LogicNode extends FloatingNode { - public LogicNode() { - super(StampFactory.forVoid()); + public static final NodeClass TYPE = NodeClass.create(LogicNode.class); + + public LogicNode(NodeClass c) { + super(c, StampFactory.forVoid()); } public static LogicNode and(LogicNode a, LogicNode b, double shortCircuitProbability) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,14 +37,18 @@ import com.oracle.graal.nodes.util.*; @NodeInfo -public class LoopBeginNode extends AbstractMergeNode implements IterableNodeType, LIRLowerable { +public final class LoopBeginNode extends AbstractMergeNode implements IterableNodeType, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(LoopBeginNode.class); protected double loopFrequency; protected int nextEndIndex; protected int unswitches; + protected int inversionCount; + @OptionalInput(InputType.Guard) GuardingNode overflowGuard; public LoopBeginNode() { + super(TYPE); loopFrequency = 1; } @@ -94,16 +98,12 @@ * * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop */ - public List orderedLoopEnds() { - List snapshot = loopEnds().snapshot(); - Collections.sort(snapshot, new Comparator() { - - @Override - public int compare(LoopEndNode o1, LoopEndNode o2) { - return o1.endIndex() - o2.endIndex(); - } - }); - return snapshot; + public LoopEndNode[] orderedLoopEnds() { + LoopEndNode[] result = new LoopEndNode[this.getLoopEndCount()]; + for (LoopEndNode end : loopEnds()) { + result[end.endIndex()] = end; + } + return result; } public AbstractEndNode forwardEnd() { @@ -149,7 +149,7 @@ return loopEnd.endIndex() + forwardEndCount(); } } else { - return super.forwardEndIndex(pred); + return super.forwardEndIndex((EndNode) pred); } throw ValueNodeUtil.shouldNotReachHere("unknown pred : " + pred); } @@ -179,14 +179,26 @@ return nextEndIndex++; } + public int getLoopEndCount() { + return nextEndIndex; + } + public int unswitches() { return unswitches; } - public void incUnswitches() { + public void incrementUnswitches() { unswitches++; } + public int getInversionCount() { + return inversionCount; + } + + public void setInversionCount(int count) { + inversionCount = count; + } + @Override public void simplify(SimplifierTool tool) { removeDeadPhis(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,13 +33,15 @@ * {@linkplain #loopBegin() loop header}. */ @NodeInfo -public class LoopEndNode extends AbstractEndNode { +public final class LoopEndNode extends AbstractEndNode { + public static final NodeClass TYPE = NodeClass.create(LoopEndNode.class); @Input(InputType.Association) LoopBeginNode loopBegin; protected boolean canSafepoint; protected int endIndex; public LoopEndNode(LoopBeginNode begin) { + super(TYPE); int idx = begin.nextEndIndex(); assert idx >= 0; this.endIndex = idx; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,11 +27,13 @@ import com.oracle.graal.nodeinfo.*; @NodeInfo(allowedUsageTypes = {InputType.Association}) -public class LoopExitNode extends BeginStateSplitNode implements IterableNodeType { +public final class LoopExitNode extends BeginStateSplitNode implements IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(LoopExitNode.class); @Input(InputType.Association) LoopBeginNode loopBegin; public LoopExitNode(LoopBeginNode loop) { + super(TYPE); assert loop != null; loopBegin = loop; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,17 +27,20 @@ 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.nodeinfo.*; @NodeInfo public abstract class LoweredCallTargetNode extends CallTargetNode { + public static final NodeClass TYPE = NodeClass.create(LoweredCallTargetNode.class); protected final Stamp returnStamp; protected final JavaType[] signature; protected final CallingConvention.Type callType; - public LoweredCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { - super(arguments, target, invokeKind); + protected LoweredCallTargetNode(NodeClass c, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, + CallingConvention.Type callType, InvokeKind invokeKind) { + super(c, arguments, target, invokeKind); this.returnStamp = returnStamp; this.signature = signature; this.callType = callType; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +38,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Extension}) public final class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(MemoryMapNode.class); protected final List locationIdentities; @Input(InputType.Memory) NodeInputList nodes; @@ -51,7 +52,7 @@ } public MemoryMapNode(Map mmap) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); locationIdentities = new ArrayList<>(mmap.keySet()); nodes = new NodeInputList<>(this, mmap.values()); assert checkOrder(mmap); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,17 +34,18 @@ @NodeInfo(nameTemplate = "MemoryPhi({i#values}) {p#locationIdentity/s}", allowedUsageTypes = {InputType.Memory}) public final class MemoryPhiNode extends PhiNode implements MemoryNode { + public static final NodeClass TYPE = NodeClass.create(MemoryPhiNode.class); @Input(InputType.Memory) NodeInputList values; protected final LocationIdentity locationIdentity; public MemoryPhiNode(AbstractMergeNode merge, LocationIdentity locationIdentity) { - super(StampFactory.forVoid(), merge); + super(TYPE, StampFactory.forVoid(), merge); this.locationIdentity = locationIdentity; this.values = new NodeInputList<>(this); } public MemoryPhiNode(AbstractMergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) { - super(StampFactory.forVoid(), merge); + super(TYPE, StampFactory.forVoid(), merge); this.locationIdentity = locationIdentity; this.values = new NodeInputList<>(this, values); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; /** @@ -29,6 +30,27 @@ */ @NodeInfo public final class MergeNode extends AbstractMergeNode { + + public static final NodeClass TYPE = NodeClass.create(MergeNode.class); + public MergeNode() { + super(TYPE); + } + + public static void removeMergeIfDegenerated(MergeNode node) { + if (node.forwardEndCount() == 1 && node.hasNoUsages()) { + FixedNode currentNext = node.next(); + node.setNext(null); + EndNode forwardEnd = node.forwardEndAt(0); + forwardEnd.replaceAtPredecessor(currentNext); + node.markDeleted(); + forwardEnd.markDeleted(); + } + } + + @Override + public boolean verify() { + assertTrue(this.forwardEndCount() > 1, "Must merge more than one end."); + return true; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 @@ * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call. */ @NodeInfo(nameTemplate = "Param({p#index})") -public class ParameterNode extends AbstractLocalNode implements IterableNodeType, UncheckedInterfaceProvider { +public final class ParameterNode extends AbstractLocalNode implements IterableNodeType, UncheckedInterfaceProvider { + + public static final NodeClass TYPE = NodeClass.create(ParameterNode.class); public ParameterNode(int index, Stamp stamp) { - super(index, stamp); + super(TYPE, index, stamp); } public Stamp uncheckedStamp() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +41,11 @@ @NodeInfo public abstract class PhiNode extends FloatingNode implements Simplifiable { + public static final NodeClass TYPE = NodeClass.create(PhiNode.class); @Input(InputType.Association) protected AbstractMergeNode merge; - protected PhiNode(Stamp stamp, AbstractMergeNode merge) { - super(stamp); + protected PhiNode(NodeClass c, Stamp stamp, AbstractMergeNode merge) { + super(c, stamp); this.merge = merge; } @@ -142,10 +143,12 @@ } @NodeInfo - static class MultipleValuesNode extends ValueNode { + static final class MultipleValuesNode extends ValueNode { + + public static final NodeClass TYPE = NodeClass.create(MultipleValuesNode.class); public MultipleValuesNode() { - super(null); + super(TYPE, null); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,8 +36,9 @@ * this information. */ @NodeInfo -public class PiArrayNode extends PiNode implements ArrayLengthProvider { +public final class PiArrayNode extends PiNode implements ArrayLengthProvider { + public static final NodeClass TYPE = NodeClass.create(PiArrayNode.class); @Input ValueNode length; public ValueNode length() { @@ -45,7 +46,7 @@ } public PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) { - super(object, stamp); + super(TYPE, object, stamp); this.length = length; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +44,7 @@ @NodeInfo public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(PiNode.class); @Input ValueNode object; protected final Stamp piStamp; @@ -51,12 +52,18 @@ return object; } + protected PiNode(NodeClass c, ValueNode object, Stamp stamp) { + super(c, stamp, null); + this.object = object; + this.piStamp = stamp; + } + public PiNode(ValueNode object, Stamp stamp) { this(object, stamp, null); } public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) { - super(stamp, (GuardingNode) anchor); + super(TYPE, stamp, (GuardingNode) anchor); this.object = object; this.piStamp = stamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,10 +36,11 @@ @NodeInfo public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable { + public static final NodeClass TYPE = NodeClass.create(ProxyNode.class); @Input(InputType.Association) AbstractBeginNode proxyPoint; - public ProxyNode(Stamp stamp, AbstractBeginNode proxyPoint) { - super(stamp); + protected ProxyNode(NodeClass c, Stamp stamp, AbstractBeginNode proxyPoint) { + super(c, stamp); assert proxyPoint != null; this.proxyPoint = proxyPoint; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +28,9 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType { +public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(ReturnNode.class); @OptionalInput ValueNode result; @OptionalInput(InputType.Extension) MemoryMapNode memoryMap; @@ -42,7 +43,7 @@ } public ReturnNode(ValueNode result, MemoryMapNode memoryMap) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.result = result; this.memoryMap = memoryMap; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.nodes; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @@ -30,10 +31,12 @@ * Marks a position in the graph where a safepoint should be emitted. */ @NodeInfo -public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable { +public final class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(SafepointNode.class); public SafepointNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,8 +27,9 @@ import com.oracle.graal.nodeinfo.*; @NodeInfo -public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary { +public final class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary { + public static final NodeClass TYPE = NodeClass.create(ShortCircuitOrNode.class); @Input(InputType.Condition) LogicNode x; @Input(InputType.Condition) LogicNode y; protected boolean xNegated; @@ -36,6 +37,7 @@ protected double shortCircuitProbability; public ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { + super(TYPE); this.x = x; this.xNegated = xNegated; this.y = y; @@ -105,7 +107,7 @@ if (isXNegated()) { if (isYNegated()) { // !a || !a = !a - return new LogicNegationNode(forX); + return LogicNegationNode.create(forX); } else { // !a || a = true return LogicConstantNode.tautology(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,11 +29,12 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public class SimpleInfopointNode extends InfopointNode implements LIRLowerable, IterableNodeType, Simplifiable { +public final class SimpleInfopointNode extends InfopointNode implements LIRLowerable, IterableNodeType, Simplifiable { + public static final NodeClass TYPE = NodeClass.create(SimpleInfopointNode.class); protected BytecodePosition position; public SimpleInfopointNode(InfopointReason reason, BytecodePosition position) { - super(reason); + super(TYPE, reason); this.position = position; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.extended.*; @@ -31,7 +32,14 @@ */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(StartNode.class); + + protected StartNode(NodeClass c) { + super(c); + } + public StartNode() { + super(TYPE); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon Mar 02 19:11:22 2015 +0100 @@ -151,7 +151,7 @@ public Stamp getReturnStamp() { Stamp returnStamp = null; - for (ReturnNode returnNode : getNodes(ReturnNode.class)) { + for (ReturnNode returnNode : getNodes(ReturnNode.TYPE)) { ValueNode result = returnNode.result(); if (result != null) { if (returnStamp == null) { @@ -246,7 +246,7 @@ } public ParameterNode getParameter(int index) { - for (ParameterNode param : getNodes(ParameterNode.class)) { + for (ParameterNode param : getNodes(ParameterNode.TYPE)) { if (param.index() == index) { return param; } @@ -255,7 +255,7 @@ } public Iterable getInvokes() { - final Iterator callTargets = getNodes(MethodCallTargetNode.class).iterator(); + final Iterator callTargets = getNodes(MethodCallTargetNode.TYPE).iterator(); return new Iterable() { private Invoke next; @@ -299,7 +299,7 @@ } public boolean hasLoops() { - return hasNode(LoopBeginNode.class); + return hasNode(LoopBeginNode.TYPE); } public void removeFloating(FloatingNode node) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,8 +37,9 @@ * A node that attaches a type profile to a proxied input node. */ @NodeInfo -public class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy { +public final class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(TypeProfileProxyNode.class); protected final JavaTypeProfile profile; protected transient ResolvedJavaType lastCheckedType; protected transient JavaTypeProfile lastCheckedProfile; @@ -59,7 +60,7 @@ } protected TypeProfileProxyNode(ValueNode value, JavaTypeProfile profile) { - super(value.stamp(), value); + super(TYPE, value.stamp(), value); this.profile = profile; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @@ -29,13 +30,15 @@ @NodeInfo public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Unary { + public static final NodeClass TYPE = NodeClass.create(UnaryOpLogicNode.class); @Input protected ValueNode value; public ValueNode getValue() { return value; } - public UnaryOpLogicNode(ValueNode value) { + public UnaryOpLogicNode(NodeClass c, ValueNode value) { + super(c); assert value != null; this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @@ -31,8 +32,9 @@ * Unwinds the current frame to an exception handler in the caller frame. */ @NodeInfo -public class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable { +public final class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(UnwindNode.class); @Input ValueNode exception; public ValueNode exception() { @@ -40,7 +42,7 @@ } public UnwindNode(ValueNode exception) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); assert exception == null || exception.getKind() == Kind.Object; this.exception = exception; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodeinfo.*; @@ -34,13 +35,15 @@ @NodeInfo public abstract class ValueNode extends com.oracle.graal.graph.Node implements KindProvider { + public static final NodeClass TYPE = NodeClass.create(ValueNode.class); /** * The kind of this value. This is {@link Kind#Void} for instructions that produce no value. * This kind is guaranteed to be a {@linkplain Kind#getStackKind() stack kind}. */ protected Stamp stamp; - public ValueNode(Stamp stamp) { + public ValueNode(NodeClass c, Stamp stamp) { + super(c); this.stamp = stamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Mar 02 19:11:22 2015 +0100 @@ -88,7 +88,7 @@ * Converts a given instruction to a value string. The representation of an node as a value is * formed by concatenating the {@linkplain com.oracle.graal.api.meta.Kind#getTypeChar character} * denoting its {@linkplain ValueNode#getKind kind} and its id. For example, {@code "i13"}. - * + * * @param value the instruction to convert to a value string. If {@code value == null}, then "-" * is returned. * @return the instruction representation as a string diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +33,21 @@ @NodeInfo(nameTemplate = "ValuePhi({i#values})") public class ValuePhiNode extends PhiNode { + public static final NodeClass TYPE = NodeClass.create(ValuePhiNode.class); @Input protected NodeInputList values; public ValuePhiNode(Stamp stamp, AbstractMergeNode merge) { - super(stamp, merge); + this(TYPE, stamp, merge); + } + + protected ValuePhiNode(NodeClass c, Stamp stamp, AbstractMergeNode merge) { + super(c, stamp, merge); assert stamp != StampFactory.forVoid(); values = new NodeInputList<>(this); } public ValuePhiNode(Stamp stamp, AbstractMergeNode merge, ValueNode[] values) { - super(stamp, merge); + super(TYPE, stamp, merge); assert stamp != StampFactory.forVoid(); this.values = new NodeInputList<>(this, values); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +28,13 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public class ValueProxyNode extends ProxyNode implements Canonicalizable, Virtualizable, ValueProxy { +public final class ValueProxyNode extends ProxyNode implements Canonicalizable, Virtualizable, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(ValueProxyNode.class); @Input ValueNode value; public ValueProxyNode(ValueNode value, AbstractBeginNode proxyPoint) { - super(value.stamp(), proxyPoint); + super(TYPE, value.stamp(), proxyPoint); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +32,12 @@ @NodeInfo(allowedUsageTypes = {InputType.State}) public abstract class VirtualState extends Node { + protected VirtualState(NodeClass c) { + super(c); + } + + public static final NodeClass TYPE = NodeClass.create(VirtualState.class); + public abstract static class NodeClosure { public abstract void apply(Node usage, T node); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Abs; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -35,9 +36,10 @@ */ @NodeInfo public final class AbsNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { + public static final NodeClass TYPE = NodeClass.create(AbsNode.class); public AbsNode(ValueNode x) { - super(ArithmeticOpTable::getAbs, x); + super(TYPE, ArithmeticOpTable::getAbs, x); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Add; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -33,10 +35,16 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "+") -public class AddNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { +public class AddNode extends BinaryArithmeticNode implements NarrowableArithmeticNode, BinaryCommutative { + + public static final NodeClass TYPE = NodeClass.create(AddNode.class); public AddNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getAdd, x, y); + this(TYPE, x, y); + } + + protected AddNode(NodeClass c, ValueNode x, ValueNode y) { + super(c, ArithmeticOpTable::getAdd, x, y); } public static ValueNode create(ValueNode x, ValueNode y) { @@ -46,7 +54,7 @@ if (tryConstantFold != null) { return tryConstantFold; } else { - return new AddNode(x, y); + return new AddNode(x, y).maybeCommuteInputs(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.And; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -34,10 +37,23 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "&") -public final class AndNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { +public final class AndNode extends BinaryArithmeticNode implements NarrowableArithmeticNode, BinaryCommutative { + + public static final NodeClass TYPE = NodeClass.create(AndNode.class); public AndNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getAnd, x, y); + super(TYPE, ArithmeticOpTable::getAnd, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getAnd(); + Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + if (tryConstantFold != null) { + return tryConstantFold; + } else { + return new AndNode(x, y).maybeCommuteInputs(); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,15 +37,17 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public abstract class BinaryArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { +public abstract class BinaryArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable, Canonicalizable.Binary { + + @SuppressWarnings("rawtypes") public static final NodeClass TYPE = NodeClass.create(BinaryArithmeticNode.class); protected interface SerializableBinaryFunction extends Function>, Serializable { } protected final SerializableBinaryFunction getOp; - public BinaryArithmeticNode(SerializableBinaryFunction getOp, ValueNode x, ValueNode y) { - super(getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), y.stamp()), x, y); + protected BinaryArithmeticNode(NodeClass> c, SerializableBinaryFunction getOp, ValueNode x, ValueNode y) { + super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), y.stamp()), x, y); this.getOp = getOp; } @@ -250,4 +252,30 @@ } return false; } + + /** + * Ensure a canonical ordering of inputs for commutative nodes to improve GVN results. Order the + * inputs by increasing {@link Node#id} and call {@link Graph#findDuplicate(Node)} on the node + * if it's currently in a graph. It's assumed that if there was a constant on the left it's been + * moved to the right by other code and that ordering is left alone. + * + * @return the original node or another node with the same input ordering + */ + @SuppressWarnings("deprecation") + public BinaryNode maybeCommuteInputs() { + assert this instanceof BinaryCommutative; + if (!y.isConstant() && x.getId() > y.getId()) { + ValueNode tmp = x; + x = y; + y = tmp; + if (graph() != null) { + // See if this node already exists + BinaryNode duplicate = graph().findDuplicate(this); + if (duplicate != null) { + return duplicate; + } + } + } + return this; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -33,6 +34,7 @@ @NodeInfo public abstract class BinaryNode extends FloatingNode implements Canonicalizable.Binary { + public static final NodeClass TYPE = NodeClass.create(BinaryNode.class); @Input protected ValueNode x; @Input protected ValueNode y; @@ -61,8 +63,8 @@ * @param x the first input instruction * @param y the second input instruction */ - public BinaryNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp); + protected BinaryNode(NodeClass c, Stamp stamp, ValueNode x, ValueNode y) { + super(c, stamp); this.x = x; this.y = y; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -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.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -37,8 +38,9 @@ * into variants that do not materialize the value (CompareIf, CompareGuard...) */ @NodeInfo -public abstract class CompareNode extends BinaryOpLogicNode { +public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary { + public static final NodeClass TYPE = NodeClass.create(CompareNode.class); protected final Condition condition; protected final boolean unorderedIsTrue; @@ -48,8 +50,8 @@ * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ - public CompareNode(Condition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) { - super(x, y); + protected CompareNode(NodeClass c, Condition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) { + super(c, x, y); this.condition = condition; this.unorderedIsTrue = unorderedIsTrue; } @@ -88,7 +90,7 @@ return conditionalNode.condition(); } else { assert falseResult == true; - return new LogicNegationNode(conditionalNode.condition()); + return LogicNegationNode.create(conditionalNode.condition()); } } @@ -166,7 +168,8 @@ } public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { - return graph.unique(createCompareNode(condition, x, y, constantReflection)); + LogicNode result = createCompareNode(condition, x, y, constantReflection); + return (result.graph() == null ? graph.unique(result) : result); } public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -40,6 +41,7 @@ @NodeInfo public final class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(ConditionalNode.class); @Input(InputType.Condition) LogicNode condition; @Input ValueNode trueValue; @Input ValueNode falseValue; @@ -53,7 +55,7 @@ } public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { - super(trueValue.stamp().meet(falseValue.stamp())); + super(TYPE, trueValue.stamp().meet(falseValue.stamp())); assert trueValue.stamp().isCompatible(falseValue.stamp()); this.condition = condition; this.trueValue = trueValue; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,7 +25,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Div; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -35,8 +37,21 @@ @NodeInfo(shortName = "/") public final class DivNode extends BinaryArithmeticNode

    { + public static final NodeClass TYPE = NodeClass.create(DivNode.class); + public DivNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getDiv, x, y); + super(TYPE, ArithmeticOpTable::getDiv, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y) { + BinaryOp
    op = ArithmeticOpTable.forStamp(x.stamp()).getDiv(); + Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + if (tryConstantFold != null) { + return tryConstantFold; + } else { + return new DivNode(x, y); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,18 +23,20 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode implements Canonicalizable.Binary { + public static final NodeClass TYPE = NodeClass.create(FixedBinaryNode.class); @Input protected ValueNode x; @Input protected ValueNode y; - public FixedBinaryNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp); + public FixedBinaryNode(NodeClass c, Stamp stamp, ValueNode x, ValueNode y) { + super(c, stamp); this.x = x; this.y = y; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -38,14 +39,23 @@ */ @NodeInfo public final class FloatConvertNode extends UnaryArithmeticNode implements ConvertNode, Lowerable, ArithmeticLIRLowerable { + public static final NodeClass TYPE = NodeClass.create(FloatConvertNode.class); protected final FloatConvert op; public FloatConvertNode(FloatConvert op, ValueNode input) { - super(table -> table.getFloatConvert(op), input); + super(TYPE, table -> table.getFloatConvert(op), input); this.op = op; } + public static ValueNode create(FloatConvert op, ValueNode input) { + ValueNode synonym = findSynonym(input, ArithmeticOpTable.forStamp(input.stamp()).getFloatConvert(op)); + if (synonym != null) { + return synonym; + } + return new FloatConvertNode(op, input); + } + public FloatConvert getFloatConvert() { return op; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,16 +26,19 @@ 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.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") -public final class FloatEqualsNode extends CompareNode { +public final class FloatEqualsNode extends CompareNode implements BinaryCommutative { + public static final NodeClass TYPE = NodeClass.create(FloatEqualsNode.class); public FloatEqualsNode(ValueNode x, ValueNode y) { - super(Condition.EQ, false, x, y); + super(TYPE, Condition.EQ, false, x, y); assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp : x.stamp() + " " + y.stamp(); assert x.stamp().isCompatible(y.stamp()); } @@ -45,7 +48,7 @@ if (result != null) { return result; } else { - return new FloatEqualsNode(x, y); + return new FloatEqualsNode(x, y).maybeCommuteInputs(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,23 +22,35 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") -public class FloatLessThanNode extends CompareNode { +public final class FloatLessThanNode extends CompareNode { + public static final NodeClass TYPE = NodeClass.create(FloatLessThanNode.class); public FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) { - super(Condition.LT, unorderedIsTrue, x, y); + super(TYPE, Condition.LT, unorderedIsTrue, x, y); assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp; assert x.stamp().isCompatible(y.stamp()); } + public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue, ConstantReflectionProvider constantReflection) { + LogicNode result = CompareNode.tryConstantFold(Condition.LT, x, y, constantReflection, unorderedIsTrue); + if (result != null) { + return result; + } else { + return new FloatLessThanNode(x, y, unorderedIsTrue); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { ValueNode result = super.canonical(tool, forX, forY); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -29,9 +29,10 @@ @NodeInfo public abstract class FloatingNode extends ValueNode implements Node.ValueNumberable { + public static final NodeClass TYPE = NodeClass.create(FloatingNode.class); - public FloatingNode(Stamp stamp) { - super(stamp); + public FloatingNode(NodeClass c, Stamp stamp) { + super(c, stamp); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,18 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|<|") -public class IntegerBelowNode extends CompareNode { +public final class IntegerBelowNode extends CompareNode { + public static final NodeClass TYPE = NodeClass.create(IntegerBelowNode.class); public IntegerBelowNode(ValueNode x, ValueNode y) { - super(Condition.BT, false, x, y); + super(TYPE, Condition.BT, false, x, y); assert x.stamp() instanceof IntegerStamp; assert y.stamp() instanceof IntegerStamp; } @@ -64,7 +66,7 @@ } if (forX.isConstant() && forX.asJavaConstant().asLong() == 0) { // 0 |<| y is the same as 0 != y - return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY, tool.getConstantReflection())); + return LogicNegationNode.create(CompareNode.createCompareNode(Condition.EQ, forX, forY, tool.getConstantReflection())); } return this; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -38,6 +39,7 @@ */ @NodeInfo public abstract class IntegerConvertNode extends UnaryNode implements ConvertNode, ArithmeticLIRLowerable { + @SuppressWarnings("rawtypes") public static final NodeClass TYPE = NodeClass.create(IntegerConvertNode.class); protected final SerializableIntegerConvertFunction getOp; protected final SerializableIntegerConvertFunction getReverseOp; @@ -48,8 +50,9 @@ protected interface SerializableIntegerConvertFunction extends Function>, Serializable { } - protected IntegerConvertNode(SerializableIntegerConvertFunction getOp, SerializableIntegerConvertFunction getReverseOp, int inputBits, int resultBits, ValueNode input) { - super(getOp.apply(ArithmeticOpTable.forStamp(input.stamp())).foldStamp(inputBits, resultBits, input.stamp()), input); + protected IntegerConvertNode(NodeClass> c, SerializableIntegerConvertFunction getOp, SerializableIntegerConvertFunction getReverseOp, int inputBits, + int resultBits, ValueNode input) { + super(c, getOp.apply(ArithmeticOpTable.forStamp(input.stamp())).foldStamp(inputBits, resultBits, input.stamp()), input); this.getOp = getOp; this.getReverseOp = getReverseOp; this.inputBits = inputBits; @@ -86,13 +89,20 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode synonym = findSynonym(getOp(forValue), forValue, inputBits, resultBits, stamp()); + if (synonym != null) { + return synonym; + } + return this; + } + + protected static ValueNode findSynonym(IntegerConvertOp operation, ValueNode value, int inputBits, int resultBits, Stamp stamp) { if (inputBits == resultBits) { return value; } else if (value.isConstant()) { - return ConstantNode.forPrimitive(stamp(), convert(forValue.asConstant(), tool.getConstantReflection())); - } else { - return this; + return ConstantNode.forPrimitive(stamp, operation.foldConstant(inputBits, resultBits, value.asConstant())); } + return null; } public static ValueNode convert(ValueNode input, Stamp stamp) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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 static com.oracle.graal.graph.Edges.Type.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -33,10 +31,11 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "/") -public class IntegerDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { +public final class IntegerDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(IntegerDivNode.class); public IntegerDivNode(ValueNode x, ValueNode y) { - super(IntegerStamp.OPS.getDiv().foldStamp(x.stamp(), y.stamp()), x, y); + super(TYPE, IntegerStamp.OPS.getDiv().foldStamp(x.stamp(), y.stamp()), x, y); } @Override @@ -94,8 +93,8 @@ } if (next() instanceof IntegerDivNode) { - NodeClass nodeClass = getNodeClass(); - if (next().getClass() == this.getClass() && nodeClass.getEdges(Inputs).areEqualIn(this, next()) && valueEquals(next())) { + NodeClass nodeClass = getNodeClass(); + if (next().getClass() == this.getClass() && nodeClass.getInputEdges().areEqualIn(this, next()) && valueEquals(next())) { return next(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,16 +26,19 @@ 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.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") -public final class IntegerEqualsNode extends CompareNode { +public final class IntegerEqualsNode extends CompareNode implements BinaryCommutative { + public static final NodeClass TYPE = NodeClass.create(IntegerEqualsNode.class); public IntegerEqualsNode(ValueNode x, ValueNode y) { - super(Condition.EQ, false, x, y); + super(TYPE, Condition.EQ, false, x, y); assert !x.getKind().isNumericFloat() && x.getKind() != Kind.Object; assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object; } @@ -45,7 +48,25 @@ if (result != null) { return result; } else { - return new IntegerEqualsNode(x, y); + if (x instanceof ConditionalNode) { + ConditionalNode conditionalNode = (ConditionalNode) x; + if (conditionalNode.trueValue() == y) { + return conditionalNode.condition(); + } + if (conditionalNode.falseValue() == y) { + return LogicNegationNode.create(conditionalNode.condition()); + } + } else if (y instanceof ConditionalNode) { + ConditionalNode conditionalNode = (ConditionalNode) y; + if (conditionalNode.trueValue() == x) { + return conditionalNode.condition(); + } + if (conditionalNode.falseValue() == x) { + return LogicNegationNode.create(conditionalNode.condition()); + } + } + + return new IntegerEqualsNode(x, y).maybeCommuteInputs(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +26,18 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") -public class IntegerLessThanNode extends CompareNode { +public final class IntegerLessThanNode extends CompareNode { + public static final NodeClass TYPE = NodeClass.create(IntegerLessThanNode.class); public IntegerLessThanNode(ValueNode x, ValueNode y) { - super(Condition.LT, false, x, y); + super(TYPE, Condition.LT, false, x, y); assert !x.getKind().isNumericFloat() && x.getKind() != Kind.Object; assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +24,18 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "%") -public class IntegerRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { +public final class IntegerRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(IntegerRemNode.class); public IntegerRemNode(ValueNode x, ValueNode y) { - super(IntegerStamp.OPS.getRem().foldStamp(x.stamp(), y.stamp()), x, y); + super(TYPE, IntegerStamp.OPS.getRem().foldStamp(x.stamp(), y.stamp()), x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -33,10 +35,11 @@ * both x and y. */ @NodeInfo -public class IntegerTestNode extends BinaryOpLogicNode { +public final class IntegerTestNode extends BinaryOpLogicNode implements BinaryCommutative { + public static final NodeClass TYPE = NodeClass.create(IntegerTestNode.class); public IntegerTestNode(ValueNode x, ValueNode y) { - super(x, y); + super(TYPE, x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -33,10 +34,12 @@ * An IsNullNode will be true if the supplied value is null, and false if it is non-null. */ @NodeInfo -public class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable { +public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable { + + public static final NodeClass TYPE = NodeClass.create(IsNullNode.class); public IsNullNode(ValueNode object) { - super(object); + super(TYPE, object); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.Shl; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -32,10 +33,12 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "<<") -public class LeftShiftNode extends ShiftNode { +public final class LeftShiftNode extends ShiftNode { + + public static final NodeClass TYPE = NodeClass.create(LeftShiftNode.class); public LeftShiftNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getShl, x, y); + super(TYPE, ArithmeticOpTable::getShl, x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +27,8 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Mul; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -34,10 +36,27 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "*") -public class MulNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { +public class MulNode extends BinaryArithmeticNode implements NarrowableArithmeticNode, BinaryCommutative { + + public static final NodeClass TYPE = NodeClass.create(MulNode.class); public MulNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getMul, x, y); + this(TYPE, x, y); + } + + protected MulNode(NodeClass c, ValueNode x, ValueNode y) { + super(c, ArithmeticOpTable::getMul, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getMul(); + Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + if (tryConstantFold != null) { + return tryConstantFold; + } else { + return new MulNode(x, y).maybeCommuteInputs(); + } } @Override @@ -59,33 +78,8 @@ if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getKind().isNumericInteger()) { long i = ((PrimitiveConstant) c).asLong(); - boolean signFlip = false; - if (i < 0) { - i = -i; - signFlip = true; - } - if (i > 0) { - ValueNode mulResult = null; - long bit1 = i & -i; - long bit2 = i - bit1; - bit2 = bit2 & -bit2; // Extract 2nd bit - if (CodeUtil.isPowerOf2(i)) { // - mulResult = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i))); - } else if (bit2 + bit1 == i) { // We can work with two shifts and add - ValueNode shift1 = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(bit1))); - ValueNode shift2 = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(bit2))); - mulResult = new AddNode(shift1, shift2); - } else if (CodeUtil.isPowerOf2(i + 1)) { // shift and subtract - ValueNode shift1 = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i + 1))); - mulResult = new SubNode(shift1, forX); - } - if (mulResult != null) { - if (signFlip) { - return new NegateNode(mulResult); - } else { - return mulResult; - } - } + if (i > 0 && CodeUtil.isPowerOf2(i)) { + return new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i))); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +23,10 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -37,13 +39,29 @@ @NodeInfo public final class NarrowNode extends IntegerConvertNode { + public static final NodeClass TYPE = NodeClass.create(NarrowNode.class); + public NarrowNode(ValueNode input, int resultBits) { this(input, PrimitiveStamp.getBits(input.stamp()), resultBits); assert 0 < resultBits && resultBits <= PrimitiveStamp.getBits(input.stamp()); } public NarrowNode(ValueNode input, int inputBits, int resultBits) { - super(ArithmeticOpTable::getNarrow, ArithmeticOpTable::getSignExtend, inputBits, resultBits, input); + super(TYPE, ArithmeticOpTable::getNarrow, ArithmeticOpTable::getSignExtend, inputBits, resultBits, input); + } + + public static ValueNode create(ValueNode input, int resultBits) { + return create(input, PrimitiveStamp.getBits(input.stamp()), resultBits); + } + + public static ValueNode create(ValueNode input, int inputBits, int resultBits) { + IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp()).getNarrow(); + ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp())); + if (synonym != null) { + return synonym; + } else { + return new NarrowNode(input, inputBits, resultBits); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Neg; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -36,8 +37,10 @@ @NodeInfo public final class NegateNode extends UnaryArithmeticNode implements NarrowableArithmeticNode { + public static final NodeClass TYPE = NodeClass.create(NegateNode.class); + public NegateNode(ValueNode value) { - super(ArithmeticOpTable::getNeg, value); + super(TYPE, ArithmeticOpTable::getNeg, value); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,7 +23,9 @@ package com.oracle.graal.nodes.calc; 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -35,15 +37,36 @@ * true. */ @NodeInfo -public class NormalizeCompareNode extends BinaryNode implements Lowerable { +public final class NormalizeCompareNode extends BinaryNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(NormalizeCompareNode.class); protected final boolean isUnorderedLess; public NormalizeCompareNode(ValueNode x, ValueNode y, boolean isUnorderedLess) { - super(StampFactory.forKind(Kind.Int), x, y); + super(TYPE, StampFactory.forKind(Kind.Int), x, y); this.isUnorderedLess = isUnorderedLess; } + public static ValueNode create(ValueNode x, ValueNode y, boolean isUnorderedLess, ConstantReflectionProvider constantReflection) { + LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false); + if (result instanceof LogicConstantNode) { + LogicConstantNode logicConstantNode = (LogicConstantNode) result; + LogicNode resultLT = CompareNode.tryConstantFold(Condition.LT, x, y, constantReflection, isUnorderedLess); + if (resultLT instanceof LogicConstantNode) { + LogicConstantNode logicConstantNodeLT = (LogicConstantNode) resultLT; + if (logicConstantNodeLT.getValue()) { + return ConstantNode.forInt(-1); + } else if (logicConstantNode.getValue()) { + return ConstantNode.forInt(0); + } else { + return ConstantNode.forInt(1); + } + } + } + + return new NormalizeCompareNode(x, y, isUnorderedLess); + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { // nothing to do @@ -56,10 +79,10 @@ LogicNode lessComp; if (getX().stamp() instanceof FloatStamp) { equalComp = graph().unique(FloatEqualsNode.create(getX(), getY(), tool.getConstantReflection())); - lessComp = graph().unique(new FloatLessThanNode(getX(), getY(), isUnorderedLess)); + lessComp = graph().unique(FloatLessThanNode.create(getX(), getY(), isUnorderedLess, tool.getConstantReflection())); } else { - equalComp = graph().unique(new IntegerEqualsNode(getX(), getY())); - lessComp = graph().unique(new IntegerLessThanNode(getX(), getY())); + equalComp = graph().unique(IntegerEqualsNode.create(getX(), getY(), tool.getConstantReflection())); + lessComp = graph().unique(IntegerLessThanNode.create(getX(), getY(), tool.getConstantReflection())); } ConditionalNode equalValue = graph().unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph()))); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Not; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -34,10 +35,12 @@ * Binary negation of long or integer values. */ @NodeInfo -public class NotNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { +public final class NotNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { + + public static final NodeClass TYPE = NodeClass.create(NotNode.class); public NotNode(ValueNode x) { - super(ArithmeticOpTable::getNot, x); + super(TYPE, ArithmeticOpTable::getNot, x); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,8 +34,10 @@ @NodeInfo(shortName = "==") public final class ObjectEqualsNode extends PointerEqualsNode implements Virtualizable { + public static final NodeClass TYPE = NodeClass.create(ObjectEqualsNode.class); + public ObjectEqualsNode(ValueNode x, ValueNode y) { - super(x, y); + super(TYPE, x, y); assert x.stamp() instanceof AbstractObjectStamp; assert y.stamp() instanceof AbstractObjectStamp; } @@ -89,7 +92,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 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Or; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -34,10 +37,23 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|") -public class OrNode extends BinaryArithmeticNode { +public final class OrNode extends BinaryArithmeticNode implements BinaryCommutative { + + public static final NodeClass TYPE = NodeClass.create(OrNode.class); public OrNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getOr, x, y); + super(TYPE, ArithmeticOpTable::getOr, x, y); + } + + public static ValueNode create(ValueNode x, ValueNode y) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getOr(); + Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + if (tryConstantFold != null) { + return tryConstantFold; + } else { + return new OrNode(x, y).maybeCommuteInputs(); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,16 +24,24 @@ 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.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") -public class PointerEqualsNode extends CompareNode { +public class PointerEqualsNode extends CompareNode implements BinaryCommutative { + + public static final NodeClass TYPE = NodeClass.create(PointerEqualsNode.class); public PointerEqualsNode(ValueNode x, ValueNode y) { - super(Condition.EQ, false, x, y); + this(TYPE, x, y); + } + + protected PointerEqualsNode(NodeClass c, ValueNode x, ValueNode y) { + super(c, Condition.EQ, false, x, y); assert x.stamp() instanceof AbstractPointerStamp; assert y.stamp() instanceof AbstractPointerStamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ 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.nodeinfo.*; @@ -38,14 +39,16 @@ * the old stamp. */ @NodeInfo -public class ReinterpretNode extends UnaryNode implements ArithmeticLIRLowerable { +public final class ReinterpretNode extends UnaryNode implements ArithmeticLIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(ReinterpretNode.class); public ReinterpretNode(Kind to, ValueNode value) { this(StampFactory.forKind(to), value); } public ReinterpretNode(Stamp to, ValueNode value) { - super(to, value); + super(TYPE, to, value); assert to instanceof ArithmeticStamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +24,19 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Rem; +import com.oracle.graal.graph.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "%") -public class RemNode extends BinaryArithmeticNode implements Lowerable { +public final class RemNode extends BinaryArithmeticNode implements Lowerable { + + public static final NodeClass TYPE = NodeClass.create(RemNode.class); public RemNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getRem, x, y); + super(TYPE, ArithmeticOpTable::getRem, x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.Shr; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -31,10 +32,12 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = ">>") -public class RightShiftNode extends ShiftNode { +public final class RightShiftNode extends ShiftNode { + + public static final NodeClass TYPE = NodeClass.create(RightShiftNode.class); public RightShiftNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getShr, x, y); + super(TYPE, ArithmeticOpTable::getShr, x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -39,6 +40,8 @@ @NodeInfo public abstract class ShiftNode extends BinaryNode implements ArithmeticLIRLowerable { + @SuppressWarnings("rawtypes") public static final NodeClass TYPE = NodeClass.create(ShiftNode.class); + protected interface SerializableShiftFunction extends Function>, Serializable { } @@ -50,8 +53,8 @@ * @param x the first input value * @param s the second input value */ - public ShiftNode(SerializableShiftFunction getOp, ValueNode x, ValueNode s) { - super(getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), (IntegerStamp) s.stamp()), x, s); + protected ShiftNode(NodeClass> c, SerializableShiftFunction getOp, ValueNode x, ValueNode s) { + super(c, getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), (IntegerStamp) s.stamp()), x, s); assert ((IntegerStamp) s.stamp()).getBits() == 32; this.getOp = getOp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +23,10 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -35,7 +37,9 @@ * The {@code SignExtendNode} converts an integer to a wider integer using sign extension. */ @NodeInfo -public class SignExtendNode extends IntegerConvertNode { +public final class SignExtendNode extends IntegerConvertNode { + + public static final NodeClass TYPE = NodeClass.create(SignExtendNode.class); public SignExtendNode(ValueNode input, int resultBits) { this(input, PrimitiveStamp.getBits(input.stamp()), resultBits); @@ -43,7 +47,21 @@ } public SignExtendNode(ValueNode input, int inputBits, int resultBits) { - super(ArithmeticOpTable::getSignExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); + super(TYPE, ArithmeticOpTable::getSignExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); + } + + public static ValueNode create(ValueNode input, int resultBits) { + return create(input, PrimitiveStamp.getBits(input.stamp()), resultBits); + } + + public static ValueNode create(ValueNode input, int inputBits, int resultBits) { + IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp()).getSignExtend(); + ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp())); + if (synonym != null) { + return synonym; + } else { + return new SignExtendNode(input, inputBits, resultBits); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Sqrt; +import com.oracle.graal.graph.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -33,10 +34,12 @@ * Square root. */ @NodeInfo -public class SqrtNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { +public final class SqrtNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { + + public static final NodeClass TYPE = NodeClass.create(SqrtNode.class); public SqrtNode(ValueNode x) { - super(ArithmeticOpTable::getSqrt, x); + super(TYPE, ArithmeticOpTable::getSqrt, x); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -36,8 +37,14 @@ @NodeInfo(shortName = "-") public class SubNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { + public static final NodeClass TYPE = NodeClass.create(SubNode.class); + public SubNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getSub, x, y); + this(TYPE, x, y); + } + + protected SubNode(NodeClass c, ValueNode x, ValueNode y) { + super(c, ArithmeticOpTable::getSub, x, y); } public static ValueNode create(ValueNode x, ValueNode y) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +27,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -35,13 +36,15 @@ @NodeInfo public abstract class UnaryArithmeticNode extends UnaryNode implements ArithmeticLIRLowerable { + @SuppressWarnings("rawtypes") public static final NodeClass TYPE = NodeClass.create(UnaryArithmeticNode.class); + protected interface SerializableUnaryFunction extends Function>, Serializable { } protected final SerializableUnaryFunction getOp; - protected UnaryArithmeticNode(SerializableUnaryFunction getOp, ValueNode value) { - super(getOp.apply(ArithmeticOpTable.forStamp(value.stamp())).foldStamp(value.stamp()), value); + protected UnaryArithmeticNode(NodeClass> c, SerializableUnaryFunction getOp, ValueNode value) { + super(c, getOp.apply(ArithmeticOpTable.forStamp(value.stamp())).foldStamp(value.stamp()), value); this.getOp = getOp; } @@ -56,9 +59,17 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (forValue.isConstant()) { - return ConstantNode.forPrimitive(stamp(), getOp(forValue).foldConstant(forValue.asConstant())); + ValueNode synonym = findSynonym(forValue, getOp(forValue)); + if (synonym != null) { + return synonym; } return this; } + + protected static ValueNode findSynonym(ValueNode forValue, UnaryOp op) { + if (forValue.isConstant()) { + return ConstantNode.forPrimitive(op.foldStamp(forValue.stamp()), op.foldConstant(forValue.asConstant())); + } + return null; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,6 +35,7 @@ @NodeInfo public abstract class UnaryNode extends FloatingNode implements Canonicalizable.Unary { + public static final NodeClass TYPE = NodeClass.create(UnaryNode.class); @Input protected ValueNode value; public ValueNode getValue() { @@ -46,8 +48,8 @@ * @param stamp the result type of this instruction * @param value the input instruction */ - public UnaryNode(Stamp stamp, ValueNode value) { - super(stamp); + protected UnaryNode(NodeClass c, Stamp stamp, ValueNode value) { + super(c, stamp); this.value = value; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +24,19 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|/|") -public class UnsignedDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { +public final class UnsignedDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(UnsignedDivNode.class); public UnsignedDivNode(ValueNode x, ValueNode y) { - super(x.stamp().unrestricted(), x, y); + super(TYPE, x.stamp().unrestricted(), x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,16 +24,19 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|%|") -public class UnsignedRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { +public final class UnsignedRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(UnsignedRemNode.class); public UnsignedRemNode(ValueNode x, ValueNode y) { - super(x.stamp().unrestricted(), x, y); + super(TYPE, x.stamp().unrestricted(), x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.UShr; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -32,10 +33,12 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = ">>>") -public class UnsignedRightShiftNode extends ShiftNode { +public final class UnsignedRightShiftNode extends ShiftNode { + + public static final NodeClass TYPE = NodeClass.create(UnsignedRightShiftNode.class); public UnsignedRightShiftNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getUShr, x, y); + super(TYPE, ArithmeticOpTable::getUShr, x, y); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Xor; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -34,13 +37,26 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "^") -public class XorNode extends BinaryArithmeticNode { +public final class XorNode extends BinaryArithmeticNode implements BinaryCommutative { + + public static final NodeClass TYPE = NodeClass.create(XorNode.class); public XorNode(ValueNode x, ValueNode y) { - super(ArithmeticOpTable::getXor, x, y); + super(TYPE, ArithmeticOpTable::getXor, x, y); assert x.stamp().isCompatible(y.stamp()); } + public static ValueNode create(ValueNode x, ValueNode y) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getXor(); + Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + if (tryConstantFold != null) { + return tryConstantFold; + } else { + return new XorNode(x, y).maybeCommuteInputs(); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { ValueNode ret = super.canonical(tool, forX, forY); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +25,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; -import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -37,7 +38,9 @@ * The {@code ZeroExtendNode} converts an integer to a wider integer using zero extension. */ @NodeInfo -public class ZeroExtendNode extends IntegerConvertNode { +public final class ZeroExtendNode extends IntegerConvertNode { + + public static final NodeClass TYPE = NodeClass.create(ZeroExtendNode.class); public ZeroExtendNode(ValueNode input, int resultBits) { this(input, PrimitiveStamp.getBits(input.stamp()), resultBits); @@ -45,7 +48,21 @@ } public ZeroExtendNode(ValueNode input, int inputBits, int resultBits) { - super(ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); + super(TYPE, ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); + } + + public static ValueNode create(ValueNode input, int resultBits) { + return create(input, PrimitiveStamp.getBits(input.stamp()), resultBits); + } + + public static ValueNode create(ValueNode input, int inputBits, int resultBits) { + IntegerConvertOp signExtend = ArithmeticOpTable.forStamp(input.stamp()).getZeroExtend(); + ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp())); + if (synonym != null) { + return synonym; + } else { + return new ZeroExtendNode(input, inputBits, resultBits); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,6 +30,7 @@ public final class Block extends AbstractBlockBase { + public static final int DISTANCED_DOMINATOR_CACHE = 5; protected final AbstractBeginNode beginNode; protected FixedNode endNode; @@ -38,6 +39,7 @@ protected Loop loop; protected Block postdominator; + protected Block distancedDominatorCache; protected Block(AbstractBeginNode node) { this.beginNode = node; @@ -51,6 +53,7 @@ return endNode; } + @Override public Loop getLoop() { return loop; } @@ -59,18 +62,22 @@ this.loop = loop; } + @Override public int getLoopDepth() { return loop == null ? 0 : loop.getDepth(); } + @Override public boolean isLoopHeader() { return getBeginNode() instanceof LoopBeginNode; } + @Override public boolean isLoopEnd() { return getEndNode() instanceof LoopEndNode; } + @Override public boolean isExceptionEntry() { Node predecessor = getBeginNode().predecessor(); return predecessor != null && predecessor instanceof InvokeWithExceptionNode && getBeginNode() == ((InvokeWithExceptionNode) predecessor).exceptionEdge(); @@ -97,6 +104,7 @@ return b; } + @Override public Block getPostdominator() { return postdominator; } @@ -159,6 +167,7 @@ return "B" + id; } + @Override public double probability() { return probability; } @@ -167,4 +176,31 @@ assert probability >= 0 && Double.isFinite(probability); this.probability = probability; } + + public Block getDistancedDominatorCache() { + Block result = this.distancedDominatorCache; + if (result == null) { + Block current = this; + for (int i = 0; i < DISTANCED_DOMINATOR_CACHE; ++i) { + current = current.getDominator(); + } + distancedDominatorCache = current; + return current; + } else { + return result; + } + } + + @Override + public Block getDominator(int distance) { + Block result = this; + int i = 0; + for (; i < distance - (DISTANCED_DOMINATOR_CACHE - 1); i += DISTANCED_DOMINATOR_CACHE) { + result = result.getDistancedDominatorCache(); + } + for (; i < distance; ++i) { + result = result.getDominator(); + } + return result; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Mon Mar 02 19:11:22 2015 +0100 @@ -156,7 +156,7 @@ private void identifyBlocks() { // Find all block headers int numBlocks = 0; - for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) { + for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.TYPE)) { Block block = new Block(begin); numBlocks++; identifyBlock(block); @@ -173,6 +173,7 @@ // First time we see this block: push all successors. for (Node suxNode : block.getEndNode().cfgSuccessors()) { Block suxBlock = blockFor(suxNode); + assert suxBlock != null : suxNode; if (suxBlock.getId() == BLOCK_ID_INITIAL) { stack.add(suxBlock); } @@ -200,14 +201,19 @@ } // Connect blocks (including loop backward edges), but ignoring dead code (blocks with id < 0). + // Predecessors need to be in the order expected when iterating phi inputs. private void connectBlocks() { for (Block block : reversePostOrder) { - List predecessors = new ArrayList<>(4); + List predecessors = new ArrayList<>(1); double probability = block.getBeginNode() instanceof StartNode ? 1D : 0D; for (Node predNode : block.getBeginNode().cfgPredecessors()) { Block predBlock = nodeToBlock.get(predNode); if (predBlock.getId() >= 0) { predecessors.add(predBlock); + if (predBlock.getSuccessors() == null) { + predBlock.setSuccessors(new ArrayList<>(1)); + } + predBlock.getSuccessors().add(block); probability += predBlock.probability; } } @@ -222,6 +228,10 @@ assert predBlock != null : predNode; if (predBlock.getId() >= 0) { predecessors.add(predBlock); + if (predBlock.getSuccessors() == null) { + predBlock.setSuccessors(new ArrayList<>(1)); + } + predBlock.getSuccessors().add(block); } } } @@ -230,19 +240,9 @@ } block.setPredecessors(predecessors); block.setProbability(probability); - - List successors = new ArrayList<>(4); - for (Node suxNode : block.getEndNode().cfgSuccessors()) { - Block suxBlock = nodeToBlock.get(suxNode); - assert suxBlock.getId() >= 0; - successors.add(suxBlock); + if (block.getSuccessors() == null) { + block.setSuccessors(new ArrayList<>(1)); } - if (block.getEndNode() instanceof LoopEndNode) { - Block suxBlock = nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin()); - assert suxBlock.getId() >= 0; - successors.add(suxBlock); - } - block.setSuccessors(successors); } } @@ -266,29 +266,30 @@ computeLoopBlocks(exitBlock.getFirstPredecessor(), loop); loop.getExits().add(exitBlock); } - List unexpected = new LinkedList<>(); - for (Block b : loop.getBlocks()) { + + // The following loop can add new blocks to the end of the loop's block list. + int size = loop.getBlocks().size(); + for (int i = 0; i < size; ++i) { + Block b = loop.getBlocks().get(i); for (Block sux : b.getSuccessors()) { if (sux.loop != loop) { AbstractBeginNode begin = sux.getBeginNode(); if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) { Debug.log(3, "Unexpected loop exit with %s, including whole branch in the loop", sux); - unexpected.add(sux); + addBranchToLoop(loop, sux); } } } } - for (Block b : unexpected) { - addBranchToLoop(loop, b); - } } } } private static void addBranchToLoop(Loop l, Block b) { - if (l.getBlocks().contains(b)) { + if (b.loop == l) { return; } + assert !(l.getBlocks().contains(b)); l.getBlocks().add(b); b.loop = l; for (Block sux : b.getSuccessors()) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/BlackholeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/BlackholeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/BlackholeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.debug; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -30,10 +31,11 @@ @NodeInfo public final class BlackholeNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(BlackholeNode.class); @Input ValueNode value; public BlackholeNode(ValueNode value) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,7 +33,9 @@ * control flow anchors. */ @NodeInfo -public class ControlFlowAnchorNode extends FixedWithNextNode implements LIRLowerable { +public final class ControlFlowAnchorNode extends FixedWithNextNode implements LIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(ControlFlowAnchorNode.class); private static class Unique { } @@ -41,7 +43,7 @@ protected Unique unique; public ControlFlowAnchorNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.unique = new Unique(); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.debug; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -38,6 +39,7 @@ @NodeInfo public class DynamicCounterNode extends FixedWithNextNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(DynamicCounterNode.class); @Input ValueNode increment; protected final String name; @@ -45,7 +47,11 @@ protected final boolean withContext; public DynamicCounterNode(String name, String group, ValueNode increment, boolean withContext) { - super(StampFactory.forVoid()); + this(TYPE, name, group, increment, withContext); + } + + protected DynamicCounterNode(NodeClass c, String name, String group, ValueNode increment, boolean withContext) { + super(c, StampFactory.forVoid()); this.name = name; this.group = group; this.increment = increment; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/OpaqueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/OpaqueNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/OpaqueNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,18 +22,20 @@ */ package com.oracle.graal.nodes.debug; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class OpaqueNode extends FloatingNode implements LIRLowerable { +public final class OpaqueNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(OpaqueNode.class); @Input ValueNode value; public OpaqueNode(ValueNode value) { - super(value.stamp().unrestricted()); + super(TYPE, value.stamp().unrestricted()); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/VerifyHeapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/VerifyHeapNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/VerifyHeapNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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.nodes.debug; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,10 +33,12 @@ * heap corruption issues. */ @NodeInfo -public class VerifyHeapNode extends FixedWithNextNode implements Lowerable { +public final class VerifyHeapNode extends FixedWithNextNode implements Lowerable { + + public static final NodeClass TYPE = NodeClass.create(VerifyHeapNode.class); public VerifyHeapNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ */ package com.oracle.graal.nodes.debug; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,12 +35,13 @@ * actually executed. */ @NodeInfo -public class WeakCounterNode extends DynamicCounterNode implements Simplifiable, Virtualizable { +public final class WeakCounterNode extends DynamicCounterNode implements Simplifiable, Virtualizable { + public static final NodeClass TYPE = NodeClass.create(WeakCounterNode.class); @Input ValueNode checkedValue; public WeakCounterNode(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) { - super(group, name, increment, addContext); + super(TYPE, group, name, increment, addContext); this.checkedValue = checkedValue; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,6 +31,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(AbstractWriteNode.class); @Input ValueNode value; @OptionalInput(InputType.State) FrameState stateAfter; @OptionalInput(InputType.Memory) Node lastLocationAccess; @@ -64,18 +65,18 @@ return initialization; } - public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) { - this(object, value, location, barrierType, false); + protected AbstractWriteNode(NodeClass c, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) { + this(c, object, value, location, barrierType, false); } - public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) { - super(object, location, StampFactory.forVoid(), barrierType); + protected AbstractWriteNode(NodeClass c, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) { + super(c, object, location, StampFactory.forVoid(), barrierType); this.value = value; this.initialization = initialization; } - public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { - super(object, location, StampFactory.forVoid(), guard, barrierType, false, null); + protected AbstractWriteNode(NodeClass c, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { + super(c, object, location, StampFactory.forVoid(), guard, barrierType, false, null); this.value = value; this.initialization = initialization; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; @@ -38,6 +39,7 @@ @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}") public final class AddLocationNode extends LocationNode implements Canonicalizable.Binary { + public static final NodeClass TYPE = NodeClass.create(AddLocationNode.class); @Input(InputType.Association) ValueNode x; @Input(InputType.Association) ValueNode y; @@ -50,7 +52,7 @@ } public AddLocationNode(LocationNode x, LocationNode y) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); assert x.getLocationIdentity().equals(y.getLocationIdentity()); this.x = x; this.y = y; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -32,8 +33,10 @@ @NodeInfo public abstract class ArrayRangeWriteNode extends AbstractMemoryCheckpoint { - protected ArrayRangeWriteNode(Stamp stamp) { - super(stamp); + public static final NodeClass TYPE = NodeClass.create(ArrayRangeWriteNode.class); + + protected ArrayRangeWriteNode(NodeClass c, Stamp stamp) { + super(c, stamp); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -42,10 +43,11 @@ @NodeInfo public final class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable { + public static final NodeClass TYPE = NodeClass.create(BoxNode.class); protected final Kind boxingKind; public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) { - super(StampFactory.exactNonNull(resultType), value); + super(TYPE, StampFactory.exactNonNull(resultType), value); this.boxingKind = boxingKind; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -38,6 +39,7 @@ @NodeInfo public final class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable { + public static final NodeClass TYPE = NodeClass.create(BranchProbabilityNode.class); public static final double LIKELY_PROBABILITY = 0.6; public static final double NOT_LIKELY_PROBABILITY = 1 - LIKELY_PROBABILITY; @@ -54,7 +56,7 @@ @Input ValueNode condition; public BranchProbabilityNode(ValueNode probability, ValueNode condition) { - super(condition.stamp()); + super(TYPE, condition.stamp()); this.probability = probability; this.condition = condition; } @@ -98,12 +100,17 @@ couldSet = true; ifNodeUsages.setTrueSuccessorProbability(probabilityToSet); } + + if (!couldSet && node.usages().filter(FixedGuardNode.class).isNotEmpty()) { + couldSet = true; + } } } } if (couldSet) { - replaceAndDelete(condition); - tool.addToWorkList(condition.usages()); + ValueNode currentCondition = condition; + replaceAndDelete(currentCondition); + tool.addToWorkList(currentCondition.usages()); } else { if (!isSubstitutionGraph()) { throw new GraalInternalError("Wrong usage of branch probability injection!"); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,11 +36,12 @@ @NodeInfo public final class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(BytecodeExceptionNode.class); protected final Class exceptionClass; @Input NodeInputList arguments; public BytecodeExceptionNode(MetaAccessProvider metaAccess, Class exceptionClass, ValueNode... arguments) { - super(StampFactory.exactNonNull(metaAccess.lookupJavaType(exceptionClass))); + super(TYPE, StampFactory.exactNonNull(metaAccess.lookupJavaType(exceptionClass))); this.exceptionClass = exceptionClass; this.arguments = new NodeInputList<>(this, arguments); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -32,6 +33,7 @@ @NodeInfo public final class ComputeAddressNode extends FloatingNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(ComputeAddressNode.class); @Input ValueNode object; @Input(InputType.Association) ValueNode location; @@ -44,7 +46,7 @@ } public ComputeAddressNode(ValueNode object, ValueNode location, Stamp stamp) { - super(stamp); + super(TYPE, stamp); this.object = object; this.location = location; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.spi.*; @@ -35,11 +36,12 @@ @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") public final class ConstantLocationNode extends LocationNode { + public static final NodeClass TYPE = NodeClass.create(ConstantLocationNode.class); protected final LocationIdentity locationIdentity; protected final long displacement; public ConstantLocationNode(LocationIdentity identity, long displacement) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.locationIdentity = identity; this.displacement = displacement; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -32,6 +33,7 @@ */ @NodeInfo public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access { + public static final NodeClass TYPE = NodeClass.create(FixedAccessNode.class); @OptionalInput(InputType.Guard) protected GuardingNode guard; @Input protected ValueNode object; @@ -64,16 +66,17 @@ this.nullCheck = check; } - public FixedAccessNode(ValueNode object, ValueNode location, Stamp stamp) { - this(object, location, stamp, BarrierType.NONE); + protected FixedAccessNode(NodeClass c, ValueNode object, ValueNode location, Stamp stamp) { + this(c, object, location, stamp, BarrierType.NONE); } - public FixedAccessNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { - this(object, location, stamp, null, barrierType, false, null); + protected FixedAccessNode(NodeClass c, ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { + this(c, object, location, stamp, null, barrierType, false, null); } - public FixedAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { - super(stamp, stateBefore); + protected FixedAccessNode(NodeClass c, ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, + FrameState stateBefore) { + super(c, stamp, stateBefore); this.object = object; this.location = location; this.guard = guard; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,12 +23,14 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(FixedValueAnchorNode.class); @Input ValueNode object; @@ -37,7 +39,7 @@ } public FixedValueAnchorNode(ValueNode object) { - super(StampFactory.forNodeIntrinsic()); + super(TYPE, StampFactory.forNodeIntrinsic()); this.object = object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -32,17 +33,19 @@ */ @NodeInfo public abstract class FloatableAccessNode extends FixedAccessNode { + public static final NodeClass TYPE = NodeClass.create(FloatableAccessNode.class); - public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp) { - super(object, location, stamp); + protected FloatableAccessNode(NodeClass c, ValueNode object, ValueNode location, Stamp stamp) { + super(c, object, location, stamp); } - public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { - super(object, location, stamp, guard, barrierType, false, null); + protected FloatableAccessNode(NodeClass c, ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { + super(c, object, location, stamp, guard, barrierType, false, null); } - public FloatableAccessNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, FrameState stateBefore) { - super(object, location, stamp, guard, barrierType, nullCheck, stateBefore); + protected FloatableAccessNode(NodeClass c, ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck, + FrameState stateBefore) { + super(c, object, location, stamp, guard, barrierType, nullCheck, stateBefore); } public abstract FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,11 +24,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess { + public static final NodeClass TYPE = NodeClass.create(FloatingAccessNode.class); @Input ValueNode object; @Input(InputType.Association) LocationNode location; @@ -50,14 +52,14 @@ return location.getLocationIdentity(); } - public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp) { - super(stamp); + protected FloatingAccessNode(NodeClass c, ValueNode object, LocationNode location, Stamp stamp) { + super(c, stamp); this.object = object; this.location = location; } - public FloatingAccessNode(ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { - super(stamp, guard); + protected FloatingAccessNode(NodeClass c, ValueNode object, LocationNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { + super(c, stamp, guard); this.object = object; this.location = location; this.barrierType = barrierType; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,7 +35,8 @@ * relative location. This node does not null check the object. */ @NodeInfo -public class FloatingReadNode extends FloatingAccessNode implements LIRLowerable, Canonicalizable { +public final class FloatingReadNode extends FloatingAccessNode implements LIRLowerable, Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(FloatingReadNode.class); @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess; @@ -48,7 +49,7 @@ } public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType) { - super(object, location, stamp, guard, barrierType); + super(TYPE, object, location, stamp, guard, barrierType); this.lastLocationAccess = lastLocationAccess; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,6 +37,7 @@ */ @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}", allowedUsageTypes = {InputType.Memory}) public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode.DeoptDuring, MemoryCheckpoint.Multi { + public static final NodeClass TYPE = NodeClass.create(ForeignCallNode.class); @Input protected NodeInputList arguments; @OptionalInput(InputType.State) protected FrameState stateDuring; @@ -46,7 +47,7 @@ protected int bci = BytecodeFrame.UNKNOWN_BCI; public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { - super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); + super(TYPE, StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls; @@ -57,14 +58,21 @@ } public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List arguments) { - super(stamp); + super(TYPE, stamp); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls; } + protected ForeignCallNode(NodeClass c, ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { + super(c, stamp); + this.arguments = new NodeInputList<>(this); + this.descriptor = descriptor; + this.foreignCalls = foreignCalls; + } + public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { - super(stamp); + super(TYPE, stamp); this.arguments = new NodeInputList<>(this); this.descriptor = descriptor; this.foreignCalls = foreignCalls; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,7 +38,8 @@ * constants. */ @NodeInfo(nameTemplate = "IdxLoc {p#locationIdentity/s}") -public class IndexedLocationNode extends LocationNode implements Canonicalizable { +public final class IndexedLocationNode extends LocationNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(IndexedLocationNode.class); protected final LocationIdentity locationIdentity; protected final long displacement; @@ -64,7 +65,7 @@ } public IndexedLocationNode(LocationIdentity identity, long displacement, ValueNode index, int indexScaling) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); assert index != null; assert indexScaling != 0; this.locationIdentity = identity; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -37,12 +38,13 @@ * values. The actual implementation of the switch will be decided by the backend. */ @NodeInfo -public class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { +public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { + public static final NodeClass TYPE = NodeClass.create(IntegerSwitchNode.class); protected final int[] keys; public IntegerSwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { - super(value, successors, keySuccessors, keyProbabilities); + super(TYPE, value, successors, keySuccessors, keyProbabilities); assert keySuccessors.length == keys.length + 1; assert keySuccessors.length == keyProbabilities.length; this.keys = keys; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,13 +35,14 @@ * barriers, implicit conversions and optionally oop uncompression. */ @NodeInfo -public class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode, Canonicalizable { +public final class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode, Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(JavaReadNode.class); protected final Kind readKind; protected final boolean compressible; public JavaReadNode(Kind readKind, ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) { - super(object, location, StampFactory.forKind(readKind), barrierType); + super(TYPE, object, location, StampFactory.forKind(readKind), barrierType); this.readKind = readKind; this.compressible = compressible; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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.nodes.extended; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,13 +33,14 @@ * write barriers, implicit conversions and optionally oop compression. */ @NodeInfo -public class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single { +public final class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(JavaWriteNode.class); protected final Kind writeKind; protected final boolean compressible; public JavaWriteNode(Kind writeKind, ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { - super(object, value, location, barrierType, initialization); + super(TYPE, object, value, location, barrierType, initialization); this.writeKind = writeKind; this.compressible = compressible; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -35,6 +36,7 @@ @NodeInfo public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable { + public static final NodeClass TYPE = NodeClass.create(LoadHubNode.class); @Input ValueNode value; public ValueNode getValue() { @@ -51,7 +53,7 @@ } public LoadHubNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode value, ValueNode guard) { - super(hubStamp(stampProvider, value), (GuardingNode) guard); + super(TYPE, hubStamp(stampProvider, value), (GuardingNode) guard); assert value != guard; this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +36,9 @@ * Loads a method from the virtual method table of a given hub. */ @NodeInfo -public class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable { +public final class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(LoadMethodNode.class); @Input ValueNode hub; protected final ResolvedJavaMethod method; protected final ResolvedJavaType receiverType; @@ -47,7 +48,7 @@ } public LoadMethodNode(@InjectedNodeParameter Stamp stamp, ResolvedJavaMethod method, ResolvedJavaType receiverType, ValueNode hub) { - super(stamp); + super(TYPE, stamp); this.receiverType = receiverType; this.hub = hub; this.method = method; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -38,14 +39,16 @@ @NodeInfo(allowedUsageTypes = {InputType.Association}) public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { + public static final NodeClass TYPE = NodeClass.create(LocationNode.class); + /** * Marker interface for locations in snippets. */ public interface Location { } - protected LocationNode(Stamp stamp) { - super(stamp); + protected LocationNode(NodeClass c, Stamp stamp) { + super(c, stamp); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -39,12 +40,13 @@ * Creates a memory barrier. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class MembarNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { +public final class MembarNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(MembarNode.class); protected final int barriers; public MembarNode(int barriers) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.barriers = barriers; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,14 +32,10 @@ LocationIdentity getLocationIdentity(); - default MemoryNode getLastLocationAccess() { - return null; - } + MemoryNode getLastLocationAccess(); /** * @param lla the {@link MemoryNode} that represents the last kill of the location */ - default void setLastLocationAccess(MemoryNode lla) { - // empty - } + void setLastLocationAccess(MemoryNode lla); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,17 +23,19 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(allowedUsageTypes = {InputType.Guard}) -public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, GuardingNode { +public final class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(NullCheckNode.class); @Input ValueNode object; public NullCheckNode(ValueNode object) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.object = object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +28,12 @@ import com.oracle.graal.nodes.*; @NodeInfo(nameTemplate = "OSRLocal({p#index})") -public class OSRLocalNode extends AbstractLocalNode implements IterableNodeType { +public final class OSRLocalNode extends AbstractLocalNode implements IterableNodeType { + + public static final NodeClass TYPE = NodeClass.create(OSRLocalNode.class); public OSRLocalNode(int index, Stamp stamp) { - super(index, stamp); + super(TYPE, index, stamp); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,14 +22,18 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class OSRStartNode extends StartNode implements Lowerable { +public final class OSRStartNode extends StartNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(OSRStartNode.class); + public OSRStartNode() { + super(TYPE); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,18 +37,20 @@ * Reads an {@linkplain FixedAccessNode accessed} value. */ @NodeInfo -public class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode { +public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode { + + public static final NodeClass TYPE = NodeClass.create(ReadNode.class); public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType) { - super(object, location, stamp, null, barrierType); + super(TYPE, object, location, stamp, null, barrierType); } public ReadNode(ValueNode object, ValueNode location, Stamp stamp, GuardingNode guard, BarrierType barrierType) { - super(object, location, stamp, guard, barrierType); + super(TYPE, 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); + super(TYPE, object, location, stamp, guard, barrierType, nullCheck, stateBefore); } public ReadNode(ValueNode object, ValueNode location, ValueNode guard, BarrierType barrierType) { @@ -57,7 +59,7 @@ * location is a parameter, i.e., a ParameterNode, the constructor cannot use the declared * type LocationNode. */ - super(object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, barrierType); + super(TYPE, object, location, StampFactory.forNodeIntrinsic(), (GuardingNode) guard, barrierType); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,13 +23,15 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class StoreHubNode extends FixedWithNextNode implements Lowerable { +public final class StoreHubNode extends FixedWithNextNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(StoreHubNode.class); @Input ValueNode value; @Input ValueNode object; @@ -42,7 +44,7 @@ } public StoreHubNode(ValueNode object, ValueNode value) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.value = value; this.object = object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +37,7 @@ @NodeInfo public abstract class SwitchNode extends ControlSplitNode { + public static final NodeClass TYPE = NodeClass.create(SwitchNode.class); @Successor protected NodeSuccessorList successors; @Input protected ValueNode value; @@ -50,8 +51,8 @@ * @param value the instruction that provides the value to be switched over * @param successors the list of successors of this switch */ - public SwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) { - super(StampFactory.forVoid()); + protected SwitchNode(NodeClass c, ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) { + super(c, StampFactory.forVoid()); assert value.stamp().getStackKind().isNumericInteger() || value.stamp() instanceof AbstractPointerStamp : value.stamp() + " key not supported by SwitchNode"; assert keySuccessors.length == keyProbabilities.length; this.successors = new NodeSuccessorList<>(this, successors); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -33,10 +34,11 @@ @NodeInfo public final class UnboxNode extends UnaryNode implements Virtualizable, Lowerable { + public static final NodeClass TYPE = NodeClass.create(UnboxNode.class); protected final Kind boxingKind; protected UnboxNode(ValueNode value, Kind boxingKind) { - super(StampFactory.forKind(boxingKind.getStackKind()), value); + super(TYPE, StampFactory.forKind(boxingKind.getStackKind()), value); this.boxingKind = boxingKind; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,13 +33,14 @@ @NodeInfo public abstract class UnsafeAccessNode extends FixedWithNextNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(UnsafeAccessNode.class); @Input ValueNode object; @Input ValueNode offset; protected final Kind accessKind; protected final LocationIdentity locationIdentity; - public UnsafeAccessNode(Stamp stamp, ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) { - super(stamp); + protected UnsafeAccessNode(NodeClass c, Stamp stamp, ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) { + super(c, stamp); assert accessKind != null; this.object = object; this.offset = offset; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,17 +38,18 @@ * than the type this nodes casts to. */ @NodeInfo -public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { +public final class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(UnsafeCastNode.class); @Input ValueNode object; public UnsafeCastNode(ValueNode object, Stamp stamp) { - super(stamp); + super(TYPE, stamp); this.object = object; } public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) { - super(stamp, (GuardingNode) anchor); + super(TYPE, stamp, (GuardingNode) anchor); this.object = object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -36,7 +37,8 @@ * performed before the load. */ @NodeInfo -public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable { +public final class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable { + public static final NodeClass TYPE = NodeClass.create(UnsafeLoadNode.class); @OptionalInput(InputType.Condition) LogicNode guardingCondition; public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) { @@ -44,7 +46,7 @@ } public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity, LogicNode condition) { - super(StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity); + super(TYPE, StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity); this.guardingCondition = condition; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -36,8 +37,9 @@ * performed before the store. */ @NodeInfo -public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single { +public final class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(UnsafeStoreNode.class); @Input ValueNode value; @OptionalInput(InputType.State) FrameState stateAfter; @@ -46,7 +48,7 @@ } public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity, FrameState stateAfter) { - super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity); + super(TYPE, StampFactory.forVoid(), object, offset, accessKind, locationIdentity); this.value = value; this.stateAfter = stateAfter; assert accessKind != Kind.Void && accessKind != Kind.Illegal; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.nodes.extended; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,12 +35,13 @@ * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph. */ @NodeInfo(allowedUsageTypes = {InputType.Anchor, InputType.Guard}) -public class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode { +public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(ValueAnchorNode.class); @OptionalInput(InputType.Guard) ValueNode anchored; public ValueAnchorNode(ValueNode value) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.anchored = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,18 +35,20 @@ * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}. */ @NodeInfo -public class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable { +public final class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable { + + public static final NodeClass TYPE = NodeClass.create(WriteNode.class); public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType) { - super(object, value, location, barrierType); + super(TYPE, object, value, location, barrierType); } public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean initialization) { - super(object, value, location, barrierType, initialization); + super(TYPE, object, value, location, barrierType, initialization); } public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { - super(object, value, location, barrierType, guard, initialization); + super(TYPE, object, value, location, barrierType, guard, initialization); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,6 +35,7 @@ @NodeInfo public abstract class AbstractNewArrayNode extends AbstractNewObjectNode implements ArrayLengthProvider { + public static final NodeClass TYPE = NodeClass.create(AbstractNewArrayNode.class); @Input protected ValueNode length; @Override @@ -41,8 +43,8 @@ return length; } - public AbstractNewArrayNode(Stamp stamp, ValueNode length, boolean fillContents) { - super(stamp, fillContents); + public AbstractNewArrayNode(NodeClass c, Stamp stamp, ValueNode length, boolean fillContents) { + super(c, stamp, fillContents); this.length = length; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,10 +38,11 @@ @NodeInfo public abstract class AbstractNewObjectNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable { + public static final NodeClass TYPE = NodeClass.create(AbstractNewObjectNode.class); protected final boolean fillContents; - public AbstractNewObjectNode(Stamp stamp, boolean fillContents) { - super(stamp); + public AbstractNewObjectNode(NodeClass c, Stamp stamp, boolean fillContents) { + super(c, stamp); this.fillContents = fillContents; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -32,6 +33,7 @@ @NodeInfo public abstract class AccessArrayNode extends FixedWithNextNode { + public static final NodeClass TYPE = NodeClass.create(AccessArrayNode.class); @Input protected ValueNode array; public ValueNode array() { @@ -43,8 +45,8 @@ * * @param array the instruction that produces the array object value */ - public AccessArrayNode(Stamp stamp, ValueNode array) { - super(stamp); + public AccessArrayNode(NodeClass c, Stamp stamp, ValueNode array) { + super(c, stamp); this.array = array; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,6 +35,7 @@ @NodeInfo public abstract class AccessFieldNode extends FixedWithNextNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(AccessFieldNode.class); @OptionalInput ValueNode object; protected final ResolvedJavaField field; @@ -48,8 +50,8 @@ * @param object the instruction producing the receiver object * @param field the compiler interface representation of the field */ - public AccessFieldNode(Stamp stamp, ValueNode object, ResolvedJavaField field) { - super(stamp); + public AccessFieldNode(NodeClass c, Stamp stamp, ValueNode object, ResolvedJavaField field) { + super(c, stamp); this.object = object; this.field = field; assert field.getDeclaringClass().isInitialized(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,6 +36,7 @@ @NodeInfo public abstract class AccessIndexedNode extends AccessArrayNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(AccessIndexedNode.class); @Input protected ValueNode index; protected final Kind elementKind; @@ -50,8 +52,8 @@ * @param index the instruction producing the index * @param elementKind the kind of the elements of the array */ - protected AccessIndexedNode(Stamp stamp, ValueNode array, ValueNode index, Kind elementKind) { - super(stamp, array); + protected AccessIndexedNode(NodeClass c, Stamp stamp, ValueNode array, ValueNode index, Kind elementKind) { + super(c, stamp, array); this.index = index; this.elementKind = elementKind; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -37,6 +38,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode.DeoptBefore, DeoptimizingNode.DeoptAfter { + public static final NodeClass TYPE = NodeClass.create(AccessMonitorNode.class); @OptionalInput(InputType.State) FrameState stateBefore; @Input ValueNode object; @Input(InputType.Association) MonitorIdNode monitorId; @@ -69,8 +71,8 @@ * * @param object the instruction producing the object */ - public AccessMonitorNode(ValueNode object, MonitorIdNode monitorId) { - super(StampFactory.forVoid()); + protected AccessMonitorNode(NodeClass c, ValueNode object, MonitorIdNode monitorId) { + super(c, StampFactory.forVoid()); this.object = object; this.monitorId = monitorId; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,6 +37,7 @@ @NodeInfo public final class ArrayLengthNode extends FixedWithNextNode implements Canonicalizable.Unary, Lowerable, Virtualizable { + public static final NodeClass TYPE = NodeClass.create(ArrayLengthNode.class); @Input ValueNode array; public ValueNode array() { @@ -47,7 +49,7 @@ } public ArrayLengthNode(ValueNode array) { - super(StampFactory.positiveInt()); + super(TYPE, StampFactory.positiveInt()); this.array = array; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -38,6 +39,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public final class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(AtomicReadAndAddNode.class); @Input ValueNode object; @Input ValueNode offset; @Input ValueNode delta; @@ -45,7 +47,7 @@ protected final LocationIdentity locationIdentity; public AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) { - super(StampFactory.forKind(delta.getKind())); + super(TYPE, StampFactory.forKind(delta.getKind())); this.object = object; this.offset = offset; this.delta = delta; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -39,6 +40,7 @@ @NodeInfo public final class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(AtomicReadAndWriteNode.class); @Input ValueNode object; @Input ValueNode offset; @Input ValueNode newValue; @@ -47,7 +49,7 @@ protected final LocationIdentity locationIdentity; public AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { - super(StampFactory.forKind(newValue.getKind())); + super(TYPE, StampFactory.forKind(newValue.getKind())); this.object = object; this.offset = offset; this.newValue = newValue; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,6 +37,7 @@ @NodeInfo public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary, Lowerable { + public static final NodeClass TYPE = NodeClass.create(CheckCastDynamicNode.class); @Input ValueNode object; @Input ValueNode hub; @@ -46,7 +48,7 @@ protected final boolean forStoreCheck; public CheckCastDynamicNode(ValueNode hub, ValueNode object, boolean forStoreCheck) { - super(object.stamp()); + super(TYPE, object.stamp()); this.hub = hub; this.object = object; this.forStoreCheck = forStoreCheck; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -44,6 +44,7 @@ @NodeInfo public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Simplifiable, Lowerable, Virtualizable, ValueProxy { + public static final NodeClass TYPE = NodeClass.create(CheckCastNode.class); @Input protected ValueNode object; protected final ResolvedJavaType type; protected final JavaTypeProfile profile; @@ -55,7 +56,7 @@ protected final boolean forStoreCheck; public CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) { - super(StampFactory.declaredTrusted(type)); + super(TYPE, StampFactory.declaredTrusted(type)); assert type != null; this.type = type; this.object = object; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ClassIsAssignableFromNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ClassIsAssignableFromNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ClassIsAssignableFromNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,10 +36,13 @@ */ @NodeInfo public final class ClassIsAssignableFromNode extends LogicNode implements Canonicalizable.Binary, Lowerable { + + public static final NodeClass TYPE = NodeClass.create(ClassIsAssignableFromNode.class); @Input ValueNode thisClass; @Input ValueNode otherClass; public ClassIsAssignableFromNode(ValueNode thisClass, ValueNode otherClass) { + super(TYPE); this.thisClass = thisClass; this.otherClass = otherClass; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -38,6 +39,7 @@ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public final class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(CompareAndSwapNode.class); @Input ValueNode object; @Input ValueNode offset; @Input ValueNode expected; @@ -47,7 +49,7 @@ protected final LocationIdentity locationIdentity; public CompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { - super(StampFactory.forKind(Kind.Boolean.getStackKind())); + super(TYPE, StampFactory.forKind(Kind.Boolean.getStackKind())); assert expected.stamp().isCompatible(newValue.stamp()); this.object = object; this.offset = offset; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +39,7 @@ */ @NodeInfo public class DynamicNewArrayNode extends AbstractNewArrayNode { + public static final NodeClass TYPE = NodeClass.create(DynamicNewArrayNode.class); @Input ValueNode elementType; @@ -49,11 +50,15 @@ protected final Kind knownElementKind; public DynamicNewArrayNode(ValueNode elementType, ValueNode length) { - this(elementType, length, true, null); + this(TYPE, elementType, length, true, null); } public DynamicNewArrayNode(ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind) { - super(StampFactory.objectNonNull(), length, fillContents); + this(TYPE, elementType, length, fillContents, knownElementKind); + } + + protected DynamicNewArrayNode(NodeClass c, ValueNode elementType, ValueNode length, boolean fillContents, Kind knownElementKind) { + super(c, StampFactory.objectNonNull(), length, fillContents); this.elementType = elementType; this.knownElementKind = knownElementKind; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,11 +31,12 @@ @NodeInfo public final class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(DynamicNewInstanceNode.class); @Input ValueNode clazz; public DynamicNewInstanceNode(ValueNode clazz, boolean fillContents) { - super(StampFactory.objectNonNull(), fillContents); + super(TYPE, StampFactory.objectNonNull(), fillContents); this.clazz = clazz; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -35,9 +36,10 @@ */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) public final class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(ExceptionObjectNode.class); public ExceptionObjectNode(MetaAccessProvider metaAccess) { - super(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class))); + super(TYPE, StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class))); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,11 +37,13 @@ */ @NodeInfo public class InstanceOfDynamicNode extends LogicNode implements Canonicalizable.Binary, Lowerable { + public static final NodeClass TYPE = NodeClass.create(InstanceOfDynamicNode.class); @Input ValueNode object; @Input ValueNode mirror; public InstanceOfDynamicNode(ValueNode mirror, ValueNode object) { + super(TYPE); this.mirror = mirror; this.object = object; assert mirror.getKind() == Kind.Object : mirror.getKind(); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -35,13 +36,14 @@ * The {@code InstanceOfNode} represents an instanceof test. */ @NodeInfo -public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable { +public final class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable { + public static final NodeClass TYPE = NodeClass.create(InstanceOfNode.class); protected final ResolvedJavaType type; protected JavaTypeProfile profile; public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { - super(object); + super(TYPE, object); this.type = type; this.profile = profile; assert type != null; @@ -102,7 +104,7 @@ if (!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 LogicNegationNode.create(new IsNullNode(forValue)); } } return null; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +23,18 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable { +public final class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable { + + public static final NodeClass TYPE = NodeClass.create(LoadExceptionObjectNode.class); public LoadExceptionObjectNode(Stamp stamp) { - super(stamp); + super(TYPE, stamp); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -39,8 +40,10 @@ @NodeInfo(nameTemplate = "LoadField#{p#field/s}") public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary, VirtualizableRoot, UncheckedInterfaceProvider { + public static final NodeClass TYPE = NodeClass.create(LoadFieldNode.class); + public LoadFieldNode(ValueNode object, ResolvedJavaField field) { - super(createStamp(field), object, field); + super(TYPE, createStamp(field), object, field); } public ValueNode getValue() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +37,8 @@ @NodeInfo public class LoadIndexedNode extends AccessIndexedNode implements Virtualizable, Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(LoadIndexedNode.class); + /** * Creates a new LoadIndexedNode. * @@ -45,7 +47,7 @@ * @param elementKind the element type */ public LoadIndexedNode(ValueNode array, ValueNode index, Kind elementKind) { - this(createStamp(array, elementKind), array, index, elementKind); + this(TYPE, createStamp(array, elementKind), array, index, elementKind); } public static ValueNode create(ValueNode array, ValueNode index, Kind elementKind, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { @@ -56,8 +58,8 @@ return new LoadIndexedNode(array, index, elementKind); } - protected LoadIndexedNode(Stamp stamp, ValueNode array, ValueNode index, Kind elementKind) { - super(stamp, array, index, elementKind); + protected LoadIndexedNode(NodeClass c, Stamp stamp, ValueNode array, ValueNode index, Kind elementKind) { + super(c, stamp, array, index, elementKind); } private static Stamp createStamp(ValueNode array, Kind kind) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ import sun.misc.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -35,13 +36,14 @@ * {@link Unsafe#getAndSetInt(Object, long, int)} . */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { +public final class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(LoweredAtomicReadAndWriteNode.class); @Input ValueNode newValue; @OptionalInput(InputType.State) FrameState stateAfter; public LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType) { - super(object, location, newValue.stamp().unrestricted(), barrierType); + super(TYPE, object, location, newValue.stamp().unrestricted(), barrierType); this.newValue = newValue; } @@ -73,7 +75,7 @@ return false; } - public final ValueNode getNewValue() { + public ValueNode getNewValue() { return newValue; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -33,8 +34,9 @@ * Represents the lowered version of an atomic compare-and-swap operation{@code CompareAndSwapNode}. */ @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Memory}) -public class LoweredCompareAndSwapNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { +public final class LoweredCompareAndSwapNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(LoweredCompareAndSwapNode.class); @Input ValueNode expectedValue; @Input ValueNode newValue; @OptionalInput(InputType.State) FrameState stateAfter; @@ -62,7 +64,7 @@ } public LoweredCompareAndSwapNode(ValueNode object, LocationNode location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType) { - super(object, location, StampFactory.forKind(Kind.Boolean.getStackKind()), barrierType); + super(TYPE, object, location, StampFactory.forKind(Kind.Boolean.getStackKind()), barrierType); assert expectedValue.getKind() == newValue.getKind(); this.expectedValue = expectedValue; this.newValue = newValue; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +34,15 @@ @NodeInfo public class MethodCallTargetNode extends CallTargetNode implements IterableNodeType, Simplifiable { + public static final NodeClass TYPE = NodeClass.create(MethodCallTargetNode.class); protected final JavaType returnType; public MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) { - super(arguments, targetMethod, invokeKind); + this(TYPE, invokeKind, targetMethod, arguments, returnType); + } + + protected MethodCallTargetNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) { + super(c, arguments, targetMethod, invokeKind); this.returnType = returnType; } @@ -243,7 +248,7 @@ } public static MethodCallTargetNode find(StructuredGraph graph, ResolvedJavaMethod method) { - for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.TYPE)) { if (target.targetMethod().equals(method)) { return target; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +35,10 @@ @NodeInfo public final class MonitorEnterNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorEnter, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(MonitorEnterNode.class); + public MonitorEnterNode(ValueNode object, MonitorIdNode monitorId) { - super(object, monitorId); + super(TYPE, object, monitorId); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +39,11 @@ @NodeInfo public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Simplifiable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(MonitorExitNode.class); @OptionalInput ValueNode escapedReturnValue; public MonitorExitNode(ValueNode object, MonitorIdNode monitorId, ValueNode escapedReturnValue) { - super(object, monitorId); + super(TYPE, object, monitorId); this.escapedReturnValue = escapedReturnValue; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,10 +36,15 @@ @NodeInfo(allowedUsageTypes = {InputType.Association}) public class MonitorIdNode extends ValueNode implements IterableNodeType, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(MonitorIdNode.class); protected int lockDepth; public MonitorIdNode(int lockDepth) { - super(StampFactory.forVoid()); + this(TYPE, lockDepth); + } + + protected MonitorIdNode(NodeClass c, int lockDepth) { + super(c, StampFactory.forVoid()); this.lockDepth = lockDepth; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -40,8 +41,14 @@ @NodeInfo public class NewArrayNode extends AbstractNewArrayNode implements VirtualizableAllocation { + public static final NodeClass TYPE = NodeClass.create(NewArrayNode.class); + public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { - super(StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents); + super(TYPE, StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents); + } + + protected NewArrayNode(NodeClass c, ResolvedJavaType elementType, ValueNode length, boolean fillContents) { + super(c, StampFactory.exactNonNull(elementType.getArrayClass()), length, fillContents); } @NodeIntrinsic diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -38,10 +39,11 @@ @NodeInfo(nameTemplate = "New {p#instanceClass/s}") public final class NewInstanceNode extends AbstractNewObjectNode implements VirtualizableAllocation { + public static final NodeClass TYPE = NodeClass.create(NewInstanceNode.class); protected final ResolvedJavaType instanceClass; public NewInstanceNode(ResolvedJavaType type, boolean fillContents) { - super(StampFactory.exactNonNull(type), fillContents); + super(TYPE, StampFactory.exactNonNull(type), fillContents); assert !type.isArray() && !type.isInterface() && !type.isPrimitive(); this.instanceClass = type; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +35,7 @@ @NodeInfo public final class NewMultiArrayNode extends DeoptimizingFixedWithNextNode implements Lowerable, ArrayLengthProvider { + public static final NodeClass TYPE = NodeClass.create(NewMultiArrayNode.class); @Input protected NodeInputList dimensions; protected final ResolvedJavaType type; @@ -51,7 +52,7 @@ } public NewMultiArrayNode(ResolvedJavaType type, ValueNode[] dimensions) { - super(StampFactory.exactNonNull(type)); + super(TYPE, StampFactory.exactNonNull(type)); this.type = type; this.dimensions = new NodeInputList<>(this, dimensions); assert dimensions.length > 0 && type.isArray(); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,13 +37,14 @@ * constructor. */ @NodeInfo -public class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable.Unary, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter { +public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable.Unary, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter { + public static final NodeClass TYPE = NodeClass.create(RegisterFinalizerNode.class); @OptionalInput(InputType.State) FrameState deoptState; @Input ValueNode value; public RegisterFinalizerNode(ValueNode value) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +37,9 @@ * inlined. */ @NodeInfo -public class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable { +public final class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(SelfReplacingMethodCallTargetNode.class); // Replacement method data protected final ResolvedJavaMethod replacementTargetMethod; protected final JavaType replacementReturnType; @@ -46,7 +47,7 @@ public SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod, ValueNode[] replacementArguments, JavaType replacementReturnType) { - super(invokeKind, targetMethod, arguments, returnType); + super(TYPE, invokeKind, targetMethod, arguments, returnType); this.replacementTargetMethod = replacementTargetMethod; this.replacementReturnType = replacementReturnType; this.replacementArguments = new NodeInputList<>(this, replacementArguments); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,7 +34,8 @@ * The {@code StoreFieldNode} represents a write to a static or instance field. */ @NodeInfo(nameTemplate = "StoreField#{p#field/s}") -public class StoreFieldNode extends AccessFieldNode implements StateSplit, VirtualizableRoot { +public final class StoreFieldNode extends AccessFieldNode implements StateSplit, VirtualizableRoot { + public static final NodeClass TYPE = NodeClass.create(StoreFieldNode.class); @Input ValueNode value; @OptionalInput(InputType.State) FrameState stateAfter; @@ -57,12 +59,12 @@ } public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value) { - super(StampFactory.forVoid(), object, field); + super(TYPE, StampFactory.forVoid(), object, field); this.value = value; } public StoreFieldNode(ValueNode object, ResolvedJavaField field, ValueNode value, FrameState stateAfter) { - super(StampFactory.forVoid(), object, field); + super(TYPE, StampFactory.forVoid(), object, field); this.value = value; this.stateAfter = stateAfter; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,8 +34,9 @@ * The {@code StoreIndexedNode} represents a write to an array element. */ @NodeInfo -public class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable { +public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable { + public static final NodeClass TYPE = NodeClass.create(StoreIndexedNode.class); @Input ValueNode value; @OptionalInput(InputType.State) FrameState stateAfter; @@ -57,7 +59,7 @@ } public StoreIndexedNode(ValueNode array, ValueNode index, Kind elementKind, ValueNode value) { - super(StampFactory.forVoid(), array, index, elementKind); + super(TYPE, StampFactory.forVoid(), array, index, elementKind); this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -38,12 +39,13 @@ * comparison is an exact type comparison, not an instanceof. */ @NodeInfo -public class TypeSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { +public final class TypeSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable { + public static final NodeClass TYPE = NodeClass.create(TypeSwitchNode.class); protected final ResolvedJavaType[] keys; public TypeSwitchNode(ValueNode value, AbstractBeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { - super(value, successors, keySuccessors, keyProbabilities); + super(TYPE, value, successors, keySuccessors, keyProbabilities); assert successors.length <= keys.length + 1; assert keySuccessors.length == keyProbabilities.length; this.keys = keys; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/PiPushable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/PiPushable.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/PiPushable.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,7 +30,7 @@ public interface PiPushable { /** - * + * * @param parent PiNode * @return true if node was moved */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Mon Mar 02 19:11:22 2015 +0100 @@ -73,6 +73,13 @@ StructuredGraph getMethodSubstitution(ResolvedJavaMethod method); /** + * Gets the method that is a substitution for a given method. + * + * @return the method, if any, that is a substitution for {@code method} + */ + ResolvedJavaMethod getMethodSubstitutionMethod(ResolvedJavaMethod method); + + /** * Gets the node class with which a method invocation should be replaced. * * @param method target of an invocation diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Mon Mar 02 19:11:22 2015 +0100 @@ -60,7 +60,7 @@ * tool, and not directly on the node, because by the time this method is called the * virtualized/non-virtualized state is still speculative and might not hold because of loops, * etc. - * + * * @param tool the tool used to describe the effects of this node */ void virtualize(VirtualizerTool tool); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableAllocation.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableAllocation.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableAllocation.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,7 +25,7 @@ /** * This interface allows a node to convey information about what its effect would be if some of its * inputs were virtualized. - * + * * The difference to {@link VirtualizableRoot} is that removing {@link VirtualizableAllocation} * nodes is not considered progress during the escape analysis iterations. */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableRoot.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableRoot.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableRoot.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,12 +25,12 @@ /** * This interface allows a node to convey information about what its effect would be if some of its * inputs were virtualized. - * + * * The difference to {@link Virtualizable} is that the {@link #virtualize(VirtualizerTool)} method * will be called regardless of whether this node had any interaction with virtualized nodes. This * interface can therefore be used for object allocations, for which virtualization introduces new * virtualized objects. - * + * */ public interface VirtualizableRoot extends Virtualizable { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,15 +24,14 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.virtual.*; public class GraphUtil { @@ -40,7 +39,7 @@ @Override public final boolean apply(Node n) { - return n instanceof FloatingNode || n instanceof VirtualState || n instanceof CallTargetNode || n instanceof VirtualObjectNode; + return !(n instanceof FixedNode); } }; @@ -50,7 +49,7 @@ // We reached a control flow end. AbstractEndNode end = (AbstractEndNode) node; killEnd(end, tool); - } else { + } else if (node instanceof FixedNode) { // Normal control flow node. /* * We do not take a successor snapshot because this iterator supports concurrent @@ -62,6 +61,7 @@ killCFG(successor, tool); } } + node.replaceAtPredecessor(null); propagateKill(node); } @@ -112,21 +112,36 @@ return FLOATING; } - public static void propagateKill(Node node) { + private static void propagateKill(Node node) { if (node != null && node.isAlive()) { - List usagesSnapshot = node.usages().filter(isFloatingNode()).snapshot(); + node.markDeleted(); + + node.acceptInputs((n, in) -> { + if (in.isAlive()) { + in.removeUsage(n); + if (in.hasNoUsages() && !(in instanceof FixedNode)) { + killWithUnusedFloatingInputs(in); + } + } + }); - // null out remaining usages - node.replaceAtUsages(null); - node.replaceAtPredecessor(null); - killWithUnusedFloatingInputs(node); - - for (Node usage : usagesSnapshot) { - if (!usage.isDeleted()) { - if (usage instanceof PhiNode) { - usage.replaceFirstInput(node, null); - } else { - propagateKill(usage); + ArrayList usageToKill = null; + for (Node usage : node.usages()) { + if (usage.isAlive() && !(usage instanceof FixedNode)) { + if (usageToKill == null) { + usageToKill = new ArrayList<>(); + } + usageToKill.add(usage); + } + } + if (usageToKill != null) { + for (Node usage : usageToKill) { + if (usage.isAlive()) { + if (usage instanceof PhiNode) { + usage.replaceFirstInput(node, null); + } else { + propagateKill(usage); + } } } } @@ -134,11 +149,9 @@ } public static void killWithUnusedFloatingInputs(Node node) { - List floatingInputs = node.inputs().filter(isFloatingNode()).snapshot(); node.safeDelete(); - - for (Node in : floatingInputs) { - if (in.isAlive() && in.hasNoUsages()) { + for (Node in : node.inputs()) { + if (in.isAlive() && in.hasNoUsages() && !(in instanceof FixedNode)) { killWithUnusedFloatingInputs(in); } } @@ -241,13 +254,7 @@ if (n instanceof StateSplit) { FrameState state = ((StateSplit) n).stateAfter(); - while (state != null) { - ResolvedJavaMethod method = state.method(); - if (method != null) { - elements.add(method.asStackTraceElement(state.bci - 1)); - } - state = state.outerFrameState(); - } + elements.addAll(Arrays.asList(approxSourceStackTraceElement(state))); break; } n = n.predecessor(); @@ -256,14 +263,63 @@ } /** + * Gets an approximate source code location for frame state. + * + * @return the StackTraceElements if an approximate source location is found, null otherwise + */ + public static StackTraceElement[] approxSourceStackTraceElement(FrameState frameState) { + ArrayList elements = new ArrayList<>(); + FrameState state = frameState; + while (state != null) { + ResolvedJavaMethod method = state.method(); + if (method != null) { + elements.add(method.asStackTraceElement(state.bci - 1)); + } + state = state.outerFrameState(); + } + return elements.toArray(new StackTraceElement[0]); + } + + /** * Gets an approximate source code location for a node, encoded as an exception, if possible. * * @return the exception with the location */ public static RuntimeException approxSourceException(Node node, Throwable cause) { final StackTraceElement[] elements = approxSourceStackTraceElement(node); + return createBailoutException(cause == null ? "" : cause.getMessage(), cause, elements); + } + + /** + * Creates a bailout exception with the given stack trace elements and message. + * + * @param message the message of the exception + * @param elements the stack trace elements + * @return the exception + */ + public static BailoutException createBailoutException(String message, Throwable cause, StackTraceElement[] elements) { @SuppressWarnings("serial") - RuntimeException exception = new RuntimeException((cause == null) ? null : cause.getMessage(), cause) { + BailoutException exception = new BailoutException(cause, message) { + + @Override + public final synchronized Throwable fillInStackTrace() { + setStackTrace(elements); + return this; + } + }; + return exception; + } + + /** + * Creates a runtime exception with the given stack trace elements and message. + * + * @param message the message of the exception + * @param elements the stack trace elements + * @return the exception + */ + public static RuntimeException createRuntimeException(String message, Throwable cause, StackTraceElement[] elements) { + @SuppressWarnings("serial") + RuntimeException exception = new RuntimeException(message, cause) { @Override public final synchronized Throwable fillInStackTrace() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -35,11 +36,12 @@ @NodeInfo public final class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider { + public static final NodeClass TYPE = NodeClass.create(AllocatedObjectNode.class); @Input VirtualObjectNode virtualObject; @Input(InputType.Extension) CommitAllocationNode commit; public AllocatedObjectNode(VirtualObjectNode virtualObject) { - super(StampFactory.exactNonNull(virtualObject.type())); + super(TYPE, StampFactory.exactNonNull(virtualObject.type())); this.virtualObject = virtualObject; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,13 +35,14 @@ @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension}) public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable { + public static final NodeClass TYPE = NodeClass.create(CommitAllocationNode.class); @Input NodeInputList virtualObjects = new NodeInputList<>(this); @Input NodeInputList values = new NodeInputList<>(this); @Input(InputType.Association) NodeInputList locks = new NodeInputList<>(this); protected ArrayList lockIndexes = new ArrayList<>(Arrays.asList(0)); public CommitAllocationNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } public List getVirtualObjects() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,12 +22,14 @@ */ package com.oracle.graal.nodes.virtual; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo public abstract class EscapeObjectState extends VirtualState implements ValueNumberable { + public static final NodeClass TYPE = NodeClass.create(EscapeObjectState.class); @Input protected VirtualObjectNode object; @@ -35,7 +37,8 @@ return object; } - public EscapeObjectState(VirtualObjectNode object) { + public EscapeObjectState(NodeClass c, VirtualObjectNode object) { + super(c); this.object = object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,18 +27,20 @@ import sun.misc.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]") -public class VirtualArrayNode extends VirtualObjectNode implements ArrayLengthProvider { +public final class VirtualArrayNode extends VirtualObjectNode implements ArrayLengthProvider { + public static final NodeClass TYPE = NodeClass.create(VirtualArrayNode.class); protected final ResolvedJavaType componentType; protected final int length; public VirtualArrayNode(ResolvedJavaType componentType, int length) { - super(componentType.getArrayClass(), true); + super(TYPE, componentType.getArrayClass(), true); this.componentType = componentType; this.length = length; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,17 +23,19 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @NodeInfo -public class VirtualBoxingNode extends VirtualInstanceNode { +public final class VirtualBoxingNode extends VirtualInstanceNode { + public static final NodeClass TYPE = NodeClass.create(VirtualBoxingNode.class); protected final Kind boxingKind; public VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) { - super(type, false); + super(TYPE, type, false); this.boxingKind = boxingKind; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +23,14 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo(nameTemplate = "VirtualInstance {p#type/s}") public class VirtualInstanceNode extends VirtualObjectNode { + public static final NodeClass TYPE = NodeClass.create(VirtualInstanceNode.class); protected final ResolvedJavaType type; protected final ResolvedJavaField[] fields; @@ -37,7 +39,15 @@ } public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) { - super(type, hasIdentity); + this(TYPE, type, fields, hasIdentity); + } + + protected VirtualInstanceNode(NodeClass c, ResolvedJavaType type, boolean hasIdentity) { + this(c, type, type.getInstanceFields(true), hasIdentity); + } + + protected VirtualInstanceNode(NodeClass c, ResolvedJavaType type, ResolvedJavaField[] fields, boolean hasIdentity) { + super(c, type, hasIdentity); this.type = type; this.fields = fields; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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 @@ @NodeInfo public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(VirtualObjectNode.class); protected boolean hasIdentity; - public VirtualObjectNode(ResolvedJavaType type, boolean hasIdentity) { - super(StampFactory.exactNonNull(type)); + protected VirtualObjectNode(NodeClass c, ResolvedJavaType type, boolean hasIdentity) { + super(c, StampFactory.exactNonNull(type)); this.hasIdentity = hasIdentity; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/NestedBooleanOptionValueTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options.test/src/com/oracle/graal/options/test/NestedBooleanOptionValueTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,128 @@ +/* + * 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.options.test; + +import static com.oracle.graal.options.test.NestedBooleanOptionValueTest.Options.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.options.*; +import com.oracle.graal.options.OptionValue.OverrideScope; + +public class NestedBooleanOptionValueTest { + + public static class Options { + public static final OptionValue Master0 = new OptionValue<>(true); + public static final OptionValue NestedOption0 = new NestedBooleanOptionValue(Master0, true); + public static final OptionValue Master1 = new OptionValue<>(true); + public static final OptionValue NestedOption1 = new NestedBooleanOptionValue(Master1, true); + public static final OptionValue Master2 = new OptionValue<>(true); + public static final OptionValue NestedOption2 = new NestedBooleanOptionValue(Master2, false); + } + + static final OptionDescriptor master0 = new OptionDescriptor("Master0", Boolean.class, "", Options.class, "Master0", Master0); + static final OptionDescriptor nestedOption0 = new OptionDescriptor("NestedOption0", Boolean.class, "", Options.class, "NestedOption0", NestedOption0); + static final OptionDescriptor master1 = new OptionDescriptor("Master1", Boolean.class, "", Options.class, "Master1", Master1); + static final OptionDescriptor nestedOption1 = new OptionDescriptor("NestedOption1", Boolean.class, "", Options.class, "NestedOption1", NestedOption1); + static final OptionDescriptor master2 = new OptionDescriptor("Master2", Boolean.class, "", Options.class, "Master2", Master2); + static final OptionDescriptor nestedOption2 = new OptionDescriptor("NestedOption2", Boolean.class, "", Options.class, "NestedOption2", NestedOption2); + + @Test + public void runOverrides() { + assertTrue(Master0.getValue()); + assertTrue(NestedOption0.getValue()); + try (OverrideScope s1 = OptionValue.override(Master0, false)) { + assertFalse(Master0.getValue()); + assertFalse(NestedOption0.getValue()); + try (OverrideScope s2 = OptionValue.override(NestedOption0, false)) { + assertFalse(NestedOption0.getValue()); + } + try (OverrideScope s2 = OptionValue.override(NestedOption0, true)) { + assertTrue(NestedOption0.getValue()); + } + } + assertTrue(Master0.getValue()); + try (OverrideScope s1 = OptionValue.override(NestedOption0, false)) { + assertFalse(NestedOption0.getValue()); + } + try (OverrideScope s1 = OptionValue.override(NestedOption0, true)) { + assertTrue(NestedOption0.getValue()); + } + } + + @Test + public void runDefaultTrue() { + Master1.setValue(true); + assertTrue(Master1.getValue()); + assertTrue(NestedOption1.getValue()); + // nested value unset + Master1.setValue(false); + assertFalse(Master1.getValue()); + assertFalse(NestedOption1.getValue()); + // set false + Master1.setValue(false); + NestedOption1.setValue(false); + assertFalse(Master1.getValue()); + assertFalse(NestedOption1.getValue()); + Master1.setValue(true); + assertTrue(Master1.getValue()); + assertFalse(NestedOption1.getValue()); + // set true + Master1.setValue(false); + NestedOption1.setValue(true); + assertFalse(Master1.getValue()); + assertTrue(NestedOption1.getValue()); + Master1.setValue(true); + assertTrue(Master1.getValue()); + assertTrue(NestedOption1.getValue()); + } + + @Test + public void runDefaultFalse() { + Master2.setValue(true); + assertTrue(Master2.getValue()); + assertFalse(NestedOption2.getValue()); + // nested value unset + Master2.setValue(false); + assertFalse(Master2.getValue()); + assertFalse(NestedOption2.getValue()); + // set false + Master2.setValue(false); + NestedOption2.setValue(false); + assertFalse(Master2.getValue()); + assertFalse(NestedOption2.getValue()); + Master2.setValue(true); + assertTrue(Master2.getValue()); + assertFalse(NestedOption2.getValue()); + // set true + Master2.setValue(false); + NestedOption2.setValue(true); + assertFalse(Master2.getValue()); + assertTrue(NestedOption2.getValue()); + Master2.setValue(true); + assertTrue(Master2.getValue()); + assertTrue(NestedOption2.getValue()); + } + +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.options/src/com/oracle/graal/options/NestedBooleanOptionValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/NestedBooleanOptionValue.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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.options; + +/** + * A nested Boolean {@link OptionValue} that can be overridden by a {@link #masterOption master + * option}. + *

    + *

  • If the option is present on the command line the specified value is used. + *
  • Otherwise {@link #getValue()} depends on the {@link #masterOption} and evaluates as follows: + *
      + *
    • If {@link #masterOption} is set, this value equals to {@link #initialValue}. + *
    • Otherwise, if {@link #masterOption} is {@code false}, this option is {@code false}. + */ +public class NestedBooleanOptionValue extends OptionValue { + private final OptionValue masterOption; + private final Boolean initialValue; + + public NestedBooleanOptionValue(OptionValue masterOption, Boolean initialValue) { + super(null); + this.masterOption = masterOption; + this.initialValue = initialValue; + } + + public OptionValue getMasterOption() { + return masterOption; + } + + @Override + public Boolean getValue() { + Boolean v = super.getValue(); + if (v == null) { + return initialValue && masterOption.getValue(); + } + return v; + } + +} diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.Graph.NodeEventListener; import com.oracle.graal.graph.Graph.NodeEventScope; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -187,7 +188,7 @@ if (node.isAlive()) { METRIC_PROCESSED_NODES.increment(); - NodeClass nodeClass = node.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); if (tryGlobalValueNumbering(node, nodeClass)) { return; } @@ -213,7 +214,7 @@ } } - public static boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) { + public static boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) { if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) { Node newNode = node.graph().findDuplicate(node); if (newNode != null) { @@ -228,7 +229,7 @@ return false; } - public boolean tryCanonicalize(final Node node, NodeClass nodeClass) { + public boolean tryCanonicalize(final Node node, NodeClass nodeClass) { if (customCanonicalizer != null) { Node canonical = customCanonicalizer.canonicalize(node); if (performReplacement(node, canonical)) { @@ -254,13 +255,16 @@ } } - public boolean baseTryCanonicalize(final Node node, NodeClass nodeClass) { + 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; try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) { canonical = ((Canonicalizable) node).canonical(tool); + if (canonical == node && nodeClass.isCommutative()) { + canonical = ((BinaryCommutative) node).maybeCommuteInputs(); + } } if (performReplacement(node, canonical)) { return true; @@ -311,9 +315,6 @@ if (canonical != null && !canonical.isAlive()) { assert !canonical.isDeleted(); canonical = graph.addOrUniqueWithInputs(canonical); - if (canonical == node) { - graph.addOrUniqueWithInputs(newCanonical); - } } if (node instanceof FloatingNode) { if (canonical == null) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,13 +40,13 @@ protected void run(StructuredGraph graph, PhaseContext context) { HashSetNodeEventListener listener = new HashSetNodeEventListener(); try (NodeEventScope s = graph.trackNodeEvents(listener)) { - for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.class)) { + for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.TYPE)) { graph.replaceFloating(proxy, proxy.getValue()); } } if (!listener.getNodes().isEmpty()) { canonicalizer.applyIncremental(graph, context, listener.getNodes()); } - assert graph.getNodes(TypeProfileProxyNode.class).count() == 0; + assert graph.getNodes(TypeProfileProxyNode.TYPE).count() == 0; } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; /** * This phase will find branches which always end with a {@link DeoptimizeNode} and replace their @@ -48,7 +49,7 @@ * {@link DeoptimizeNode} as close to the {@link ControlSplitNode} as possible. * */ -public class ConvertDeoptimizeToGuardPhase extends Phase { +public class ConvertDeoptimizeToGuardPhase extends BasePhase { private SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, false); private static AbstractBeginNode findBeginNode(FixedNode startNode) { @@ -56,56 +57,81 @@ } @Override - protected void run(final StructuredGraph graph) { + protected void run(final StructuredGraph graph, PhaseContext context) { assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies"; - if (graph.getNodes(DeoptimizeNode.class).isEmpty()) { + if (graph.getNodes(DeoptimizeNode.TYPE).isEmpty()) { return; } - for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) { + for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.TYPE)) { assert d.isAlive(); visitDeoptBegin(AbstractBeginNode.prevBegin(d), d.action(), d.reason(), graph); } - for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) { - - AbstractBeginNode pred = AbstractBeginNode.prevBegin(fixedGuard); - if (pred instanceof AbstractMergeNode) { - AbstractMergeNode merge = (AbstractMergeNode) pred; - if (fixedGuard.condition() instanceof CompareNode) { - CompareNode compare = (CompareNode) fixedGuard.condition(); - List mergePredecessors = merge.cfgPredecessors().snapshot(); - - Constant[] xs = IfNode.constantValues(compare.getX(), merge, true); - if (xs == null) { - continue; - } - Constant[] ys = IfNode.constantValues(compare.getY(), merge, true); - if (ys == null) { - continue; - } - for (int i = 0; i < mergePredecessors.size(); ++i) { - AbstractEndNode mergePredecessor = mergePredecessors.get(i); - if (!mergePredecessor.isAlive()) { - break; - } - if (xs[i] == null) { - continue; - } - if (ys[i] == null) { - continue; - } - if (xs[i] instanceof PrimitiveConstant && ys[i] instanceof PrimitiveConstant && - compare.condition().foldCondition(xs[i], ys[i], null, compare.unorderedIsTrue()) == fixedGuard.isNegated()) { - visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), graph); - } - } - } + if (context != null) { + for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.TYPE)) { + trySplitFixedGuard(fixedGuard, context); } } new DeadCodeEliminationPhase(Optional).apply(graph); } + private void trySplitFixedGuard(FixedGuardNode fixedGuard, PhaseContext context) { + LogicNode condition = fixedGuard.condition(); + if (condition instanceof CompareNode) { + CompareNode compare = (CompareNode) condition; + ValueNode x = compare.getX(); + ValuePhiNode xPhi = (x instanceof ValuePhiNode) ? (ValuePhiNode) x : null; + if (x instanceof ConstantNode || xPhi != null) { + ValueNode y = compare.getY(); + ValuePhiNode yPhi = (y instanceof ValuePhiNode) ? (ValuePhiNode) y : null; + if (y instanceof ConstantNode || yPhi != null) { + processFixedGuardAndPhis(fixedGuard, context, compare, x, xPhi, y, yPhi); + } + } + } + } + + private void processFixedGuardAndPhis(FixedGuardNode fixedGuard, PhaseContext context, CompareNode compare, ValueNode x, ValuePhiNode xPhi, ValueNode y, ValuePhiNode yPhi) { + AbstractBeginNode pred = AbstractBeginNode.prevBegin(fixedGuard); + if (pred instanceof AbstractMergeNode) { + AbstractMergeNode merge = (AbstractMergeNode) pred; + if (xPhi != null && xPhi.merge() != merge) { + return; + } + if (yPhi != null && yPhi.merge() != merge) { + return; + } + + processFixedGuardAndMerge(fixedGuard, context, compare, x, xPhi, y, yPhi, merge); + } + } + + private void processFixedGuardAndMerge(FixedGuardNode fixedGuard, PhaseContext context, CompareNode compare, ValueNode x, ValuePhiNode xPhi, ValueNode y, ValuePhiNode yPhi, AbstractMergeNode merge) { + List mergePredecessors = merge.cfgPredecessors().snapshot(); + for (int i = 0; i < mergePredecessors.size(); ++i) { + AbstractEndNode mergePredecessor = mergePredecessors.get(i); + if (!mergePredecessor.isAlive()) { + break; + } + Constant xs; + if (xPhi == null) { + xs = x.asConstant(); + } else { + xs = xPhi.valueAt(mergePredecessor).asConstant(); + } + Constant ys; + if (yPhi == null) { + ys = y.asConstant(); + } else { + ys = yPhi.valueAt(mergePredecessor).asConstant(); + } + if (xs != null && ys != null && compare.condition().foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue()) == fixedGuard.isNegated()) { + visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), fixedGuard.graph()); + } + } + } + private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) { if (deoptBegin instanceof AbstractMergeNode) { AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,8 @@ import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Options.*; +import java.util.function.*; + import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -70,93 +72,52 @@ if (optional && ReduceDCE.getValue()) { return; } + NodeFlood flood = graph.createNodeFlood(); - + int totalNodeCount = graph.getNodeCount(); flood.add(graph.start()); - iterateSuccessors(flood); - disconnectCFGNodes(flood, graph); - iterateInputs(flood, graph); + iterateSuccessorsAndInputs(flood); + int totalMarkedCount = flood.getTotalMarkedCount(); + if (totalNodeCount == totalMarkedCount) { + // All nodes are live => nothing more to do. + return; + } else { + // Some nodes are not marked alive and therefore dead => proceed. + assert totalNodeCount > totalMarkedCount; + } + deleteNodes(flood, graph); - - // remove chained Merges - for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class)) { - if (merge.forwardEndCount() == 1 && !(merge instanceof LoopBeginNode)) { - graph.reduceTrivialMerge(merge); - } - } } - private static void iterateSuccessors(NodeFlood flood) { + private static void iterateSuccessorsAndInputs(NodeFlood flood) { + BiConsumer consumer = (n, succOrInput) -> { + assert succOrInput.isAlive() : succOrInput; + flood.add(succOrInput); + }; for (Node current : flood) { if (current instanceof AbstractEndNode) { AbstractEndNode end = (AbstractEndNode) current; flood.add(end.merge()); } else { - for (Node successor : current.successors()) { - flood.add(successor); - } - } - } - } - - private static void disconnectCFGNodes(NodeFlood flood, StructuredGraph graph) { - for (AbstractEndNode node : graph.getNodes(AbstractEndNode.class)) { - if (!flood.isMarked(node)) { - AbstractMergeNode merge = node.merge(); - if (merge != null && flood.isMarked(merge)) { - // We are a dead end node leading to a live merge. - merge.removeEnd(node); - } - } - } - for (LoopBeginNode loop : graph.getNodes(LoopBeginNode.class)) { - if (flood.isMarked(loop)) { - boolean reachable = false; - for (LoopEndNode end : loop.loopEnds()) { - if (flood.isMarked(end)) { - reachable = true; - break; - } - } - if (!reachable) { - Debug.log("Removing loop with unreachable end: %s", loop); - for (LoopEndNode end : loop.loopEnds().snapshot()) { - loop.removeEnd(end); - } - graph.reduceDegenerateLoopBegin(loop); - } + current.acceptSuccessors(consumer); + current.acceptInputs(consumer); } } } private static void deleteNodes(NodeFlood flood, StructuredGraph graph) { + BiConsumer consumer = (n, input) -> { + if (input.isAlive() && flood.isMarked(input)) { + input.removeUsage(n); + } + }; + for (Node node : graph.getNodes()) { if (!flood.isMarked(node)) { - node.clearInputs(); - node.clearSuccessors(); - } - } - for (Node node : graph.getNodes()) { - if (!flood.isMarked(node)) { + node.markDeleted(); + node.acceptInputs(consumer); metricNodesRemoved.increment(); - node.safeDelete(); } } } - - private static void iterateInputs(NodeFlood flood, StructuredGraph graph) { - for (Node node : graph.getNodes()) { - if (flood.isMarked(node)) { - for (Node input : node.inputs()) { - flood.add(input); - } - } - } - for (Node current : flood) { - for (Node input : current.inputs()) { - flood.add(input); - } - } - } - } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,7 +40,7 @@ @Override protected void run(StructuredGraph graph, MidTierContext context) { ControlFlowGraph cfg = null; - for (FrameState fs : graph.getNodes(FrameState.class)) { + for (FrameState fs : graph.getNodes(FrameState.TYPE)) { FixedNode target = null; PhiNode reasonActionPhi = null; PhiNode speculationPhi = null; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,10 +32,10 @@ @Override protected void run(StructuredGraph graph) { - for (ShortCircuitOrNode logic : graph.getNodes(ShortCircuitOrNode.class)) { + for (ShortCircuitOrNode logic : graph.getNodes(ShortCircuitOrNode.TYPE)) { processBinary(logic); } - assert graph.getNodes(ShortCircuitOrNode.class).isEmpty(); + assert graph.getNodes(ShortCircuitOrNode.TYPE).isEmpty(); } private static void processBinary(ShortCircuitOrNode binary) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -45,7 +45,6 @@ private boolean createFloatingReads; private boolean createMemoryMapNodes; - private boolean updateExistingPhis; public static class MemoryMapImpl implements MemoryMap { @@ -90,7 +89,7 @@ } public FloatingReadPhase() { - this(true, false, false); + this(true, false); } /** @@ -99,13 +98,10 @@ * {@link FloatingReadNode}s) where possible * @param createMemoryMapNodes a {@link MemoryMapNode} will be created for each return if this * is true - * @param updateExistingPhis if true, then existing {@link MemoryPhiNode}s in the graph will be - * updated */ - public FloatingReadPhase(boolean createFloatingReads, boolean createMemoryMapNodes, boolean updateExistingPhis) { + public FloatingReadPhase(boolean createFloatingReads, boolean createMemoryMapNodes) { this.createFloatingReads = createFloatingReads; this.createMemoryMapNodes = createMemoryMapNodes; - this.updateExistingPhis = updateExistingPhis; } /** @@ -135,7 +131,7 @@ ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(modifiedInLoops), graph.start(), CollectionsFactory.newSet()); HashSetNodeEventListener listener = new HashSetNodeEventListener(EnumSet.of(NODE_ADDED, ZERO_USAGES)); try (NodeEventScope nes = graph.trackNodeEvents(listener)) { - ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops, createFloatingReads, createMemoryMapNodes, updateExistingPhis), graph.start(), new MemoryMapImpl(graph.start())); + ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops, createFloatingReads, createMemoryMapNodes), graph.start(), new MemoryMapImpl(graph.start())); } for (Node n : removeExternallyUsedNodes(listener.getNodes())) { @@ -150,7 +146,7 @@ } } - public static MemoryMapImpl mergeMemoryMaps(AbstractMergeNode merge, List states, boolean updateExistingPhis) { + public static MemoryMapImpl mergeMemoryMaps(AbstractMergeNode merge, List states) { MemoryMapImpl newState = new MemoryMapImpl(); Set keys = CollectionsFactory.newSet(); @@ -159,17 +155,6 @@ } assert checkNoImmutableLocations(keys); - Map existingPhis = null; - if (updateExistingPhis) { - for (MemoryPhiNode phi : merge.phis().filter(MemoryPhiNode.class)) { - if (existingPhis == null) { - existingPhis = CollectionsFactory.newMap(); - } - phi.values().clear(); - existingPhis.put(phi.getLocationIdentity(), phi); - } - } - for (LocationIdentity key : keys) { int mergedStatesCount = 0; boolean isPhi = false; @@ -184,10 +169,7 @@ } else if (merged == null) { merged = last; } else { - MemoryPhiNode phi = null; - if (existingPhis == null || (phi = existingPhis.remove(key)) == null) { - phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key)); - } + MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key)); for (int j = 0; j < mergedStatesCount; j++) { phi.addInput(ValueNodeUtil.asNode(merged)); } @@ -200,11 +182,6 @@ } newState.lastMemorySnapshot.put(key, merged); } - if (existingPhis != null) { - for (Map.Entry entry : existingPhis.entrySet()) { - entry.getValue().replaceAndDelete(newState.getLastLocationAccess(entry.getKey()).asNode()); - } - } return newState; } @@ -273,13 +250,11 @@ private final Map> modifiedInLoops; private boolean createFloatingReads; private boolean createMemoryMapNodes; - private boolean updateExistingPhis; - public FloatingReadClosure(Map> modifiedInLoops, boolean createFloatingReads, boolean createMemoryMapNodes, boolean updateExistingPhis) { + public FloatingReadClosure(Map> modifiedInLoops, boolean createFloatingReads, boolean createMemoryMapNodes) { this.modifiedInLoops = modifiedInLoops; this.createFloatingReads = createFloatingReads; this.createMemoryMapNodes = createMemoryMapNodes; - this.updateExistingPhis = updateExistingPhis; } @Override @@ -347,7 +322,7 @@ @Override protected MemoryMapImpl merge(AbstractMergeNode merge, List states) { - return mergeMemoryMaps(merge, states, updateExistingPhis); + return mergeMemoryMaps(merge, states); } @Override @@ -378,24 +353,10 @@ Map phis = CollectionsFactory.newMap(); - if (updateExistingPhis) { - for (MemoryPhiNode phi : loop.phis().filter(MemoryPhiNode.class).snapshot()) { - if (modifiedLocations.contains(phi.getLocationIdentity())) { - phi.values().clear(); - phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(phi.getLocationIdentity()))); - phis.put(phi.getLocationIdentity(), phi); - } else { - phi.replaceAndDelete(initialState.getLastLocationAccess(phi.getLocationIdentity()).asNode()); - } - } - } - for (LocationIdentity location : modifiedLocations) { - if (!updateExistingPhis || !phis.containsKey(location)) { - MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location)); - phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location))); - phis.put(location, phi); - } + MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location)); + phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location))); + phis.put(location, phi); } for (Map.Entry entry : phis.entrySet()) { initialState.lastMemorySnapshot.put(entry.getKey(), entry.getValue()); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -110,7 +110,7 @@ if (graph.getGuardsStage().areFrameStatesAtSideEffects()) { ReentrantNodeIterator.apply(new FrameStateAssignmentClosure(), graph.start(), null); graph.setGuardsStage(GuardsStage.AFTER_FSA); - graph.getNodes(FrameState.class).filter(state -> state.hasNoUsages()).forEach(GraphUtil::killWithUnusedFloatingInputs); + graph.getNodes(FrameState.TYPE).filter(state -> state.hasNoUsages()).forEach(GraphUtil::killWithUnusedFloatingInputs); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -163,7 +163,8 @@ StructuredGraph graph = guard.graph(); AbstractBeginNode fastPath = graph.add(new BeginNode()); @SuppressWarnings("deprecation") - DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation(), null)); + int debugId = useGuardIdAsDebugId ? guard.getId() : DeoptimizeNode.DEFAULT_DEBUG_ID; + DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), debugId, guard.getSpeculation(), null)); AbstractBeginNode deoptBranch = BeginNode.begin(deopt); AbstractBeginNode trueSuccessor; AbstractBeginNode falseSuccessor; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LockEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LockEliminationPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LockEliminationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,7 +31,7 @@ @Override protected void run(StructuredGraph graph) { - for (MonitorExitNode node : graph.getNodes(MonitorExitNode.class)) { + for (MonitorExitNode node : graph.getNodes(MonitorExitNode.TYPE)) { FixedNode next = node.next(); if (next instanceof MonitorEnterNode) { MonitorEnterNode monitorEnterNode = (MonitorEnterNode) next; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,7 +35,7 @@ @Override protected void run(StructuredGraph graph) { if (GenLoopSafepoints.getValue()) { - for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) { + for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.TYPE)) { if (loopEndNode.canSafepoint()) { SafepointNode safepointNode = graph.add(new SafepointNode()); graph.addBeforeFixed(loopEndNode, safepointNode); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * 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,11 +47,12 @@ public class LoweringPhase extends BasePhase { @NodeInfo - static class DummyGuardHandle extends ValueNode implements GuardedNode { + static final class DummyGuardHandle extends ValueNode implements GuardedNode { + public static final NodeClass TYPE = NodeClass.create(DummyGuardHandle.class); @Input(InputType.Guard) GuardingNode guard; public DummyGuardHandle(GuardingNode guard) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.guard = guard; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,7 +35,7 @@ @Override protected void run(StructuredGraph graph) { Stamp nonNull = StampFactory.objectNonNull(); - for (ParameterNode param : graph.getNodes(ParameterNode.class)) { + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { if (param.stamp() instanceof ObjectStamp) { ObjectStamp paramStamp = (ObjectStamp) param.stamp(); param.setStamp(paramStamp.join(nonNull)); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -55,7 +55,7 @@ @Override protected void run(StructuredGraph graph) { LazyCFG cfg = new LazyCFG(graph); - for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) { + for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.TYPE)) { if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) { NodeIterable guards = begin.guards(); if (guards.isNotEmpty()) { @@ -71,7 +71,7 @@ } } } - for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) { + for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.TYPE)) { optimizeAtControlSplit(controlSplit, cfg); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,7 +34,7 @@ @Override protected void run(StructuredGraph graph) { - for (PiNode pi : graph.getNodes(PiNode.class)) { + for (PiNode pi : graph.getNodes(PiNode.TYPE)) { for (Node n : pi.usages().snapshot()) { if (n instanceof PiPushable) { PiPushable pip = (PiPushable) n; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,12 +30,12 @@ @Override protected void run(StructuredGraph graph) { - for (ProxyNode vpn : graph.getNodes(ProxyNode.class)) { + for (ProxyNode vpn : graph.getNodes(ProxyNode.TYPE)) { if (vpn instanceof ValueProxyNode) { graph.replaceFloating(vpn, vpn.value()); } } - for (LoopExitNode exit : graph.getNodes(LoopExitNode.class)) { + for (LoopExitNode exit : graph.getNodes(LoopExitNode.TYPE)) { FrameState stateAfter = exit.stateAfter(); if (stateAfter != null) { exit.setStateAfter(null); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -62,9 +62,11 @@ private final CanonicalizerPhase canonicalizer; @NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor}) - static class DummyAnchorNode extends FixedWithNextNode implements GuardingNode, AnchoringNode { + static final class DummyAnchorNode extends FixedWithNextNode implements GuardingNode, AnchoringNode { + public static final NodeClass TYPE = NodeClass.create(DummyAnchorNode.class); + public DummyAnchorNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } } @@ -156,12 +158,12 @@ @Override protected void run(StructuredGraph graph, PhaseContext phaseContext) { - if (graph.hasNode(AbstractMergeNode.class)) { + if (graph.hasNode(AbstractMergeNode.TYPE)) { ToDoubleFunction nodeProbabilities = new FixedNodeProbabilityCache(); // A snapshot is taken here, so that new MergeNode instances aren't considered for tail // duplication. - for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class).snapshot()) { + for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.TYPE).snapshot()) { if (!(merge instanceof LoopBeginNode) && nodeProbabilities.applyAsDouble(merge) >= TailDuplicationProbability.getValue()) { tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext, canonicalizer); } @@ -278,11 +280,11 @@ mergeAfter.clearEnds(); expandDuplicated(duplicatedNodes, mergeAfter); - List endSnapshot = merge.forwardEnds().snapshot(); + List endSnapshot = merge.forwardEnds().snapshot(); List phiSnapshot = merge.phis().snapshot(); int endIndex = 0; - for (final AbstractEndNode forwardEnd : merge.forwardEnds()) { + for (final EndNode forwardEnd : merge.forwardEnds()) { Map duplicates; if (replacements == null || replacements.get(endIndex) == null) { duplicates = graph.addDuplicates(duplicatedNodes, graph, duplicatedNodes.size(), (DuplicationReplacement) null); @@ -294,7 +296,7 @@ for (Map.Entry phi : bottomPhis.entrySet()) { phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey())); } - mergeAfter.addForwardEnd((AbstractEndNode) duplicates.get(endAfter)); + mergeAfter.addForwardEnd((EndNode) duplicates.get(endAfter)); // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding // EndNode @@ -450,8 +452,8 @@ * @return The newly created end node. */ private AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) { - AbstractMergeNode newBottomMerge = graph.add(new MergeNode()); - AbstractEndNode newBottomEnd = graph.add(new EndNode()); + MergeNode newBottomMerge = graph.add(new MergeNode()); + EndNode newBottomEnd = graph.add(new EndNode()); newBottomMerge.addForwardEnd(newBottomEnd); newBottomMerge.setStateAfter(stateAfterMerge); ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -48,10 +48,10 @@ } assert graph.getGuardsStage().areFrameStatesAtDeopts(); - for (DeoptimizeNode deopt : graph.getNodes(DeoptimizeNode.class)) { + for (DeoptimizeNode deopt : graph.getNodes(DeoptimizeNode.TYPE)) { tryUseTrappingNullCheck(deopt, deopt.predecessor(), deopt.reason(), deopt.getSpeculation()); } - for (DynamicDeoptimizeNode deopt : graph.getNodes(DynamicDeoptimizeNode.class)) { + for (DynamicDeoptimizeNode deopt : graph.getNodes(DynamicDeoptimizeNode.TYPE)) { tryUseTrappingNullCheck(context.getMetaAccess(), deopt); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/VerifyHeapAtReturnPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/VerifyHeapAtReturnPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/VerifyHeapAtReturnPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,7 +30,7 @@ @Override protected void run(StructuredGraph graph) { - for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) { + for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) { VerifyHeapNode.addBefore(returnNode); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Mon Mar 02 19:11:22 2015 +0100 @@ -331,7 +331,7 @@ processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge, returnNodes.size() > 1); int callerLockDepth = stateAfter.nestedLockDepth(); if (callerLockDepth != 0) { - for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.class)) { + for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.TYPE)) { MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original); monitor.setLockDepth(monitor.getLockDepth() + callerLockDepth); } @@ -389,11 +389,11 @@ } private static void processSimpleInfopoints(Invoke invoke, StructuredGraph inlineGraph, Map duplicates) { - if (inlineGraph.getNodes(SimpleInfopointNode.class).isEmpty()) { + if (inlineGraph.getNodes(SimpleInfopointNode.TYPE).isEmpty()) { return; } BytecodePosition pos = new BytecodePosition(toBytecodePosition(invoke.stateAfter()), invoke.asNode().graph().method(), invoke.bci()); - for (SimpleInfopointNode original : inlineGraph.getNodes(SimpleInfopointNode.class)) { + for (SimpleInfopointNode original : inlineGraph.getNodes(SimpleInfopointNode.TYPE)) { SimpleInfopointNode duplicate = (SimpleInfopointNode) duplicates.get(original); duplicate.addCaller(pos); } @@ -410,7 +410,7 @@ FrameState stateAtReturn = invoke.stateAfter(); FrameState outerFrameState = null; Kind invokeReturnKind = invoke.asNode().getKind(); - for (FrameState original : inlineGraph.getNodes(FrameState.class)) { + for (FrameState original : inlineGraph.getNodes(FrameState.TYPE)) { FrameState frameState = (FrameState) duplicates.get(original); if (frameState != null && frameState.isAlive()) { if (frameState.bci == BytecodeFrame.AFTER_BCI) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Mon Mar 02 19:11:22 2015 +0100 @@ -73,7 +73,7 @@ } public static void getInlinedParameterUsages(Collection parameterUsages, StructuredGraph calleeGraph, Map duplicateMap) { - for (ParameterNode parameter : calleeGraph.getNodes(ParameterNode.class)) { + for (ParameterNode parameter : calleeGraph.getNodes(ParameterNode.TYPE)) { for (Node usage : parameter.usages()) { Node node = duplicateMap.get(usage); if (node != null && node.isAlive()) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Mon Mar 02 19:11:22 2015 +0100 @@ -226,8 +226,10 @@ assert invoke.next() == continuation; invoke.setNext(null); returnMerge.setNext(continuation); - invoke.asNode().replaceAtUsages(returnValuePhi); - invoke.asNode().replaceAndDelete(null); + if (returnValuePhi != null) { + invoke.asNode().replaceAtUsages(returnValuePhi); + } + invoke.asNode().safeDelete(); ArrayList replacementNodes = new ArrayList<>(); @@ -464,7 +466,7 @@ AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); calleeEntryNode.setNext(duplicatedInvoke.asNode()); - AbstractEndNode endNode = graph.add(new EndNode()); + EndNode endNode = graph.add(new EndNode()); duplicatedInvoke.setNext(endNode); returnMerge.addForwardEnd(endNode); @@ -499,7 +501,7 @@ // set new state (pop old exception object, push new one) newExceptionEdge.setStateAfter(stateAfterException.duplicateModified(Kind.Object, newExceptionEdge)); - AbstractEndNode endNode = graph.add(new EndNode()); + EndNode endNode = graph.add(new EndNode()); newExceptionEdge.setNext(endNode); exceptionMerge.addForwardEnd(endNode); exceptionObjectPhi.addInput(newExceptionEdge); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Mon Mar 02 19:11:22 2015 +0100 @@ -143,7 +143,7 @@ private ArrayList replaceParamsWithMoreInformativeArguments(final Invoke invoke, final HighTierContext context) { NodeInputList args = invoke.callTarget().arguments(); ArrayList parameterUsages = null; - List params = graph.getNodes(ParameterNode.class).snapshot(); + List params = graph.getNodes(ParameterNode.TYPE).snapshot(); assert params.size() <= args.size(); /* * param-nodes that aren't used (eg, as a result of canonicalization) don't occur in @@ -211,7 +211,7 @@ if (context.getGraphBuilderSuite() != null) { context.getGraphBuilderSuite().apply(newGraph, context); } - assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite"; + assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite " + method + ", " + method.canBeInlined(); new DeadCodeEliminationPhase(Optional).apply(newGraph); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Mon Mar 02 19:11:22 2015 +0100 @@ -94,7 +94,7 @@ return Collections.EMPTY_SET; } Set result = Node.newSet(); - for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + for (ParameterNode p : graph.getNodes(ParameterNode.TYPE)) { if (freshlyInstantiatedArguments.get(p.index())) { result.add(p); } @@ -186,7 +186,7 @@ } public boolean containsParam(ParameterNode param) { - for (ParameterNode p : graph.getNodes(ParameterNode.class)) { + for (ParameterNode p : graph.getNodes(ParameterNode.TYPE)) { if (p == param) { return true; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Mon Mar 02 19:11:22 2015 +0100 @@ -75,7 +75,7 @@ Map loops = Node.newIdentityMap(EXPECTED_LOOP_COUNT); loops.put(null, new Scope(graph.start(), null)); - for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.class)) { + for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.TYPE)) { createLoopScope(loopBegin, loops); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -54,7 +54,7 @@ /** * Performs the actual verification. - * + * * @throws VerificationError if the verification fails */ protected abstract boolean verify(StructuredGraph graph, C context); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Mon Mar 02 19:11:22 2015 +0100 @@ -101,7 +101,7 @@ if (current.predecessor() == null) { if (current instanceof AbstractMergeNode) { AbstractMergeNode currentMerge = (AbstractMergeNode) current; - NodeInputList currentForwardEnds = currentMerge.forwardEnds(); + NodeInputList currentForwardEnds = currentMerge.forwardEnds(); /* * Use simple iteration instead of streams, since the stream infrastructure adds * many frames which causes the recursion to overflow the stack earlier than it diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Mon Mar 02 19:11:22 2015 +0100 @@ -56,6 +56,8 @@ } boolean stampChanged; + // The algorithm is not guaranteed to reach a stable state. + int z = 0; do { stampChanged = false; /* @@ -72,7 +74,8 @@ } } } - } while (stampChanged); + ++z; + } while (stampChanged && z < 10000); /* * Check that all the illegal stamps we introduced above are correctly replaced with real diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,7 +32,7 @@ /** * Iterates over a list of nodes, which usually comes from * {@link SchedulePhase#getBlockToNodesMap()}. - * + * * While iterating, it is possible to {@link #insert(FixedNode, FixedWithNextNode) insert} and * {@link #replaceCurrent(FixedWithNextNode) replace} nodes. */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Mon Mar 02 19:11:22 2015 +0100 @@ -108,7 +108,7 @@ protected Deque getScopes(StructuredGraph graph) { Deque result = new ArrayDeque<>(); result.push(graph.start()); - for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.class)) { + for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.TYPE)) { result.push(loopBegin); } return result; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -322,11 +322,11 @@ @Override protected void run(StructuredGraph graph) { assert GraphOrder.assertNonCyclicGraph(graph); - cfg = ControlFlowGraph.compute(graph, true, true, true, true); + cfg = ControlFlowGraph.compute(graph, true, true, true, false); earliestCache = graph.createNodeMap(); blockToNodesMap = new BlockMap<>(cfg); - if (selectedStrategy != SchedulingStrategy.EARLIEST) { + if (selectedStrategy != SchedulingStrategy.EARLIEST && graph.isAfterFloatingReadPhase()) { blockToKillSet = new BlockMap<>(cfg); } @@ -359,7 +359,6 @@ for (Block b : getCFG().getBlocks()) { buf.format("==== b: %s (loopDepth: %s). ", b, b.getLoopDepth()); buf.format("dom: %s. ", b.getDominator()); - buf.format("post-dom: %s. ", b.getPostdominator()); buf.format("preds: %s. ", b.getPredecessors()); buf.format("succs: %s ====%n", b.getSuccessors()); BlockMap killSets = blockToKillSet; @@ -621,42 +620,23 @@ * @param earliestBlock */ private Block latestBlock(ValueNode node, SchedulingStrategy strategy, Block earliestBlock) { - CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null); - ensureScheduledUsages(node, strategy); + Block block = null; for (Node usage : node.usages()) { - blocksForUsage(node, usage, cdbc, strategy); - if (cdbc.block == earliestBlock) { + block = blocksForUsage(node, usage, block, earliestBlock, strategy); + if (block == earliestBlock) { break; } } - assert assertLatestBlockResult(node, cdbc); - return cdbc.block; - } - - private boolean assertLatestBlockResult(ValueNode node, CommonDominatorBlockClosure cdbc) throws SchedulingError { - if (cdbc.block != null && !dominates(earliestBlock(node), cdbc.block)) { - throw new SchedulingError("failed to find correct latest schedule for %s. cdbc: %s, earliest: %s", node, cdbc.block, earliestBlock(node)); - } - return true; + assert assertLatestBlockResult(node, block); + return block; } - /** - * A closure that will calculate the common dominator of all blocks passed to its - * {@link #apply(Block)} method. - */ - private static class CommonDominatorBlockClosure implements BlockClosure { - - public Block block; - - public CommonDominatorBlockClosure(Block block) { - this.block = block; + private boolean assertLatestBlockResult(ValueNode node, Block block) throws SchedulingError { + if (block != null && !dominates(earliestBlock(node), block)) { + throw new SchedulingError("failed to find correct latest schedule for %s. cdbc: %s, earliest: %s", node, block, earliestBlock(node)); } - - @Override - public void apply(Block newBlock) { - this.block = commonDominatorTyped(this.block, newBlock); - } + return true; } /** @@ -671,41 +651,32 @@ if (earliest != null) { return earliest; } + return earliestBlockHelper(node, earliest); + } + + private Block earliestBlockHelper(Node node, Block earliestStart) throws SchedulingError { /* * All inputs must be in a dominating block, otherwise the graph cannot be scheduled. This * implies that the inputs' blocks have a total ordering via their dominance relation. So in * order to find the earliest block placement for this node we need to find the input block * that is dominated by all other input blocks. */ + Block earliest = earliestStart; if (node.predecessor() != null) { throw new SchedulingError(); } - for (Node input : node.inputs().nonNull()) { - assert input instanceof ValueNode; - Block inputEarliest; - if (input instanceof InvokeWithExceptionNode) { - inputEarliest = cfg.getNodeToBlock().get(((InvokeWithExceptionNode) input).next()); - } else { - inputEarliest = earliestBlock(input); - } - if (earliest == null) { - earliest = inputEarliest; - } else if (earliest != inputEarliest) { - // Find out whether earliest or inputEarliest is earlier. - Block a = earliest.getDominator(); - Block b = inputEarliest; - while (true) { - if (a == inputEarliest || b == null) { - // Nothing to change, the previous earliest block is still earliest. - break; - } else if (b == earliest || a == null) { - // New earliest is the earliest. - earliest = inputEarliest; - break; - } - a = a.getDominator(); - b = b.getDominator(); + for (Node input : node.inputs()) { + if (input != null) { + assert input instanceof ValueNode; + Block inputEarliest; + if (input instanceof InvokeWithExceptionNode) { + inputEarliest = cfg.getNodeToBlock().get(((InvokeWithExceptionNode) input).next()); + } else { + inputEarliest = earliestBlock(input); + } + if (earliest == null || earliest.getDominatorDepth() < inputEarliest.getDominatorDepth()) { + earliest = inputEarliest; } } } @@ -732,14 +703,19 @@ } Block cur = latestBlock; Block result = latestBlock; - while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) { - Block dom = cur.getDominator(); - if (dom.getLoopDepth() < result.getLoopDepth()) { - result = dom; + Loop earliestLoop = earliest.getLoop(); + while (true) { + Loop curLoop = cur.getLoop(); + if (curLoop == earliestLoop) { + return result; + } else { + Block dom = cur.getDominator(); + if (dom.getLoopDepth() < result.getLoopDepth()) { + result = dom; + } + cur = dom; } - cur = dom; } - return result; } /** @@ -748,11 +724,11 @@ * * @param node the node that needs to be scheduled * @param usage the usage whose blocks need to be considered - * @param closure the closure that will be called for each block + * @param earliestBlock */ - private void blocksForUsage(ValueNode node, Node usage, CommonDominatorBlockClosure closure, SchedulingStrategy strategy) { + private Block blocksForUsage(ValueNode node, Node usage, Block startCurrentBlock, Block earliestBlock, SchedulingStrategy strategy) { assert !(node instanceof PhiNode); - + Block currentBlock = startCurrentBlock; if (usage instanceof PhiNode) { // An input to a PhiNode is used at the end of the predecessor block that corresponds to // the PhiNode input. @@ -763,7 +739,10 @@ Block mergeBlock = cfg.getNodeToBlock().get(merge); for (int i = 0; i < phi.valueCount(); ++i) { if (phi.valueAt(i) == node) { - closure.apply(mergeBlock.getPredecessors().get(i)); + currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, mergeBlock.getPredecessors().get(i)); + if (currentBlock == earliestBlock) { + break; + } } } } else if (usage instanceof VirtualState) { @@ -773,19 +752,19 @@ if (unscheduledUsage instanceof VirtualState) { // If a FrameState is an outer FrameState this method behaves as if the inner // FrameState was the actual usage, by recursing. - blocksForUsage(node, unscheduledUsage, closure, strategy); + currentBlock = blocksForUsage(node, unscheduledUsage, currentBlock, earliestBlock, strategy); } else if (unscheduledUsage instanceof AbstractBeginNode) { // Only FrameStates can be connected to BeginNodes. if (!(usage instanceof FrameState)) { throw new SchedulingError(usage.toString()); } if (unscheduledUsage instanceof StartNode) { - closure.apply(cfg.getNodeToBlock().get(unscheduledUsage)); + currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, cfg.getNodeToBlock().get(unscheduledUsage)); } else { // If a FrameState belongs to a BeginNode then it's inputs will be placed at // the common dominator of all EndNodes. for (Node pred : unscheduledUsage.cfgPredecessors()) { - closure.apply(cfg.getNodeToBlock().get(pred)); + currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, cfg.getNodeToBlock().get(pred)); } } } else { @@ -798,21 +777,18 @@ } // Otherwise: Put the input into the same block as the usage. assignBlockToNode((ValueNode) unscheduledUsage, strategy); - closure.apply(cfg.getNodeToBlock().get(unscheduledUsage)); + currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, cfg.getNodeToBlock().get(unscheduledUsage)); + } + if (currentBlock == earliestBlock) { + break; } } } else { // All other types of usages: Put the input into the same block as the usage. assignBlockToNode((ValueNode) usage, strategy); - closure.apply(cfg.getNodeToBlock().get(usage)); + currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, cfg.getNodeToBlock().get(usage)); } - } - - private void ensureScheduledUsages(Node node, SchedulingStrategy strategy) { - for (Node usage : node.usages().filter(ValueNode.class)) { - assignBlockToNode((ValueNode) usage, strategy); - } - // now true usages are ready + return currentBlock; } private void sortNodesWithinBlocks(StructuredGraph graph, SchedulingStrategy strategy) { @@ -1071,20 +1047,23 @@ return; } + if (i instanceof LoopExitNode) { + LoopExitNode loopExitNode = (LoopExitNode) i; + for (ProxyNode proxy : loopExitNode.proxies()) { + addToLatestSorting(proxy, state); + } + } + + addToLatestSortingHelper(i, state); + } + + private void addToLatestSortingHelper(ValueNode i, SortState state) { FrameState stateAfter = null; if (i instanceof StateSplit) { stateAfter = ((StateSplit) i).stateAfter(); } - for (Node input : i.inputs()) { - if (input instanceof FrameState) { - if (input != stateAfter) { - addUnscheduledToLatestSorting((FrameState) input, state); - } - } else { - addToLatestSorting((ValueNode) input, state); - } - } + addInputsToLatestSorting(i, state, stateAfter); if (state.readsSize() != 0) { if (i instanceof MemoryCheckpoint.Single) { @@ -1112,6 +1091,18 @@ } } + private void addInputsToLatestSorting(ValueNode i, SortState state, FrameState stateAfter) { + for (Node input : i.inputs()) { + if (input instanceof FrameState) { + if (input != stateAfter) { + addUnscheduledToLatestSorting((FrameState) input, state); + } + } else { + addToLatestSorting((ValueNode) input, state); + } + } + } + /** * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over * all usages. The resulting list is reversed to create an earliest-possible scheduling of diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,9 +24,9 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.lir.phases.*; -import com.oracle.graal.lir.phases.LIRHighTierPhase.*; -import com.oracle.graal.lir.phases.LIRLowTierPhase.*; -import com.oracle.graal.lir.phases.LIRMidTierPhase.*; +import com.oracle.graal.lir.phases.PreAllocationOptimizationPhase.*; +import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.*; +import com.oracle.graal.lir.phases.AllocationPhase.*; import com.oracle.graal.phases.*; public interface CompilerConfiguration extends Service { @@ -37,9 +37,9 @@ PhaseSuite createLowTier(); - LIRPhaseSuite createLIRHighTier(); + LIRPhaseSuite createPreAllocationOptimizationStage(); - LIRPhaseSuite createLIRMidTier(); + LIRPhaseSuite createAllocationStage(); - LIRPhaseSuite createLIRLowTier(); + LIRPhaseSuite createPostAllocationOptimizationStage(); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Mon Mar 02 19:11:22 2015 +0100 @@ -133,7 +133,8 @@ public static LIRSuites createDefaultLIRSuites() { String selected = CompilerConfiguration.getValue(); if (selected.equals("")) { - return new LIRSuites(defaultConfiguration.createLIRHighTier(), defaultConfiguration.createLIRMidTier(), defaultConfiguration.createLIRLowTier()); + return new LIRSuites(defaultConfiguration.createPreAllocationOptimizationStage(), defaultConfiguration.createAllocationStage(), + defaultConfiguration.createPostAllocationOptimizationStage()); } else { return createLIRSuites(selected); } @@ -144,7 +145,7 @@ if (config == null) { throw new GraalInternalError("unknown compiler configuration: " + name); } - return new LIRSuites(config.createLIRHighTier(), config.createLIRMidTier(), config.createLIRLowTier()); + return new LIRSuites(config.createPreAllocationOptimizationStage(), config.createAllocationStage(), config.createPostAllocationOptimizationStage()); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,7 +37,7 @@ /** * Adds a block to this list in an unsorted fashion, like a stack. - * + * * @param block the block to add */ public void add(AbstractMergeNode block) { @@ -55,7 +55,7 @@ /** * Adds a block to this list, sorted by the supplied number. The block with the lowest number is * returned upon subsequent removes. - * + * * @param block the block to add * @param number the number used to sort the block */ @@ -89,7 +89,7 @@ * Removes the next block from this work list. If the blocks have been added in a sorted order, * then the block with the lowest number is returned. Otherwise, the last block added is * returned. - * + * * @return the next block in the list */ public AbstractMergeNode removeFromWorkList() { @@ -101,7 +101,7 @@ /** * Checks whether the list is empty. - * + * * @return {@code true} if this list is empty */ public boolean isEmpty() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Mon Mar 02 19:11:22 2015 +0100 @@ -165,8 +165,8 @@ pendingStateAfter.applyToNonVirtual(new NodeClosure() { @Override public void apply(Node usage, Node nonVirtualNode) { - assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + - " before " + node + " in block " + block + " \n" + list; + assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list; } }); pendingStateAfter = null; @@ -208,7 +208,8 @@ } }); } else { - assert currentState.isMarked(input) || input instanceof VirtualObjectNode : input + " not available at " + node + " in block " + block + "\n" + list; + assert currentState.isMarked(input) || input instanceof VirtualObjectNode || input instanceof ConstantNode : input + " not available at " + node + + " in block " + block + "\n" + list; } } } @@ -217,7 +218,8 @@ AbstractMergeNode merge = ((AbstractEndNode) node).merge(); for (PhiNode phi : merge.phis()) { ValueNode phiValue = phi.valueAt((AbstractEndNode) node); - assert phiValue == null || currentState.isMarked(phiValue) : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block; + assert phiValue == null || currentState.isMarked(phiValue) || phiValue instanceof ConstantNode : phiValue + " not available at phi " + phi + " / end " + node + + " in block " + block; } } if (stateAfter != null) { @@ -230,8 +232,8 @@ pendingStateAfter.applyToNonVirtual(new NodeClosure() { @Override public void apply(Node usage, Node nonVirtualNode) { - assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + - " at end of block " + block + " \n" + list; + assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + + " not available at virtualstate " + usage + " at end of block " + block + " \n" + list; } }); } @@ -249,7 +251,9 @@ @Override protected NodeBitMap getInitialState() { - return graph.createNodeBitMap(); + NodeBitMap ret = graph.createNodeBitMap(); + ret.markAll(graph.getNodes().filter(ConstantNode.class)); + return ret; } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyDebugUsage.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyDebugUsage.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyDebugUsage.java Mon Mar 02 19:11:22 2015 +0100 @@ -39,7 +39,7 @@ @Override protected boolean verify(StructuredGraph graph, PhaseContext context) { - for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { ResolvedJavaMethod callee = t.targetMethod(); ResolvedJavaType debugType = context.getMetaAccess().lookupJavaType(Debug.class); if (callee.getDeclaringClass().equals(debugType)) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Mar 02 19:11:22 2015 +0100 @@ -294,7 +294,7 @@ writeString(type.toJavaName()); writeByte(KLASS); } else if (object instanceof NodeClass) { - NodeClass nodeClass = (NodeClass) object; + NodeClass nodeClass = (NodeClass) object; writeByte(POOL_NODE_CLASS); writeString(nodeClass.getJavaClass().getSimpleName()); writeString(nodeClass.getNameTemplate()); @@ -330,7 +330,7 @@ } } - private void writeEdgesInfo(NodeClass nodeClass, Edges.Type type) throws IOException { + private void writeEdgesInfo(NodeClass nodeClass, Edges.Type type) throws IOException { Edges edges = nodeClass.getEdges(type); writeShort((char) edges.getCount()); for (int i = 0; i < edges.getCount(); i++) { @@ -412,7 +412,7 @@ writeInt(graph.getNodeCount()); for (Node node : graph.getNodes()) { - NodeClass nodeClass = node.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); node.getDebugProperties(props); if (probabilities != null && node instanceof FixedNode) { try { @@ -439,13 +439,14 @@ } private void writeEdges(Node node, Edges.Type type) throws IOException { - NodeClass nodeClass = node.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); Edges edges = nodeClass.getEdges(type); + final long[] curOffsets = edges.getOffsets(); for (int i = 0; i < edges.getDirectCount(); i++) { - writeNodeRef(edges.getNode(node, i)); + writeNodeRef(Edges.getNode(node, curOffsets, i)); } for (int i = edges.getDirectCount(); i < edges.getCount(); i++) { - NodeList list = edges.getNodeList(node, i); + NodeList list = Edges.getNodeList(node, curOffsets, i); if (list == null) { writeShort((char) 0); } else { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,7 +33,6 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.graph.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.lir.*; import com.oracle.graal.lir.alloc.lsra.*; import com.oracle.graal.lir.alloc.lsra.Interval.*; @@ -131,10 +130,10 @@ * @param label A label describing the compilation phase that produced the control flow graph. * @param blocks The list of blocks to be printed. */ - public void printCFG(String label, List> blocks, boolean printNodes) { + public void printCFG(String label, List> blocks, boolean printNodes) { if (lir == null) { latestScheduling = new NodeMap<>(cfg.getNodeToBlock()); - for (AbstractBlock abstractBlock : blocks) { + for (AbstractBlockBase abstractBlock : blocks) { Block block = (Block) abstractBlock; Node cur = block.getBeginNode(); while (true) { @@ -152,7 +151,7 @@ begin("cfg"); out.print("name \"").print(label).println('"'); - for (AbstractBlock block : blocks) { + for (AbstractBlockBase block : blocks) { printBlock(block, printNodes); } end("cfg"); @@ -194,7 +193,7 @@ } } - private void printBlock(AbstractBlock block, boolean printNodes) { + private void printBlock(AbstractBlockBase block, boolean printNodes) { printBlockProlog(block); if (printNodes) { assert block instanceof Block; @@ -203,31 +202,26 @@ printBlockEpilog(block); } - private void printBlockEpilog(AbstractBlock block) { + private void printBlockEpilog(AbstractBlockBase block) { printLIR(block); end("block"); } - private void printBlockProlog(AbstractBlock block) { + private void printBlockProlog(AbstractBlockBase block) { begin("block"); out.print("name \"").print(blockToString(block)).println('"'); - if (block instanceof BciBlock) { - out.print("from_bci ").println(((BciBlock) block).startBci); - out.print("to_bci ").println(((BciBlock) block).endBci); - } else { - out.println("from_bci -1"); - out.println("to_bci -1"); - } + out.println("from_bci -1"); + out.println("to_bci -1"); out.print("predecessors "); - for (AbstractBlock pred : block.getPredecessors()) { + for (AbstractBlockBase pred : block.getPredecessors()) { out.print("\"").print(blockToString(pred)).print("\" "); } out.println(); out.print("successors "); - for (AbstractBlock succ : block.getSuccessors()) { + for (AbstractBlockBase succ : block.getSuccessors()) { if (!succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } @@ -235,7 +229,7 @@ out.println(); out.print("xhandlers"); - for (AbstractBlock succ : block.getSuccessors()) { + for (AbstractBlockBase succ : block.getSuccessors()) { if (succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } @@ -437,7 +431,7 @@ * * @param block the block to print */ - private void printLIR(AbstractBlock block) { + private void printLIR(AbstractBlockBase block) { if (lir == null) { return; } @@ -500,7 +494,7 @@ return prefix + node.toString(Verbosity.Id); } - private String blockToString(AbstractBlock block) { + private String blockToString(AbstractBlockBase block) { if (lir == null && schedule == null && block instanceof Block) { // During all the front-end phases, the block schedule is built only for the debug // output. diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Mon Mar 02 19:11:22 2015 +0100 @@ -39,23 +39,23 @@ * *
        *     HexCodeFile ::= Platform Delim HexCode Delim (OptionalSection Delim)*
      - * 
      + *
        *     OptionalSection ::= Comment | OperandComment | JumpTable | LookupTable
      - * 
      + *
        *     Platform ::= "Platform" ISA WordWidth
      - * 
      + *
        *     HexCode ::= "HexCode" StartAddress HexDigits
      - * 
      + *
        *     Comment ::= "Comment" Position String
      - * 
      + *
        *     OperandComment ::= "OperandComment" Position String
      - * 
      + *
        *     JumpTable ::= "JumpTable" Position EntrySize Low High
      - * 
      + *
        *     LookupTable ::= "LookupTable" Position NPairs KeySize OffsetSize
      - * 
      + *
        *     Position, EntrySize, Low, High, NPairs KeySize OffsetSize ::= int
      - * 
      + *
        *     Delim := "<||@"
        * 
      * diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,6 +25,7 @@ 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,9 +37,10 @@ */ @NodeInfo public final class AMD64CountLeadingZerosNode extends UnaryNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AMD64CountLeadingZerosNode.class); public AMD64CountLeadingZerosNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + super(TYPE, StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,9 +37,10 @@ */ @NodeInfo public final class AMD64CountTrailingZerosNode extends UnaryNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AMD64CountTrailingZerosNode.class); public AMD64CountTrailingZerosNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + super(TYPE, StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -38,11 +39,12 @@ */ @NodeInfo public final class AMD64FloatConvertNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AMD64FloatConvertNode.class); protected final FloatConvert op; public AMD64FloatConvertNode(FloatConvert op, ValueNode value) { - super(table -> table.getFloatConvert(op), value); + super(TYPE, table -> table.getFloatConvert(op), value); this.op = op; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -335,7 +335,7 @@ new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); - Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asJavaConstant().asLong() == 0); + Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0); } public static final int[] constantArray3 = new int[]{1, 2, 3}; @@ -351,7 +351,7 @@ new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); - Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asJavaConstant().asLong() == 1); + Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1); } public static boolean testCanonicalEqualSnippet() { @@ -367,7 +367,7 @@ new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); - Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asJavaConstant().asLong() == 1); + Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1); } public static boolean testVirtualEqualSnippet() { @@ -385,7 +385,7 @@ new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); - Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asJavaConstant().asLong() == 0); + Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0); } public static boolean testVirtualNotEqualSnippet(int x) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -253,12 +253,12 @@ canonicalizer.apply(graph, context); new InliningPhase(canonicalizer).apply(graph, context); canonicalizer.apply(graph, context); - Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); + Assert.assertEquals(1, graph.getNodes(ReturnNode.TYPE).count()); if (expectedClass != null) { if (graph.getNodes().filter(expectedClass).count() == 0) { return null; } } - return graph.getNodes(ReturnNode.class).first().result(); + return graph.getNodes(ReturnNode.TYPE).first().result(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -29,7 +29,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Edges.Type; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; @@ -45,11 +44,13 @@ @NodeInfo static final class TestNode extends Node { + public static final NodeClass TYPE = NodeClass.create(TestNode.class); @Input NodeInputList itail; @Input ConstantNode i1; @Input FloatingNode i2; public TestNode() { + super(TYPE); } } @@ -72,25 +73,25 @@ node.i1 = i1; node.i2 = i2; graph.add(node); - inputs = node.getNodeClass().getEdges(Type.Inputs); + inputs = node.getNodeClass().getInputEdges(); } /** * Checks that there are no checkcasts in the compiled version of - * {@link Edges#getNode(Node, int)}. + * {@link Edges#getNode(Node, long[], int)}. */ @Test public void test0() { - testMethod(getMethod("getNode", Node.class, int.class), inputs, node, 0); + testMethod(getMethod("getNode", Node.class, long[].class, int.class), null, node, inputs.getOffsets(), 0); } /** * Checks that there are no checkcasts in the compiled version of - * {@link Edges#getNodeList(Node, int)}. + * {@link Edges#getNodeList(Node, long[], int)}. */ @Test public void test1() { - testMethod(getMethod("getNodeList", Node.class, int.class), inputs, node, 2); + testMethod(getMethod("getNodeList", Node.class, long[].class, int.class), null, node, inputs.getOffsets(), 2); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java Mon Mar 02 19:11:22 2015 +0100 @@ -149,7 +149,7 @@ /** * Returns the kind from the character describing a primitive or void. - * + * * @param ch the character * @return the kind */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,22 +40,12 @@ public class EdgesSubstitutions { @MethodSubstitution - private static Node getNode(Node node, long offset) { + private static Node getNodeUnsafe(Node node, long offset) { return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), Node.class); } @MethodSubstitution - private static NodeList getNodeList(Node node, long offset) { + private static NodeList getNodeListUnsafe(Node node, long offset) { return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), NodeList.class); } - - @MethodSubstitution - private static void putNode(Node node, long offset, Node value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution - private static void putNodeList(Node node, long offset, NodeList value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); - } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Log.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Log.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Log.java Mon Mar 02 19:11:22 2015 +0100 @@ -80,7 +80,7 @@ /** * Prints a formatted string to the log stream. - * + * * @param format a C style printf format value that can contain at most one conversion specifier * (i.e., a sequence of characters starting with '%'). * @param value the value associated with the conversion specifier diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -64,7 +64,7 @@ @Override protected void run(StructuredGraph graph) { ArrayList cleanUpReturnList = new ArrayList<>(); - for (MethodCallTargetNode node : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode node : graph.getNodes(MethodCallTargetNode.TYPE)) { tryIntrinsify(node, cleanUpReturnList); } @@ -80,21 +80,12 @@ NodeIntrinsic intrinsic = getIntrinsic(target); if (intrinsic != null) { - assert target.getAnnotation(Fold.class) == null; - assert target.isStatic() : "node intrinsic must be static: " + target; - - ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass); - - // Prepare the arguments for the reflective constructor call on the node class. - Object[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false); - if (nodeConstructorArguments == null) { + Stamp stamp = methodCallTargetNode.invoke().asNode().stamp(); + Node newInstance = createIntrinsicNode(methodCallTargetNode.arguments(), stamp, target, graph, intrinsic); + if (newInstance == null) { return false; } - // Create the new node instance. - ResolvedJavaType c = getNodeClass(target, intrinsic); - Node newInstance = createNodeInstance(graph, c, parameterTypes, methodCallTargetNode.invoke().asNode().stamp(), intrinsic.setStampFromReturnType(), nodeConstructorArguments); - // Replace the invoke with the new node. newInstance = graph.addOrUnique(newInstance); methodCallTargetNode.invoke().intrinsify(newInstance); @@ -103,21 +94,10 @@ cleanUpReturnList.add(newInstance); } else if (isFoldable(target)) { ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass); - - // Prepare the arguments for the reflective method call - JavaConstant[] arguments = (JavaConstant[]) prepareArguments(methodCallTargetNode, parameterTypes, target, true); - if (arguments == null) { + JavaConstant constant = tryFold(methodCallTargetNode.arguments(), parameterTypes, target); + if (constant != null && constant.equals(COULD_NOT_FOLD)) { return false; } - JavaConstant receiver = null; - if (!methodCallTargetNode.isStatic()) { - receiver = arguments[0]; - arguments = Arrays.copyOfRange(arguments, 1, arguments.length); - parameterTypes = Arrays.copyOfRange(parameterTypes, 1, parameterTypes.length); - } - - // Call the method - JavaConstant constant = target.invoke(receiver, arguments); if (constant != null) { // Replace the invoke with the result of the call @@ -134,17 +114,83 @@ return true; } + @SuppressWarnings("serial") public static final JavaConstant COULD_NOT_FOLD = new PrimitiveConstant(Kind.Illegal, 100) { + @Override + public boolean equals(Object o) { + return this == o; + } + }; + + public JavaConstant tryFold(List args, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target) { + JavaConstant[] reflectArgs = (JavaConstant[]) prepareArguments(args, parameterTypes, target, true); + if (reflectArgs == null) { + return COULD_NOT_FOLD; + } + JavaConstant receiver = null; + if (!target.isStatic()) { + receiver = reflectArgs[0]; + reflectArgs = Arrays.copyOfRange(reflectArgs, 1, reflectArgs.length); + } + + // Call the method + return target.invoke(receiver, reflectArgs); + } + + private static boolean areAllConstant(List arguments) { + for (ValueNode arg : arguments) { + if (!arg.isConstant()) { + return false; + } + } + return true; + } + + /** + * Attempts to create a node to replace a call to a {@link NodeIntrinsic} annotated method. + * + * @param arguments the arguments of the call + * @param stamp the stamp to use for the returned node + * @param method the method annotated with {@link NodeIntrinsic} + * @param graph the graph into which the created node will be added + * @return a {@link ConstantNode} if the intrinsic could be + * {@linkplain NodeIntrinsic#foldable() folded}, {@code null} if intrinsification could + * not (yet) be performed, otherwise the node representing the intrinsic + */ + public ValueNode createIntrinsicNode(List arguments, Stamp stamp, ResolvedJavaMethod method, StructuredGraph graph, NodeIntrinsic intrinsic) { + assert method.getAnnotation(Fold.class) == null; + assert method.isStatic() : "node intrinsic must be static: " + method; + + ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); + + if (intrinsic.foldable() && areAllConstant(arguments)) { + JavaConstant res = tryFold(arguments, parameterTypes, method); + if (!res.equals(COULD_NOT_FOLD)) { + return ConstantNode.forConstant(res, providers.getMetaAccess()); + } + } + + // Prepare the arguments for the reflective constructor call on the node class. + Object[] nodeConstructorArguments = prepareArguments(arguments, parameterTypes, method, false); + if (nodeConstructorArguments == null) { + return null; + } + + // Create the new node instance. + ResolvedJavaType c = getNodeClass(method, intrinsic); + return createNodeInstance(graph, c, parameterTypes, stamp, intrinsic.setStampFromReturnType(), nodeConstructorArguments); + } + /** * Permits a subclass to override the default definition of "intrinsic". */ - protected NodeIntrinsic getIntrinsic(ResolvedJavaMethod method) { + public NodeIntrinsic getIntrinsic(ResolvedJavaMethod method) { return method.getAnnotation(Node.NodeIntrinsic.class); } /** * Permits a subclass to override the default definition of "foldable". */ - protected boolean isFoldable(ResolvedJavaMethod method) { + public boolean isFoldable(ResolvedJavaMethod method) { return method.getAnnotation(Fold.class) != null; } @@ -156,12 +202,11 @@ * @return the arguments for the reflective invocation or null if an argument of {@code invoke} * that is expected to be constant isn't */ - private Object[] prepareArguments(MethodCallTargetNode methodCallTargetNode, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) { - NodeInputList arguments = methodCallTargetNode.arguments(); + private Object[] prepareArguments(List arguments, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) { Object[] reflectionCallArguments = folding ? new JavaConstant[arguments.size()] : new Object[arguments.size()]; for (int i = 0; i < reflectionCallArguments.length; ++i) { int parameterIndex = i; - if (!methodCallTargetNode.isStatic()) { + if (!target.isStatic()) { parameterIndex--; } ValueNode argument = arguments.get(i); @@ -226,7 +271,7 @@ return result; } - protected Node createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType, + protected ValueNode createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType, Object[] nodeConstructorArguments) { ResolvedJavaMethod constructor = null; Object[] arguments = null; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -43,7 +43,7 @@ @Override protected void run(StructuredGraph graph) { - for (MethodCallTargetNode n : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode n : graph.getNodes(MethodCallTargetNode.TYPE)) { checkInvoke(n); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -64,6 +64,7 @@ public final Providers providers; public final SnippetReflectionProvider snippetReflection; public final TargetDescription target; + public final NodeIntrinsificationPhase nodeIntrinsificationPhase; /** * The preprocessed replacement graphs. @@ -227,6 +228,7 @@ this.target = target; this.graphs = new ConcurrentHashMap<>(); this.snippetTemplateCache = CollectionsFactory.newMap(); + this.nodeIntrinsificationPhase = createNodeIntrinsificationPhase(); } private static final boolean UseSnippetGraphCache = Boolean.parseBoolean(System.getProperty("graal.useSnippetGraphCache", "true")); @@ -285,7 +287,7 @@ // Do deferred intrinsification of node intrinsics - createNodeIntrinsificationPhase().apply(specializedSnippet); + nodeIntrinsificationPhase.apply(specializedSnippet); new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers)); NodeIntrinsificationVerificationPhase.verify(specializedSnippet); } @@ -531,13 +533,13 @@ * Does final processing of a snippet graph. */ protected void finalizeGraph(StructuredGraph graph) { - replacements.createNodeIntrinsificationPhase().apply(graph); + replacements.nodeIntrinsificationPhase.apply(graph); if (!SnippetTemplate.hasConstantParameter(method)) { NodeIntrinsificationVerificationPhase.verify(graph); } int sideEffectCount = 0; assert (sideEffectCount = graph.getNodes().filter(e -> hasSideEffect(e)).count()) >= 0; - new ConvertDeoptimizeToGuardPhase().apply(graph); + new ConvertDeoptimizeToGuardPhase().apply(graph, null); assert sideEffectCount == graph.getNodes().filter(e -> hasSideEffect(e)).count() : "deleted side effecting node"; switch (frameStateProcessing) { @@ -666,7 +668,7 @@ * Called after all inlining for a given graph is complete. */ protected void afterInlining(StructuredGraph graph) { - replacements.createNodeIntrinsificationPhase().apply(graph); + replacements.nodeIntrinsificationPhase.apply(graph); new DeadCodeEliminationPhase(Optional).apply(graph); if (OptCanonicalizer.getValue()) { new CanonicalizerPhase(true).apply(graph, new PhaseContext(replacements.providers)); @@ -679,7 +681,7 @@ final StructuredGraph graph = buildInitialGraph(methodToParse); try (Scope s = Debug.scope("buildGraph", graph)) { Set doNotInline = null; - for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { if (doNotInline != null && doNotInline.contains(callTarget)) { continue; } @@ -735,7 +737,7 @@ afterInlining(graph); - for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { + for (LoopEndNode end : graph.getNodes(LoopEndNode.TYPE)) { end.disableSafepoint(); } @@ -828,6 +830,12 @@ } @Override + public ResolvedJavaMethod getMethodSubstitutionMethod(ResolvedJavaMethod original) { + ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName()); + return cr == null ? null : cr.methodSubstitutions.get(original); + } + + @Override public void registerSnippetTemplateCache(SnippetTemplateCache templates) { assert snippetTemplateCache.get(templates.getClass().getName()) == null; snippetTemplateCache.put(templates.getClass().getName(), templates); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Mar 02 19:11:22 2015 +0100 @@ -45,6 +45,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.Graph.Mark; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node; import com.oracle.graal.loop.*; import com.oracle.graal.nodeinfo.*; @@ -392,12 +393,13 @@ } @NodeInfo - static class VarargsPlaceholderNode extends FloatingNode implements ArrayLengthProvider { + static final class VarargsPlaceholderNode extends FloatingNode implements ArrayLengthProvider { + public static final NodeClass TYPE = NodeClass.create(VarargsPlaceholderNode.class); protected final Varargs varargs; public VarargsPlaceholderNode(Varargs varargs, MetaAccessProvider metaAccess) { - super(StampFactory.exactNonNull(metaAccess.lookupJavaType(varargs.componentType).getArrayClass())); + super(TYPE, StampFactory.exactNonNull(metaAccess.lookupJavaType(varargs.componentType).getArrayClass())); this.varargs = varargs; } @@ -721,7 +723,7 @@ assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders); - new FloatingReadPhase(false, true, false).apply(snippetCopy); + new FloatingReadPhase(false, true).apply(snippetCopy); MemoryAnchorNode memoryAnchor = snippetCopy.add(new MemoryAnchorNode()); snippetCopy.start().replaceAtUsages(InputType.Memory, memoryAnchor); @@ -736,7 +738,7 @@ } else { snippetCopy.addAfterFixed(snippetCopy.start(), memoryAnchor); } - List returnNodes = snippet.getNodes(ReturnNode.class).snapshot(); + List returnNodes = snippet.getNodes(ReturnNode.TYPE).snapshot(); if (returnNodes.isEmpty()) { this.returnNode = null; } else if (returnNodes.size() == 1) { @@ -746,7 +748,7 @@ 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)); - MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps, false); + MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps); MemoryMapNode memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap())); this.returnNode.setMemoryMap(memoryMap); for (MemoryMapNode mm : memMaps) { @@ -1219,7 +1221,7 @@ Node stampDup = duplicates.get(stampNode); ((ValueNode) stampDup).setStamp(replacee.stamp()); } - for (ParameterNode paramNode : snippet.getNodes(ParameterNode.class)) { + for (ParameterNode paramNode : snippet.getNodes(ParameterNode.TYPE)) { for (Node usage : paramNode.usages()) { Node usageDup = duplicates.get(usage); propagateStamp(usageDup); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.java.GraphBuilderContext.*; +import static java.lang.Character.*; +import sun.misc.*; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.InvocationPlugins.Registration; +import com.oracle.graal.java.InvocationPlugins.Registration.Receiver; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.debug.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Provides non-runtime specific {@link InvocationPlugin}s. + */ +public class StandardGraphBuilderPlugins { + + public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + registerObjectPlugins(metaAccess, plugins); + registerMathPlugins(metaAccess, plugins); + registerUnsafePlugins(metaAccess, plugins); + registerGraalDirectivesPlugins(metaAccess, plugins); + } + + public static void registerUnsafePlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Unsafe.class); + for (Kind kind : Kind.values()) { + if ((kind.isPrimitive() && kind != Kind.Void) || kind == Kind.Object) { + String kindName = kind.getJavaName(); + kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); + String getName = "get" + kindName; + String putName = "put" + kindName; + r.register3(getName, Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, false)); + r.register4(putName, Receiver.class, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), new UnsafePutPlugin(kind, false)); + r.register3(getName + "Volatile", Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, true)); + r.register4(putName + "Volatile", Receiver.class, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), new UnsafePutPlugin(kind, true)); + if (kind != Kind.Boolean && kind != Kind.Object) { + r.register2(getName, Receiver.class, long.class, new UnsafeGetPlugin(kind, false)); + r.register3(putName, Receiver.class, long.class, kind.toJavaClass(), new UnsafePutPlugin(kind, false)); + } + } + } + } + + public static void registerMathPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Math.class); + r.register1("abs", Float.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(Kind.Float, builder.append(new AbsNode(value))); + return true; + } + }); + r.register1("abs", Double.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(Kind.Double, builder.append(new AbsNode(value))); + return true; + } + }); + r.register1("sqrt", Double.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(Kind.Double, builder.append(new SqrtNode(value))); + return true; + } + }); + + for (Kind kind : Kind.values()) { + if (kind.isPrimitive() && kind != Kind.Void) { + new BoxPlugin(kind).register(metaAccess, plugins); + new UnboxPlugin(kind).register(metaAccess, plugins); + } + } + } + + public static void registerObjectPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Object.class); + r.register1("", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode object) { + if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { + builder.append(new RegisterFinalizerNode(object)); + } + return true; + } + }); + } + + static class BoxPlugin implements InvocationPlugin { + + private final Kind kind; + + BoxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); + builder.push(Kind.Object, builder.append(new BoxNode(value, resultType, kind))); + return true; + } + + void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass()); + plugins.register(method, this); + } + } + + static class UnboxPlugin implements InvocationPlugin { + + private final Kind kind; + + UnboxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); + builder.push(kind.getStackKind(), builder.append(valueNode)); + return true; + } + + void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + String name = kind.toJavaClass().getSimpleName() + "Value"; + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); + plugins.register(method, this); + } + } + + static class UnsafeGetPlugin implements InvocationPlugin { + + private final Kind returnKind; + private final boolean isVolatile; + + public UnsafeGetPlugin(Kind returnKind, boolean isVolatile) { + this.returnKind = returnKind; + this.isVolatile = isVolatile; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode address) { + builder.push(returnKind.getStackKind(), builder.append(new DirectReadNode(address, returnKind))); + return true; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset) { + if (isVolatile) { + builder.append(new MembarNode(JMM_PRE_VOLATILE_READ)); + } + builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, LocationIdentity.ANY_LOCATION))); + if (isVolatile) { + builder.append(new MembarNode(JMM_POST_VOLATILE_READ)); + } + return true; + } + } + + static class UnsafePutPlugin implements InvocationPlugin { + + private final Kind kind; + private final boolean isVolatile; + + public UnsafePutPlugin(Kind kind, boolean isVolatile) { + this.kind = kind; + this.isVolatile = isVolatile; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode address, ValueNode value) { + builder.append(new DirectStoreNode(address, value, kind)); + return true; + } + + public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset, ValueNode value) { + if (isVolatile) { + builder.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + } + builder.append(new UnsafeStoreNode(object, offset, value, kind, LocationIdentity.ANY_LOCATION)); + if (isVolatile) { + builder.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + } + return true; + } + } + + public static void registerGraalDirectivesPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, GraalDirectives.class); + r.register0("deoptimize", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + return true; + } + }); + + r.register0("deoptimizeAndInvalidate", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + return true; + } + }); + + r.register0("inCompiledCode", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.push(Kind.Int, builder.append(ConstantNode.forInt(1))); + return true; + } + }); + + r.register0("controlFlowAnchor", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.append(new ControlFlowAnchorNode()); + return true; + } + }); + + r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { + builder.push(Kind.Int, builder.append(new BranchProbabilityNode(probability, condition))); + return true; + } + }); + + InvocationPlugin blackholePlugin = new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.append(new BlackholeNode(value)); + return true; + } + }; + + for (Kind kind : Kind.values()) { + Class cls = null; + switch (kind) { + case Object: + cls = Object.class; + break; + case Void: + case Illegal: + continue; + default: + cls = kind.toJavaClass(); + } + + r.register1("blackhole", cls, blackholePlugin); + + final Kind stackKind = kind.getStackKind(); + r.register1("opaque", cls, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(stackKind, builder.append(new OpaqueNode(value))); + return true; + } + }); + } + } + +} diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,6 +38,7 @@ @NodeInfo public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess { + public static final NodeClass TYPE = NodeClass.create(ArrayEqualsNode.class); /** {@link Kind} of the arrays to compare. */ protected final Kind kind; @@ -50,9 +51,12 @@ /** Length of both arrays. */ @Input ValueNode length; + @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess; + public ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length) { - super(StampFactory.forKind(Kind.Boolean)); - assert array1.stamp().equals(array2.stamp()); + super(TYPE, StampFactory.forKind(Kind.Boolean)); + // Ignore nullness in stamp equality test + assert array1.stamp().join(StampFactory.objectNonNull()).equals(array2.stamp().join(StampFactory.objectNonNull())); ObjectStamp array1Stamp = (ObjectStamp) array1.stamp(); ResolvedJavaType componentType = array1Stamp.type().getComponentType(); this.kind = componentType.getKind(); @@ -137,4 +141,13 @@ public LocationIdentity getLocationIdentity() { return NamedLocationIdentity.getArrayLocation(kind); } + + public MemoryNode getLastLocationAccess() { + return lastLocationAccess; + } + + public void setLastLocationAccess(MemoryNode lla) { + updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(lla)); + lastLocationAccess = lla; + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,13 +38,14 @@ @NodeInfo public final class AssertionNode extends FixedWithNextNode implements Lowerable, Canonicalizable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AssertionNode.class); @Input ValueNode value; protected final boolean compileTimeAssertion; protected final String message; public AssertionNode(boolean compileTimeAssertion, ValueNode value, String message) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.value = value; this.compileTimeAssertion = compileTimeAssertion; this.message = message; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -31,10 +32,12 @@ import com.oracle.graal.nodes.virtual.*; @NodeInfo -public class BasicArrayCopyNode extends MacroStateSplitNode implements Virtualizable { +public abstract class BasicArrayCopyNode extends MacroStateSplitNode implements Virtualizable { - public BasicArrayCopyNode(Invoke invoke) { - super(invoke); + public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); + + public BasicArrayCopyNode(NodeClass c, Invoke invoke) { + super(c, invoke); } protected ValueNode getSource() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,6 +27,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -35,10 +36,12 @@ import com.oracle.graal.nodes.virtual.*; @NodeInfo -public class BasicObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider { +public abstract class BasicObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider { - public BasicObjectCloneNode(Invoke invoke) { - super(invoke); + public static final NodeClass TYPE = NodeClass.create(BasicObjectCloneNode.class); + + protected BasicObjectCloneNode(NodeClass c, Invoke invoke) { + super(c, invoke); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,6 +25,7 @@ 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -34,8 +35,10 @@ @NodeInfo public final class BitCountNode extends UnaryNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(BitCountNode.class); + public BitCountNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + super(TYPE, StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -38,8 +39,10 @@ @NodeInfo public final class BitScanForwardNode extends UnaryNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(BitScanForwardNode.class); + public BitScanForwardNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + super(TYPE, StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -38,8 +39,10 @@ @NodeInfo public final class BitScanReverseNode extends UnaryNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(BitScanReverseNode.class); + public BitScanReverseNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + super(TYPE, StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -40,6 +40,7 @@ */ @NodeInfo public final class DeferredPiNode extends FloatingNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(DeferredPiNode.class); @Input ValueNode object; @Input ValueNode type; @@ -49,7 +50,7 @@ } public DeferredPiNode(ValueNode type, ValueNode object) { - super(StampFactory.object()); + super(TYPE, StampFactory.object()); this.type = type; this.object = object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; @@ -37,6 +38,7 @@ @NodeInfo public final class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(DirectObjectStoreNode.class); @Input ValueNode object; @Input ValueNode value; @Input ValueNode offset; @@ -45,7 +47,7 @@ protected final Kind storeKind; public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value, LocationIdentity locationIdentity, Kind storeKind) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.object = object; this.value = value; this.offset = offset; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -36,13 +37,14 @@ * {@link StateSplit} and takes a computed address instead of an object. */ @NodeInfo -public class DirectReadNode extends FixedWithNextNode implements LIRLowerable { +public final class DirectReadNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(DirectReadNode.class); @Input protected ValueNode address; protected final Kind readKind; public DirectReadNode(ValueNode address, Kind readKind) { - super(StampFactory.forKind(readKind.getStackKind())); + super(TYPE, StampFactory.forKind(readKind.getStackKind())); this.address = address; this.readKind = readKind; } @@ -52,9 +54,9 @@ } /** - * If we are sub it sizes, we try to sign/zero extend the value to at least int as it is done in - * the {@link com.oracle.graal.replacements.DefaultJavaLoweringProvider#implicitLoadConvert} and - * {@link com.oracle.graal.replacements.DefaultJavaLoweringProvider#createUnsafeRead}. + * If we are sub int sizes, we try to sign/zero extend the value to at least int as it is done + * in the {@link com.oracle.graal.replacements.DefaultJavaLoweringProvider#implicitLoadConvert} + * and {@link com.oracle.graal.replacements.DefaultJavaLoweringProvider#createUnsafeRead}. * * @see com.oracle.graal.replacements.DefaultJavaLoweringProvider#implicitLoadConvert * @see com.oracle.graal.replacements.DefaultJavaLoweringProvider#createUnsafeRead diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -36,14 +37,15 @@ * {@link StateSplit} and takes a computed address instead of an object. */ @NodeInfo -public class DirectStoreNode extends FixedWithNextNode implements LIRLowerable { +public final class DirectStoreNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(DirectStoreNode.class); @Input protected ValueNode address; @Input protected ValueNode value; protected final Kind kind; public DirectStoreNode(ValueNode address, ValueNode value, Kind kind) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.address = address; this.value = value; this.kind = kind; diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,9 +38,10 @@ */ @NodeInfo public final class ExplodeLoopNode extends FixedWithNextNode { + public static final NodeClass TYPE = NodeClass.create(ExplodeLoopNode.class); public ExplodeLoopNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } public LoopBeginNode findLoopBegin() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,14 +33,15 @@ * Implements the semantics of {@link VarargsParameter}. */ @NodeInfo -public class LoadSnippetVarargParameterNode extends FixedWithNextNode implements Canonicalizable { +public final class LoadSnippetVarargParameterNode extends FixedWithNextNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(LoadSnippetVarargParameterNode.class); @Input ValueNode index; @Input NodeInputList parameters; public LoadSnippetVarargParameterNode(ParameterNode[] locals, ValueNode index, Stamp stamp) { - super(stamp); + super(TYPE, stamp); this.index = index; this.parameters = new NodeInputList<>(this, locals); } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,8 +57,9 @@ *
    */ @NodeInfo -public class MacroNode extends FixedWithNextNode implements Lowerable { +public abstract class MacroNode extends FixedWithNextNode implements Lowerable { + public static final NodeClass TYPE = NodeClass.create(MacroNode.class); @Input protected NodeInputList arguments; protected final int bci; @@ -66,8 +67,8 @@ protected final JavaType returnType; protected final InvokeKind invokeKind; - public MacroNode(Invoke invoke) { - super(StampFactory.forKind(((MethodCallTargetNode) invoke.callTarget()).targetMethod().getSignature().getReturnKind())); + protected MacroNode(NodeClass c, Invoke invoke) { + super(c, StampFactory.forKind(((MethodCallTargetNode) invoke.callTarget()).targetMethod().getSignature().getReturnKind())); MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget(); this.arguments = new NodeInputList<>(this, methodCallTarget.arguments()); this.bci = invoke.bci(); @@ -170,7 +171,7 @@ InliningUtil.inline(invoke, replacementGraph, false, null); Debug.dump(graph(), "After inlining replacement %s", replacementGraph); } else { - if (stateAfter() == null) { + if (invoke.stateAfter() == null) { throw new GraalInternalError("cannot lower to invoke without state: %s", this); } invoke.lower(tool); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -35,12 +36,13 @@ * {@link MemoryCheckpoint}. */ @NodeInfo -public class MacroStateSplitNode extends MacroNode implements StateSplit, MemoryCheckpoint.Single { +public abstract class MacroStateSplitNode extends MacroNode implements StateSplit, MemoryCheckpoint.Single { + public static final NodeClass TYPE = NodeClass.create(MacroStateSplitNode.class); @OptionalInput(InputType.State) protected FrameState stateAfter; - public MacroStateSplitNode(Invoke invoke) { - super(invoke); + public MacroStateSplitNode(NodeClass c, Invoke invoke) { + super(c, invoke); this.stateAfter = invoke.stateAfter(); } @@ -64,7 +66,7 @@ } protected void replaceSnippetInvokes(StructuredGraph snippetGraph) { - for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.TYPE)) { Invoke invoke = call.invoke(); if (!call.targetMethod().equals(getTargetMethod())) { throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName()); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.nodeinfo.*; @@ -33,8 +34,9 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public class MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable { +public final class MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable { + public static final NodeClass TYPE = NodeClass.create(MathIntrinsicNode.class); protected final Operation operation; public enum Operation { @@ -50,7 +52,7 @@ } public MathIntrinsicNode(ValueNode value, Operation op) { - super(StampFactory.forKind(Kind.Double), value); + super(TYPE, StampFactory.forKind(Kind.Double), value); assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64; this.operation = op; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -22,15 +22,18 @@ */ package com.oracle.graal.replacements.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @NodeInfo -public class MathPowNode extends MacroStateSplitNode implements Canonicalizable.Binary { +public final class MathPowNode extends MacroStateSplitNode implements Canonicalizable.Binary { + + public static final NodeClass TYPE = NodeClass.create(MathPowNode.class); public MathPowNode(Invoke i) { - super(i); + super(TYPE, i); } public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { +public final class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { + + public static final NodeClass TYPE = NodeClass.create(MemoryAnchorNode.class); public MemoryAnchorNode() { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); } public void generate(NodeLIRBuilderTool generator) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -35,8 +35,10 @@ @NodeInfo public abstract class PureFunctionMacroNode extends MacroStateSplitNode implements Canonicalizable { - public PureFunctionMacroNode(Invoke invoke) { - super(invoke); + public static final NodeClass TYPE = NodeClass.create(PureFunctionMacroNode.class); + + protected PureFunctionMacroNode(NodeClass c, Invoke invoke) { + super(c, invoke); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,8 +34,9 @@ * Access the value of a specific register. */ @NodeInfo(nameTemplate = "ReadRegister %{p#register}") -public class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable { +public final class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(ReadRegisterNode.class); /** * The fixed register to access. */ @@ -54,7 +56,7 @@ protected final boolean incoming; public ReadRegisterNode(Register register, Kind kind, boolean directUse, boolean incoming) { - super(StampFactory.forKind(kind)); + super(TYPE, StampFactory.forKind(kind)); assert register != null; this.register = register; this.directUse = directUse; @@ -62,7 +64,7 @@ } public ReadRegisterNode(Register register, boolean directUse, boolean incoming) { - super(StampFactory.forNodeIntrinsic()); + super(TYPE, StampFactory.forNodeIntrinsic()); assert register != null; this.register = register; this.directUse = directUse; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -32,10 +33,12 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public class ReverseBytesNode extends UnaryNode implements LIRLowerable { +public final class ReverseBytesNode extends UnaryNode implements LIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(ReverseBytesNode.class); public ReverseBytesNode(ValueNode value) { - super(StampFactory.forKind(value.getKind()), value); + super(TYPE, StampFactory.forKind(value.getKind()), value); assert getKind() == Kind.Int || getKind() == Kind.Long; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +25,7 @@ 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.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -33,8 +34,9 @@ * Changes the value of a specific register. */ @NodeInfo(nameTemplate = "WriteRegister %{p#register}") -public class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable { +public final class WriteRegisterNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(WriteRegisterNode.class); /** * The fixed register to access. */ @@ -46,7 +48,7 @@ @Input ValueNode value; public WriteRegisterNode(Register register, ValueNode value) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.register = register; this.value = value; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java --- a/graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,7 +37,7 @@ /** * Gets the backend for a given architecture. - * + * * @param arch a specific architecture class */ Backend getBackend(Class arch); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Mar 02 19:11:22 2015 +0100 @@ -98,12 +98,23 @@ } } }); - compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); + int selectedProcessors = TruffleCompilerOptions.TruffleCompilerThreads.getValue(); + if (selectedProcessors == 0) { + // No manual selection made, check how many processors are available. + int availableProcessors = Runtime.getRuntime().availableProcessors(); + if (availableProcessors >= 4) { + selectedProcessors = 2; + } else if (availableProcessors >= 12) { + selectedProcessors = 4; + } + } + selectedProcessors = Math.max(1, selectedProcessors); + compileQueue = new ThreadPoolExecutor(selectedProcessors, selectedProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); } private static void installOptimizedCallTargetCallDirect() { - if (TruffleCompilerOptions.TruffleFunctionInlining.getValue()) { + if (TruffleCompilerOptions.TruffleFunctionInlining.getValue() && !TruffleCompilerOptions.FastPE.getValue()) { ((HotSpotResolvedJavaMethod) getGraalProviders().getMetaAccess().lookupJavaMethod(OptimizedCallTarget.getCallDirectMethod())).setNotInlineable(); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class BytecodeInterpreterPartialEvaluationTest extends PartialEvaluationTest { + + public static class Bytecode { + public static final byte CONST = 0; + public static final byte RETURN = 1; + public static final byte ADD = 2; + public static final byte IFZERO = 3; + public static final byte POP = 4; + public static final byte JMP = 5; + public static final byte DUP = 6; + } + + public static boolean TRACE = false; + + public static class Program extends RootNode { + private final String name; + @CompilationFinal private final byte[] bytecodes; + @CompilationFinal private final FrameSlot[] locals; + @CompilationFinal private final FrameSlot[] stack; + + public Program(String name, byte[] bytecodes, int maxLocals, int maxStack) { + this.name = name; + this.bytecodes = bytecodes; + locals = new FrameSlot[maxLocals]; + stack = new FrameSlot[maxStack]; + for (int i = 0; i < maxLocals; ++i) { + locals[i] = this.getFrameDescriptor().addFrameSlot("local" + i); + locals[i].setKind(FrameSlotKind.Int); + } + for (int i = 0; i < maxStack; ++i) { + stack[i] = this.getFrameDescriptor().addFrameSlot("stack" + i); + stack[i].setKind(FrameSlotKind.Int); + } + } + + protected void setInt(VirtualFrame frame, int stackIndex, int value) { + frame.setInt(stack[stackIndex], value); + } + + protected int getInt(VirtualFrame frame, int stackIndex) { + try { + return frame.getInt(stack[stackIndex]); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException("Error accessing stack slot " + stackIndex); + } + } + + @Override + public String toString() { + return name; + } + + public void trace(String format, Object... args) { + if (CompilerDirectives.inInterpreter() && TRACE) { + System.out.println(String.format(format, args)); + } + } + + @Override + @ExplodeLoop(merge = true) + public Object execute(VirtualFrame frame) { + trace("Start program"); + int topOfStack = -1; + int bci = 0; + while (true) { + CompilerAsserts.partialEvaluationConstant(bci); + byte bc = bytecodes[bci]; + byte value = 0; + switch (bc) { + case Bytecode.CONST: + value = bytecodes[bci + 1]; + trace("%d (%d): CONST %s", bci, topOfStack, value); + setInt(frame, ++topOfStack, value); + bci = bci + 2; + continue; + + case Bytecode.RETURN: + trace("%d (%d): RETURN", bci, topOfStack); + return getInt(frame, topOfStack); + + case Bytecode.ADD: { + int left = getInt(frame, topOfStack); + int right = getInt(frame, topOfStack - 1); + trace("%d (%d): ADD %d %d", bci, topOfStack, left, right); + setInt(frame, topOfStack - 1, left + right); + topOfStack--; + bci = bci + 1; + continue; + } + + case Bytecode.IFZERO: + trace("%d (%d): IFZERO", bci, topOfStack); + if (getInt(frame, topOfStack--) == 0) { + bci = bytecodes[bci + 1]; + continue; + } else { + bci = bci + 2; + continue; + } + + case Bytecode.POP: + trace("%d (%d): POP", bci, topOfStack); + topOfStack--; + bci++; + continue; + + case Bytecode.JMP: + trace("%d (%d): JMP", bci, topOfStack); + bci = bytecodes[bci + 1]; + continue; + + case Bytecode.DUP: + trace("%d (%d): DUP", bci, topOfStack); + setInt(frame, topOfStack + 1, getInt(frame, topOfStack)); + topOfStack++; + bci++; + continue; + } + } + } + } + + public static Object constant42() { + return 42; + } + + private static void assertReturns42(Program program) { + Assert.assertEquals(Integer.valueOf(42), Truffle.getRuntime().createCallTarget(program).call()); + } + + private void assertPartialEvalEqualsAndRunsCorrect(Program program) { + assertReturns42(program); + assertPartialEvalEquals("constant42", program); + } + + @Test + public void constReturnProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */42, + /* 2: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("constReturnProgram", bytecodes, 0, 2)); + } + + @Test + public void constAddProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */2, + /* 4: */Bytecode.ADD, + /* 5: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("constAddProgram", bytecodes, 0, 2)); + } + + @Test + public void simpleIfProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */1, + /* 4: */Bytecode.IFZERO, + /* 5: */8, + /* 6: */Bytecode.CONST, + /* 7: */42, + /* 8: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("simpleIfProgram", bytecodes, 0, 3)); + } + + @Test + public void ifAndPopProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */1, + /* 4: */Bytecode.IFZERO, + /* 5: */9, + /* 6: */Bytecode.POP, + /* 7: */Bytecode.CONST, + /* 8: */42, + /* 9: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("ifAndPopProgram", bytecodes, 0, 3)); + } + + @Test + public void simpleLoopProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */42, + /* 2: */Bytecode.CONST, + /* 3: */-12, + /* 4: */Bytecode.CONST, + /* 5: */1, + /* 6: */Bytecode.ADD, + /* 7: */Bytecode.DUP, + /* 8: */Bytecode.IFZERO, + /* 9: */12, + /* 10: */Bytecode.JMP, + /* 11: */4, + /* 12: */Bytecode.POP, + /* 13: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("simpleLoopProgram", bytecodes, 0, 3)); + } + + @Test + public void nestedLoopsProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */42, + /* 2: */Bytecode.CONST, + /* 3: */-2, + /* 4: */Bytecode.CONST, + /* 5: */1, + /* 6: */Bytecode.ADD, + /* 7: */Bytecode.DUP, + /* 8: */Bytecode.CONST, + /* 9: */-2, + /* 10: */Bytecode.CONST, + /* 11: */1, + /* 12: */Bytecode.ADD, + /* 13: */Bytecode.DUP, + /* 14: */Bytecode.IFZERO, + /* 15: */18, + /* 16: */Bytecode.JMP, + /* 17: */10, + /* 18: */Bytecode.POP, + /* 19: */Bytecode.IFZERO, + /* 20: */23, + /* 21: */Bytecode.JMP, + /* 22: */4, + /* 23: */Bytecode.POP, + /* 24: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("nestedLoopsProgram", bytecodes, 0, 6)); + } + + @Test(timeout = 1000) + public void manyIfsProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */1, + /* 4: */Bytecode.IFZERO, + /* 5: */8, + /* 6: */Bytecode.CONST, + /* 7: */1, + /* 8: */Bytecode.IFZERO, + /* 9: */12, + /* 10: */Bytecode.CONST, + /* 11: */1, + /* 12: */Bytecode.IFZERO, + /* 13: */16, + /* 14: */Bytecode.CONST, + /* 15: */1, + /* 16: */Bytecode.IFZERO, + /* 17: */20, + /* 18: */Bytecode.CONST, + /* 19: */1, + /* 20: */Bytecode.IFZERO, + /* 21: */24, + /* 22: */Bytecode.CONST, + /* 23: */1, + /* 24: */Bytecode.IFZERO, + /* 25: */28, + /* 26: */Bytecode.CONST, + /* 27: */1, + /* 28: */Bytecode.IFZERO, + /* 29: */32, + /* 30: */Bytecode.CONST, + /* 31: */1, + /* 32: */Bytecode.IFZERO, + /* 33: */36, + /* 34: */Bytecode.CONST, + /* 35: */1, + /* 36: */Bytecode.IFZERO, + /* 37: */40, + /* 38: */Bytecode.CONST, + /* 39: */1, + /* 40: */Bytecode.IFZERO, + /* 41: */44, + /* 42: */Bytecode.CONST, + /* 43: */42, + /* 44: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("manyIfsProgram", bytecodes, 0, 3)); + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/CompilerAssertsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/CompilerAssertsTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.truffle.test.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +public class CompilerAssertsTest extends PartialEvaluationTest { + + public static class NeverPartOfCompilationTestNode extends AbstractTestNode { + + @Override + public int execute(VirtualFrame frame) { + CompilerAsserts.neverPartOfCompilation(); + return 0; + } + + } + + public static class CompilationConstantTestNode extends AbstractTestNode { + @Child private AbstractTestNode child; + + public CompilationConstantTestNode(AbstractTestNode child) { + this.child = child; + } + + @Override + public int execute(VirtualFrame frame) { + CompilerAsserts.compilationConstant(child.execute(frame)); + return 0; + } + + } + + @Test + public void neverPartOfCompilationTest() { + NeverPartOfCompilationTestNode result = new NeverPartOfCompilationTestNode(); + RootTestNode rootNode = new RootTestNode(new FrameDescriptor(), "neverPartOfCompilation", result); + try { + compileHelper("neverPartOfCompilation", rootNode, new Object[0]); + Assert.fail("Expected bailout exception due to never part of compilation"); + } catch (BailoutException e) { + // Bailout exception expected. + } + } + + @Test + public void compilationNonConstantTest() { + FrameDescriptor descriptor = new FrameDescriptor(); + CompilationConstantTestNode result = new CompilationConstantTestNode(new NonConstantTestNode(5)); + RootTestNode rootNode = new RootTestNode(descriptor, "compilationConstant", result); + try { + compileHelper("compilationConstant", rootNode, new Object[0]); + Assert.fail("Expected bailout exception because expression is not compilation constant"); + } catch (BailoutException e) { + // Bailout exception expected. + } + } + + @Test + public void compilationConstantTest() { + FrameDescriptor descriptor = new FrameDescriptor(); + CompilationConstantTestNode result = new CompilationConstantTestNode(new ConstantTestNode(5)); + RootTestNode rootNode = new RootTestNode(descriptor, "compilationConstant", result); + compileHelper("compilationConstant", rootNode, new Object[0]); + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,9 +25,11 @@ import org.junit.*; import com.oracle.graal.truffle.test.nodes.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.instrument.impl.*; +import com.oracle.truffle.api.nodes.*; /** * Tests for a single simple PE test with various combinations of instrumentation attached. None of @@ -48,7 +50,6 @@ assertPartialEvalEquals("constant42", root); } - @Ignore @Test public void constantValueProbedNoInstruments() { FrameDescriptor fd = new FrameDescriptor(); @@ -59,7 +60,6 @@ assertPartialEvalEquals("constant42", root); } - @Ignore @Test public void constantValueProbedNullInstrument() { FrameDescriptor fd = new FrameDescriptor(); @@ -72,7 +72,6 @@ assertPartialEvalEquals("constant42", root); } - @Ignore @Test public void constantValueProbedNullInstrumentDisposed() { FrameDescriptor fd = new FrameDescriptor(); @@ -86,7 +85,6 @@ assertPartialEvalEquals("constant42", root); } - @Ignore @Test public void constantValueProbedTwoNullInstruments() { FrameDescriptor fd = new FrameDescriptor(); @@ -101,7 +99,6 @@ assertPartialEvalEquals("constant42", root); } - @Ignore @Test public void constantValueProbedThreeNullInstruments() { FrameDescriptor fd = new FrameDescriptor(); @@ -118,7 +115,6 @@ assertPartialEvalEquals("constant42", root); } - @Ignore @Test public void constantValueProbedThreeNullInstrumentsOneDisposed() { FrameDescriptor fd = new FrameDescriptor(); @@ -135,4 +131,118 @@ instrument2.dispose(); assertPartialEvalEquals("constant42", root); } + + @Test + public void instrumentDeopt() { + final FrameDescriptor fd = new FrameDescriptor(); + final AbstractTestNode result = new ConstantTestNode(42); + final RootTestNode root = new RootTestNode(fd, "constantValue", result); + final Probe[] probe = new Probe[1]; + final int[] count = {1}; + count[0] = 0; + // Register a "prober" that will get applied when CallTarget gets created. + final ASTProber prober = new ASTProber() { + + @Override + public void probeAST(Node node) { + node.accept(new NodeVisitor() { + + @Override + public boolean visit(Node visitedNode) { + if (visitedNode instanceof ConstantTestNode) { + probe[0] = visitedNode.probe(); + } + return true; + } + + }); + } + }; + Probe.registerASTProber(prober); + try { + final RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(root); + + // The CallTarget has one Probe, attached to the ConstantTestNode, ready to run + Assert.assertEquals(42, callTarget.call()); // Correct result + Assert.assertEquals(0, count[0]); // Didn't count anything + + // Add a counting instrument; this changes the "Probe state" and should cause a deopt + final Instrument countingInstrument = Instrument.create(new DefaultEventListener() { + + @Override + public void enter(Node node, VirtualFrame frame) { + count[0] = count[0] + 1; + } + }); + probe[0].attach(countingInstrument); + + Assert.assertEquals(42, callTarget.call()); // Correct result + Assert.assertEquals(1, count[0]); // Counted the first call + + // Remove the counting instrument; this changes the "Probe state" and should cause a + // deopt + countingInstrument.dispose(); + + Assert.assertEquals(42, callTarget.call()); // Correct result + Assert.assertEquals(1, count[0]); // Didn't count this time + } finally { + Probe.unregisterASTProber(prober); + } + + } + + /** + * Experimental feature; not yet validated. + */ + @Test + public void specialOptInstrument() { + final FrameDescriptor fd = new FrameDescriptor(); + final AbstractTestNode result = new ConstantTestNode(42); + final RootTestNode root = new RootTestNode(fd, "constantValue", result); + final Probe[] probe = new Probe[1]; + final int[] count = {1}; + count[0] = 0; + // Register a "prober" that will get applied when CallTarget gets created. + final ASTProber prober = new ASTProber() { + + @Override + public void probeAST(Node node) { + node.accept(new NodeVisitor() { + + @Override + public boolean visit(Node visitedNode) { + if (visitedNode instanceof ConstantTestNode) { + probe[0] = visitedNode.probe(); + } + return true; + } + }); + } + }; + Probe.registerASTProber(prober); + try { + final RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(root); + + // The CallTarget has one Probe, attached to the ConstantTestNode, ready to run + Assert.assertEquals(42, callTarget.call()); // Correct result + + final boolean[] isCurrentlyCompiled = {false}; + final Instrument optInstrument = Instrument.create(new Instrument.TruffleOptListener() { + + public void notifyIsCompiled(boolean isCompiled) { + isCurrentlyCompiled[0] = isCompiled; + } + }); + probe[0].attach(optInstrument); + + Assert.assertEquals(42, callTarget.call()); // Correct result + Assert.assertFalse(isCurrentlyCompiled[0]); + + // TODO (mlvdv) compile, call again, and assert that isCurrentlyCompiled == true + + } finally { + Probe.unregisterASTProber(prober); + } + + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -77,7 +77,7 @@ final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); StructuredGraph actual = partialEval(compilable, arguments, AllowAssumptions.YES); removeFrameStates(actual); - for (MethodCallTargetNode node : actual.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode node : actual.getNodes(MethodCallTargetNode.TYPE)) { Assert.fail("Found invalid method call target node: " + node); } } @@ -89,14 +89,14 @@ compilable.call(arguments); try (Scope s = Debug.scope("TruffleCompilation", new TruffleDebugJavaMethod(compilable))) { - return truffleCompiler.getPartialEvaluator().createGraph(compilable, allowAssumptions, null); + return truffleCompiler.getPartialEvaluator().createGraph(compilable, allowAssumptions); } catch (Throwable e) { throw Debug.handle(e); } } protected void removeFrameStates(StructuredGraph graph) { - for (FrameState frameState : graph.getNodes(FrameState.class)) { + for (FrameState frameState : graph.getNodes(FrameState.TYPE)) { frameState.replaceAtUsages(null); frameState.safeDelete(); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,7 +30,7 @@ @Children private final AbstractTestNode[] statements; - public BlockTestNode(AbstractTestNode[] statements) { + public BlockTestNode(AbstractTestNode... statements) { this.statements = statements; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/NonConstantTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/NonConstantTestNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class NonConstantTestNode extends AbstractTestNode { + + private int value; + + public NonConstantTestNode(int value) { + this.value = value; + } + + @Override + public int execute(VirtualFrame frame) { + return value; + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.truffle.test.nodes; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; @NodeInfo @@ -43,6 +44,11 @@ } @Override + public void applyInstrumentation() { + Probe.applyASTProbers(node); + } + + @Override public String toString() { return name; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithBoxing.java Mon Mar 02 19:11:22 2015 +0100 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle; + +import java.lang.reflect.*; +import java.util.*; + +import sun.misc.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * More efficient implementation of the Truffle frame that has no safety checks for frame accesses + * and therefore is much faster. Should not be used during debugging as potential misuses of the + * frame object would show up very late and would be hard to identify. + */ +public final class FrameWithBoxing implements VirtualFrame, MaterializedFrame { + private final FrameDescriptor descriptor; + private final Object[] arguments; + private Object[] locals; + + public FrameWithBoxing(FrameDescriptor descriptor, Object[] arguments) { + this.descriptor = descriptor; + this.arguments = arguments; + int size = descriptor.getSize(); + this.locals = new Object[size]; + Object defaultValue = descriptor.getDefaultValue(); + if (defaultValue != null) { + Arrays.fill(locals, defaultValue); + } + } + + @Override + public Object[] getArguments() { + return unsafeCast(arguments, Object[].class, true, true); + } + + @Override + public MaterializedFrame materialize() { + return this; + } + + @Override + public Object getObject(FrameSlot slot) { + int index = slot.getIndex(); + Object[] curLocals = this.getLocals(); + if (CompilerDirectives.inInterpreter() && index >= curLocals.length) { + curLocals = resizeAndCheck(slot); + } + return curLocals[index]; + } + + private Object[] getLocals() { + return unsafeCast(locals, Object[].class, true, true); + } + + @Override + public void setObject(FrameSlot slot, Object value) { + int index = slot.getIndex(); + Object[] curLocals = this.getLocals(); + if (CompilerDirectives.inInterpreter() && index >= curLocals.length) { + curLocals = resizeAndCheck(slot); + } + curLocals[index] = value; + } + + @Override + public byte getByte(FrameSlot slot) throws FrameSlotTypeException { + Object result = getObject(slot); + if (CompilerDirectives.inInterpreter() && !(result instanceof Byte)) { + throw new FrameSlotTypeException(); + } + return (Byte) result; + } + + @Override + public void setByte(FrameSlot slot, byte value) { + setObject(slot, value); + } + + @Override + public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { + Object result = getObject(slot); + if (CompilerDirectives.inInterpreter() && !(result instanceof Boolean)) { + throw new FrameSlotTypeException(); + } + return (Boolean) result; + } + + @Override + public void setBoolean(FrameSlot slot, boolean value) { + setObject(slot, value); + } + + @Override + public float getFloat(FrameSlot slot) throws FrameSlotTypeException { + Object result = getObject(slot); + if (CompilerDirectives.inInterpreter() && !(result instanceof Float)) { + throw new FrameSlotTypeException(); + } + return (Float) result; + } + + @Override + public void setFloat(FrameSlot slot, float value) { + setObject(slot, value); + } + + @Override + public long getLong(FrameSlot slot) throws FrameSlotTypeException { + Object result = getObject(slot); + if (CompilerDirectives.inInterpreter() && !(result instanceof Long)) { + throw new FrameSlotTypeException(); + } + return (Long) result; + } + + @Override + public void setLong(FrameSlot slot, long value) { + setObject(slot, value); + } + + @Override + public int getInt(FrameSlot slot) throws FrameSlotTypeException { + Object result = getObject(slot); + if (CompilerDirectives.inInterpreter() && !(result instanceof Integer)) { + throw new FrameSlotTypeException(); + } + return (Integer) result; + } + + @Override + public void setInt(FrameSlot slot, int value) { + setObject(slot, value); + } + + @Override + public double getDouble(FrameSlot slot) throws FrameSlotTypeException { + Object result = getObject(slot); + if (CompilerDirectives.inInterpreter() && !(result instanceof Double)) { + throw new FrameSlotTypeException(); + } + return (Double) result; + } + + @Override + public void setDouble(FrameSlot slot, double value) { + setObject(slot, value); + } + + @Override + public FrameDescriptor getFrameDescriptor() { + return this.descriptor; + } + + private Object[] resizeAndCheck(FrameSlot slot) { + if (!resize()) { + throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); + } + return locals; + } + + @Override + public Object getValue(FrameSlot slot) { + return getObject(slot); + } + + private boolean resize() { + int oldSize = locals.length; + int newSize = descriptor.getSize(); + if (newSize > oldSize) { + locals = Arrays.copyOf(locals, newSize); + Arrays.fill(locals, oldSize, newSize, descriptor.getDefaultValue()); + return true; + } + return false; + } + + @Override + public boolean isObject(FrameSlot slot) { + return getObject(slot) != null; + } + + @Override + public boolean isByte(FrameSlot slot) { + return getObject(slot) instanceof Byte; + } + + @Override + public boolean isBoolean(FrameSlot slot) { + return getObject(slot) instanceof Boolean; + } + + @Override + public boolean isInt(FrameSlot slot) { + return getObject(slot) instanceof Integer; + } + + @Override + public boolean isLong(FrameSlot slot) { + return getObject(slot) instanceof Long; + } + + @Override + public boolean isFloat(FrameSlot slot) { + return getObject(slot) instanceof Float; + } + + @Override + public boolean isDouble(FrameSlot slot) { + return getObject(slot) instanceof Double; + } + + @SuppressWarnings({"unchecked", "unused"}) + static T unsafeCast(Object value, Class type, boolean condition, boolean nonNull) { + return (T) value; + } + + @SuppressWarnings("unused") + static int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getInt(receiver, offset); + } + + @SuppressWarnings("unused") + static long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getLong(receiver, offset); + } + + @SuppressWarnings("unused") + static float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getFloat(receiver, offset); + } + + @SuppressWarnings("unused") + static double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getDouble(receiver, offset); + } + + @SuppressWarnings("unused") + static Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getObject(receiver, offset); + } + + @SuppressWarnings("unused") + static void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity) { + UNSAFE.putInt(receiver, offset, value); + } + + @SuppressWarnings("unused") + static void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity) { + UNSAFE.putLong(receiver, offset, value); + } + + @SuppressWarnings("unused") + static void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity) { + UNSAFE.putFloat(receiver, offset, value); + } + + @SuppressWarnings("unused") + static void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity) { + UNSAFE.putDouble(receiver, offset, value); + } + + @SuppressWarnings("unused") + static void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity) { + UNSAFE.putObject(receiver, offset, value); + } + + private static final Unsafe UNSAFE = getUnsafe(); + + private static Unsafe getUnsafe() { + try { + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } +} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Mar 02 19:11:22 2015 +0100 @@ -41,6 +41,25 @@ private Object[] locals; private long[] primitiveLocals; private byte[] tags; + public static final byte OBJECT_TAG = 0; + public static final byte ILLEGAL_TAG = 1; + public static final byte LONG_TAG = 2; + public static final byte INT_TAG = 3; + public static final byte DOUBLE_TAG = 4; + public static final byte FLOAT_TAG = 5; + public static final byte BOOLEAN_TAG = 6; + public static final byte BYTE_TAG = 7; + + static { + assert OBJECT_TAG == FrameSlotKind.Object.tag; + assert ILLEGAL_TAG == FrameSlotKind.Illegal.tag; + assert LONG_TAG == FrameSlotKind.Long.tag; + assert INT_TAG == FrameSlotKind.Int.tag; + assert DOUBLE_TAG == FrameSlotKind.Double.tag; + assert FLOAT_TAG == FrameSlotKind.Float.tag; + assert BOOLEAN_TAG == FrameSlotKind.Boolean.tag; + assert BYTE_TAG == FrameSlotKind.Byte.tag; + } public FrameWithoutBoxing(FrameDescriptor descriptor, Object[] arguments) { this.descriptor = descriptor; @@ -67,8 +86,9 @@ @Override public Object getObject(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, FrameSlotKind.Object); - return getObjectUnsafe(slot); + int slotIndex = slot.getIndex(); + verifyGet(slotIndex, OBJECT_TAG); + return getObjectUnsafe(slotIndex, slot); } private Object[] getLocals() { @@ -83,156 +103,168 @@ return unsafeCast(tags, byte[].class, true, true); } - private Object getObjectUnsafe(FrameSlot slot) { - int slotIndex = slot.getIndex(); - return unsafeGetObject(getLocals(), Unsafe.ARRAY_OBJECT_BASE_OFFSET + slotIndex * (long) Unsafe.ARRAY_OBJECT_INDEX_SCALE, this.getTags()[slotIndex] == FrameSlotKind.Object.ordinal(), slot); + private Object getObjectUnsafe(int slotIndex, FrameSlot slot) { + return unsafeGetObject(getLocals(), Unsafe.ARRAY_OBJECT_BASE_OFFSET + slotIndex * (long) Unsafe.ARRAY_OBJECT_INDEX_SCALE, this.getTags()[slotIndex] == FrameSlotKind.Object.tag, slot); } @Override public void setObject(FrameSlot slot, Object value) { - verifySet(slot, FrameSlotKind.Object); - setObjectUnsafe(slot, value); + int slotIndex = slot.getIndex(); + verifySet(slotIndex, OBJECT_TAG); + setObjectUnsafe(slotIndex, slot, value); } - private void setObjectUnsafe(FrameSlot slot, Object value) { - unsafePutObject(getLocals(), Unsafe.ARRAY_OBJECT_BASE_OFFSET + slot.getIndex() * (long) Unsafe.ARRAY_OBJECT_INDEX_SCALE, value, slot); + private void setObjectUnsafe(int slotIndex, FrameSlot slot, Object value) { + unsafePutObject(getLocals(), Unsafe.ARRAY_OBJECT_BASE_OFFSET + slotIndex * (long) Unsafe.ARRAY_OBJECT_INDEX_SCALE, value, slot); } @Override public byte getByte(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, FrameSlotKind.Byte); - return getByteUnsafe(slot); + int slotIndex = slot.getIndex(); + verifyGet(slotIndex, BYTE_TAG); + return getByteUnsafe(slotIndex, slot); } - private byte getByteUnsafe(FrameSlot slot) { - long offset = getPrimitiveOffset(slot); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Byte.ordinal(); + private byte getByteUnsafe(int slotIndex, FrameSlot slot) { + long offset = getPrimitiveOffset(slotIndex); + boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Byte.tag; return (byte) unsafeGetInt(getPrimitiveLocals(), offset, condition, slot); } @Override public void setByte(FrameSlot slot, byte value) { - verifySet(slot, FrameSlotKind.Byte); - setByteUnsafe(slot, value); + int slotIndex = slot.getIndex(); + verifySet(slotIndex, BYTE_TAG); + setByteUnsafe(slotIndex, slot, value); } - private void setByteUnsafe(FrameSlot slot, byte value) { - long offset = getPrimitiveOffset(slot); + private void setByteUnsafe(int slotIndex, FrameSlot slot, byte value) { + long offset = getPrimitiveOffset(slotIndex); unsafePutInt(getPrimitiveLocals(), offset, value, slot); } @Override public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, FrameSlotKind.Boolean); - return getBooleanUnsafe(slot); + int slotIndex = slot.getIndex(); + verifyGet(slotIndex, BOOLEAN_TAG); + return getBooleanUnsafe(slotIndex, slot); } - private boolean getBooleanUnsafe(FrameSlot slot) { - long offset = getPrimitiveOffset(slot); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Boolean.ordinal(); + private boolean getBooleanUnsafe(int slotIndex, FrameSlot slot) { + long offset = getPrimitiveOffset(slotIndex); + boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Boolean.tag; return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot) != 0; } @Override public void setBoolean(FrameSlot slot, boolean value) { - verifySet(slot, FrameSlotKind.Boolean); - setBooleanUnsafe(slot, value); + int slotIndex = slot.getIndex(); + verifySet(slotIndex, BOOLEAN_TAG); + setBooleanUnsafe(slotIndex, slot, value); } - private void setBooleanUnsafe(FrameSlot slot, boolean value) { - long offset = getPrimitiveOffset(slot); + private void setBooleanUnsafe(int slotIndex, FrameSlot slot, boolean value) { + long offset = getPrimitiveOffset(slotIndex); unsafePutInt(getPrimitiveLocals(), offset, value ? 1 : 0, slot); } @Override public float getFloat(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, FrameSlotKind.Float); - return getFloatUnsafe(slot); + int slotIndex = slot.getIndex(); + verifyGet(slotIndex, FLOAT_TAG); + return getFloatUnsafe(slotIndex, slot); } - private float getFloatUnsafe(FrameSlot slot) { - long offset = getPrimitiveOffset(slot); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Float.ordinal(); + private float getFloatUnsafe(int slotIndex, FrameSlot slot) { + long offset = getPrimitiveOffset(slotIndex); + boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Float.tag; return unsafeGetFloat(getPrimitiveLocals(), offset, condition, slot); } @Override public void setFloat(FrameSlot slot, float value) { - verifySet(slot, FrameSlotKind.Float); - setFloatUnsafe(slot, value); + int slotIndex = slot.getIndex(); + verifySet(slotIndex, FLOAT_TAG); + setFloatUnsafe(slotIndex, slot, value); } - private void setFloatUnsafe(FrameSlot slot, float value) { - long offset = getPrimitiveOffset(slot); + private void setFloatUnsafe(int slotIndex, FrameSlot slot, float value) { + long offset = getPrimitiveOffset(slotIndex); unsafePutFloat(getPrimitiveLocals(), offset, value, slot); } @Override public long getLong(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, FrameSlotKind.Long); - return getLongUnsafe(slot); + int slotIndex = slot.getIndex(); + verifyGet(slotIndex, LONG_TAG); + return getLongUnsafe(slotIndex, slot); } - private long getLongUnsafe(FrameSlot slot) { - long offset = getPrimitiveOffset(slot); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Long.ordinal(); + private long getLongUnsafe(int slotIndex, FrameSlot slot) { + long offset = getPrimitiveOffset(slotIndex); + boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Long.tag; return unsafeGetLong(getPrimitiveLocals(), offset, condition, slot); } @Override public void setLong(FrameSlot slot, long value) { - verifySet(slot, FrameSlotKind.Long); - setLongUnsafe(slot, value); + int slotIndex = slot.getIndex(); + verifySet(slotIndex, LONG_TAG); + setLongUnsafe(slotIndex, slot, value); } - private void setLongUnsafe(FrameSlot slot, long value) { - long offset = getPrimitiveOffset(slot); + private void setLongUnsafe(int slotIndex, FrameSlot slot, long value) { + long offset = getPrimitiveOffset(slotIndex); unsafePutLong(getPrimitiveLocals(), offset, value, slot); } @Override public int getInt(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, FrameSlotKind.Int); - return getIntUnsafe(slot); + int slotIndex = slot.getIndex(); + verifyGet(slotIndex, INT_TAG); + return getIntUnsafe(slotIndex, slot); } - private int getIntUnsafe(FrameSlot slot) { - long offset = getPrimitiveOffset(slot); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Int.ordinal(); + private int getIntUnsafe(int slotIndex, FrameSlot slot) { + long offset = getPrimitiveOffset(slotIndex); + boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Int.tag; return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot); } @Override public void setInt(FrameSlot slot, int value) { - verifySet(slot, FrameSlotKind.Int); - setIntUnsafe(slot, value); + int slotIndex = slot.getIndex(); + verifySet(slotIndex, INT_TAG); + setIntUnsafe(slotIndex, slot, value); } - private void setIntUnsafe(FrameSlot slot, int value) { - long offset = getPrimitiveOffset(slot); + private void setIntUnsafe(int slotIndex, FrameSlot slot, int value) { + long offset = getPrimitiveOffset(slotIndex); unsafePutInt(getPrimitiveLocals(), offset, value, slot); } @Override public double getDouble(FrameSlot slot) throws FrameSlotTypeException { - verifyGet(slot, FrameSlotKind.Double); - return getDoubleUnsafe(slot); + int slotIndex = slot.getIndex(); + verifyGet(slotIndex, DOUBLE_TAG); + return getDoubleUnsafe(slotIndex, slot); } - private double getDoubleUnsafe(FrameSlot slot) { - long offset = getPrimitiveOffset(slot); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Double.ordinal(); + private double getDoubleUnsafe(int slotIndex, FrameSlot slot) { + long offset = getPrimitiveOffset(slotIndex); + boolean condition = this.getTags()[slotIndex] == FrameSlotKind.Double.tag; return unsafeGetDouble(getPrimitiveLocals(), offset, condition, slot); } @Override public void setDouble(FrameSlot slot, double value) { - verifySet(slot, FrameSlotKind.Double); - setDoubleUnsafe(slot, value); + int slotIndex = slot.getIndex(); + verifySet(slotIndex, DOUBLE_TAG); + setDoubleUnsafe(slotIndex, slot, value); } - private void setDoubleUnsafe(FrameSlot slot, double value) { - long offset = getPrimitiveOffset(slot); + private void setDoubleUnsafe(int slotIndex, FrameSlot slot, double value) { + long offset = getPrimitiveOffset(slotIndex); unsafePutDouble(getPrimitiveLocals(), offset, value, slot); } @@ -241,59 +273,54 @@ return this.descriptor; } - private void verifySet(FrameSlot slot, FrameSlotKind accessKind) { - int slotIndex = slot.getIndex(); - if (slotIndex >= getTags().length) { - CompilerDirectives.transferToInterpreter(); + private void verifySet(int slotIndex, byte tag) { + if (CompilerDirectives.inInterpreter() && slotIndex >= getTags().length) { if (!resize()) { - throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); + throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slotIndex)); } } - getTags()[slotIndex] = (byte) accessKind.ordinal(); + getTags()[slotIndex] = tag; } - private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { - int slotIndex = slot.getIndex(); - if (slotIndex >= getTags().length) { - CompilerDirectives.transferToInterpreter(); + private void verifyGet(int slotIndex, byte tag) throws FrameSlotTypeException { + if (CompilerDirectives.inInterpreter() && slotIndex >= getTags().length) { if (!resize()) { - throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); + throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slotIndex)); } } - byte tag = this.getTags()[slotIndex]; - if (tag != accessKind.ordinal()) { + if (getTags()[slotIndex] != tag) { CompilerDirectives.transferToInterpreter(); throw new FrameSlotTypeException(); } } - private static long getPrimitiveOffset(FrameSlot slot) { - return Unsafe.ARRAY_LONG_BASE_OFFSET + slot.getIndex() * (long) Unsafe.ARRAY_LONG_INDEX_SCALE; + private static long getPrimitiveOffset(int slotIndex) { + return Unsafe.ARRAY_LONG_BASE_OFFSET + slotIndex * (long) Unsafe.ARRAY_LONG_INDEX_SCALE; } @Override public Object getValue(FrameSlot slot) { int slotIndex = slot.getIndex(); - if (slotIndex >= getTags().length) { + if (CompilerDirectives.inInterpreter() && slotIndex >= getTags().length) { CompilerDirectives.transferToInterpreter(); resize(); } byte tag = getTags()[slotIndex]; - if (tag == FrameSlotKind.Boolean.ordinal()) { - return getBooleanUnsafe(slot); - } else if (tag == FrameSlotKind.Byte.ordinal()) { - return getByteUnsafe(slot); - } else if (tag == FrameSlotKind.Int.ordinal()) { - return getIntUnsafe(slot); - } else if (tag == FrameSlotKind.Double.ordinal()) { - return getDoubleUnsafe(slot); - } else if (tag == FrameSlotKind.Long.ordinal()) { - return getLongUnsafe(slot); - } else if (tag == FrameSlotKind.Float.ordinal()) { - return getFloatUnsafe(slot); + if (tag == FrameSlotKind.Boolean.tag) { + return getBooleanUnsafe(slotIndex, slot); + } else if (tag == FrameSlotKind.Byte.tag) { + return getByteUnsafe(slotIndex, slot); + } else if (tag == FrameSlotKind.Int.tag) { + return getIntUnsafe(slotIndex, slot); + } else if (tag == FrameSlotKind.Double.tag) { + return getDoubleUnsafe(slotIndex, slot); + } else if (tag == FrameSlotKind.Long.tag) { + return getLongUnsafe(slotIndex, slot); + } else if (tag == FrameSlotKind.Float.tag) { + return getFloatUnsafe(slotIndex, slot); } else { - assert tag == FrameSlotKind.Object.ordinal(); - return getObjectUnsafe(slot); + assert tag == FrameSlotKind.Object.tag; + return getObjectUnsafe(slotIndex, slot); } } @@ -321,37 +348,37 @@ @Override public boolean isObject(FrameSlot slot) { - return getTag(slot) == FrameSlotKind.Object.ordinal(); + return getTag(slot) == FrameSlotKind.Object.tag; } @Override public boolean isByte(FrameSlot slot) { - return getTag(slot) == FrameSlotKind.Byte.ordinal(); + return getTag(slot) == FrameSlotKind.Byte.tag; } @Override public boolean isBoolean(FrameSlot slot) { - return getTag(slot) == FrameSlotKind.Boolean.ordinal(); + return getTag(slot) == FrameSlotKind.Boolean.tag; } @Override public boolean isInt(FrameSlot slot) { - return getTag(slot) == FrameSlotKind.Int.ordinal(); + return getTag(slot) == FrameSlotKind.Int.tag; } @Override public boolean isLong(FrameSlot slot) { - return getTag(slot) == FrameSlotKind.Long.ordinal(); + return getTag(slot) == FrameSlotKind.Long.tag; } @Override public boolean isFloat(FrameSlot slot) { - return getTag(slot) == FrameSlotKind.Float.ordinal(); + return getTag(slot) == FrameSlotKind.Float.tag; } @Override public boolean isDouble(FrameSlot slot) { - return getTag(slot) == FrameSlotKind.Double.ordinal(); + return getTag(slot) == FrameSlotKind.Double.tag; } @SuppressWarnings({"unchecked", "unused"}) diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Mon Mar 02 19:11:22 2015 +0100 @@ -113,7 +113,11 @@ @Override public MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor) { - return new FrameWithoutBoxing(frameDescriptor, arguments); + if (TruffleCompilerOptions.TruffleUseFrameWithoutBoxing.getValue()) { + return new FrameWithoutBoxing(frameDescriptor, arguments); + } else { + return new FrameWithBoxing(frameDescriptor, arguments); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Mar 02 19:11:22 2015 +0100 @@ -417,8 +417,12 @@ return args; } - public static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) { - return new FrameWithoutBoxing(descriptor, args); + public static VirtualFrame createFrame(FrameDescriptor descriptor, Object[] args) { + if (TruffleCompilerOptions.TruffleUseFrameWithoutBoxing.getValue()) { + return new FrameWithoutBoxing(descriptor, args); + } else { + return new FrameWithBoxing(descriptor, args); + } } public List getCallNodes() { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; @@ -37,6 +38,8 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node; import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; @@ -97,7 +100,7 @@ } } - public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions, GraphBuilderPlugins graalPlugins) { + public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions) { if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) { constantReceivers = new HashSet<>(); } @@ -121,7 +124,7 @@ HighTierContext tierContext = new HighTierContext(providers, graphCache, new PhaseSuite(), OptimisticOptimizations.NONE); if (TruffleCompilerOptions.FastPE.getValue()) { - fastPartialEvaluation(callTarget, graph, baseContext, tierContext, graalPlugins); + fastPartialEvaluation(callTarget, graph, baseContext, tierContext); } else { createRootGraph(graph); partialEvaluation(callTarget, graph, baseContext, tierContext); @@ -144,22 +147,12 @@ return graph; } - private class InterceptLoadFieldPlugin implements GraphBuilderPlugins.LoadFieldPlugin { + private class InterceptLoadFieldPlugin implements LoadFieldPlugin { public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { if (receiver.isConstant()) { JavaConstant asJavaConstant = receiver.asJavaConstant(); - return tryConstantFold(builder, field, asJavaConstant); - } - return false; - } - - private boolean tryConstantFold(GraphBuilderContext builder, ResolvedJavaField field, JavaConstant asJavaConstant) { - JavaConstant result = providers.getConstantReflection().readConstantFieldValue(field, asJavaConstant); - if (result != null) { - ConstantNode constantNode = builder.append(ConstantNode.forConstant(result, providers.getMetaAccess())); - builder.push(constantNode.getKind().getStackKind(), constantNode); - return true; + return tryConstantFold(builder, providers.getMetaAccess(), providers.getConstantReflection(), field, asJavaConstant); } return false; } @@ -170,11 +163,11 @@ builder.push(trueNode.getKind().getStackKind(), trueNode); return true; } - return tryConstantFold(builder, staticField, null); + return tryConstantFold(builder, providers.getMetaAccess(), providers.getConstantReflection(), staticField, null); } } - private class InterceptReceiverPlugin implements GraphBuilderPlugins.ParameterPlugin { + private class InterceptReceiverPlugin implements ParameterPlugin { private final Object receiver; @@ -190,37 +183,102 @@ } } - private class InlineInvokePlugin implements GraphBuilderPlugins.InlineInvokePlugin { + private class InlineInvokePlugin implements GraphBuilderPlugin.InlineInvokePlugin { - public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) { - return method.getAnnotation(TruffleBoundary.class) == null; + private Stack inlining; + private OptimizedDirectCallNode lastDirectCallNode; + private final Replacements replacements; + + public InlineInvokePlugin(TruffleInlining inlining, Replacements replacements) { + this.inlining = new Stack<>(); + this.inlining.push(inlining); + this.replacements = replacements; } + public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType, int depth) { + if (original.getAnnotation(TruffleBoundary.class) != null) { + return null; + } + if (replacements != null && (replacements.getMethodSubstitutionMethod(original) != null || replacements.getMacroSubstitution(original) != null)) { + return null; + } + if (original.equals(callSiteProxyMethod)) { + ValueNode arg1 = arguments[0]; + if (!arg1.isConstant()) { + GraalInternalError.shouldNotReachHere("The direct call node does not resolve to a constant!"); + } + + Object callNode = builder.getSnippetReflection().asObject(Object.class, (JavaConstant) arg1.asConstant()); + if (callNode instanceof OptimizedDirectCallNode) { + OptimizedDirectCallNode directCallNode = (OptimizedDirectCallNode) callNode; + lastDirectCallNode = directCallNode; + } + } else if (original.equals(callDirectMethod)) { + TruffleInliningDecision decision = getDecision(inlining.peek(), lastDirectCallNode); + lastDirectCallNode = null; + if (decision != null && decision.isInline()) { + inlining.push(decision); + builder.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) decision.getTarget().getNodeRewritingAssumption())); + return callInlinedMethod; + } + } + return original; + } + + public void postInline(ResolvedJavaMethod inlinedTargetMethod) { + if (inlinedTargetMethod.equals(callInlinedMethod)) { + inlining.pop(); + } + } } - private class LoopExplosionPlugin implements GraphBuilderPlugins.LoopExplosionPlugin { + private class LoopExplosionPlugin implements GraphBuilderPlugin.LoopExplosionPlugin { public boolean shouldExplodeLoops(ResolvedJavaMethod method) { return method.getAnnotation(ExplodeLoop.class) != null; } + public boolean shouldMergeExplosions(ResolvedJavaMethod method) { + ExplodeLoop explodeLoop = method.getAnnotation(ExplodeLoop.class); + if (explodeLoop != null) { + return explodeLoop.merge(); + } + return false; + } + } @SuppressWarnings("unused") - private void fastPartialEvaluation(OptimizedCallTarget callTarget, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext, GraphBuilderPlugins graalPlugins) { + private void fastPartialEvaluation(OptimizedCallTarget callTarget, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) { GraphBuilderConfiguration newConfig = configForRoot.copy(); + newConfig.setUseProfiling(false); newConfig.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); newConfig.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); - newConfig.setInlineInvokePlugin(new InlineInvokePlugin()); + callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy())); + newConfig.setInlineInvokePlugin(new InlineInvokePlugin(callTarget.getInlining(), providers.getReplacements())); newConfig.setLoopExplosionPlugin(new LoopExplosionPlugin()); - DefaultGraphBuilderPlugins plugins = graalPlugins == null ? new DefaultGraphBuilderPlugins() : graalPlugins.copy(); - TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins); - long ms = System.currentTimeMillis(); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig, plugins, - TruffleCompilerImpl.Optimizations).apply(graph); - System.out.println("# ms: " + (System.currentTimeMillis() - ms)); + TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), newConfig.getInvocationPlugins()); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig, TruffleCompilerImpl.Optimizations).apply(graph); Debug.dump(graph, "After FastPE"); + // Perform deoptimize to guard conversion. + new ConvertDeoptimizeToGuardPhase().apply(graph, tierContext); + + for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.TYPE)) { + Class macroSubstitution = providers.getReplacements().getMacroSubstitution(methodCallTargetNode.targetMethod()); + if (macroSubstitution != null) { + InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); + } else { + StructuredGraph inlineGraph = providers.getReplacements().getMethodSubstitution(methodCallTargetNode.targetMethod()); + if (inlineGraph != null) { + InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, true, null); + } + } + } + + // Perform dead code elimination. Dead nodes mainly come from parse time canonicalizations. + new DeadCodeEliminationPhase().apply(graph); + // Do single partial escape and canonicalization pass. try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) { new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext); @@ -285,11 +343,11 @@ private static void postPartialEvaluation(final StructuredGraph graph) { NeverPartOfCompilationNode.verifyNotFoundIn(graph); - for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { + for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.TYPE).snapshot()) { materializeNode.replaceAtUsages(materializeNode.getFrame()); graph.removeFixed(materializeNode); } - for (VirtualObjectNode virtualObjectNode : graph.getNodes(VirtualObjectNode.class)) { + for (VirtualObjectNode virtualObjectNode : graph.getNodes(VirtualObjectNode.TYPE)) { if (virtualObjectNode instanceof VirtualOnlyInstanceNode) { VirtualOnlyInstanceNode virtualOnlyInstanceNode = (VirtualOnlyInstanceNode) virtualObjectNode; virtualOnlyInstanceNode.setAllowMaterialization(true); @@ -301,6 +359,13 @@ } } } + + if (!TruffleCompilerOptions.TruffleInlineAcrossTruffleBoundary.getValue()) { + // Do not inline across Truffle boundaries. + for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.TYPE)) { + mct.invoke().setUseForInlining(false); + } + } } private void injectConstantCallTarget(final StructuredGraph graph, final OptimizedCallTarget constantCallTarget, PhaseContext baseContext) { @@ -433,7 +498,7 @@ assert graph.hasLoops() : graph + " does not contain a loop"; final StructuredGraph graphCopy = graph.copy(); final List modifiedNodes = new ArrayList<>(); - for (ParameterNode param : graphCopy.getNodes(ParameterNode.class).snapshot()) { + for (ParameterNode param : graphCopy.getNodes(ParameterNode.TYPE).snapshot()) { ValueNode arg = arguments.get(param.index()); if (arg.isConstant()) { Constant constant = arg.asConstant(); @@ -480,7 +545,7 @@ private void expandDirectCalls(StructuredGraph graph, TruffleExpansionLogger expansionLogger, TruffleInlining inlining, TruffleInliningCache inliningCache) { PhaseContext phaseContext = new PhaseContext(providers); - for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { + for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.TYPE).snapshot()) { StructuredGraph inlineGraph = parseDirectCallGraph(phaseContext, graph, inlining, inliningCache, methodCallTargetNode); if (inlineGraph != null) { @@ -493,7 +558,7 @@ } private boolean noDirectCallsLeft(StructuredGraph graph) { - for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { + for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.TYPE).snapshot()) { if (methodCallTargetNode.targetMethod().equals(callDirectMethod)) { return false; } @@ -508,6 +573,25 @@ return null; } + TruffleInliningDecision decision = getDecision(inlining, callNode); + + StructuredGraph graph; + if (decision != null && decision.isInline()) { + if (inliningCache == null) { + graph = createInlineGraph(phaseContext, caller, null, decision); + } else { + graph = inliningCache.getCachedGraph(phaseContext, caller, decision); + } + caller.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) decision.getTarget().getNodeRewritingAssumption())); + } else { + // we continue expansion of callDirect until we reach the callBoundary. + graph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), phaseContext); + } + + return graph; + } + + private static TruffleInliningDecision getDecision(TruffleInlining inlining, OptimizedDirectCallNode callNode) { TruffleInliningDecision decision = inlining.findByCall(callNode); if (decision == null) { if (TruffleCompilerOptions.TraceTrufflePerformanceWarnings.getValue()) { @@ -524,25 +608,9 @@ properties.put("callNode", callNode); TracePerformanceWarningsListener.logPerformanceWarning(String.format("CallTarget changed during compilation. Call node could not be inlined."), properties); } - decision = null; + return null; } - - StructuredGraph graph; - if (decision != null && decision.isInline()) { - if (inliningCache == null) { - graph = createInlineGraph(phaseContext, caller, null, decision); - } else { - graph = inliningCache.getCachedGraph(phaseContext, caller, decision); - } - decision.getProfile().setGraalDeepNodeCount(graph.getNodeCount()); - - caller.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) decision.getTarget().getNodeRewritingAssumption())); - } else { - // we continue expansion of callDirect until we reach the callBoundary. - graph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), phaseContext); - } - - return graph; + return decision; } private OptimizedDirectCallNode resolveConstantCallNode(MethodCallTargetNode methodCallTargetNode) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -136,7 +136,7 @@ lastUsed.put(key, counter++); cache.put(key, markerGraph); - for (ParameterNode param : graph.getNodes(ParameterNode.class)) { + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { if (param.getKind() == Kind.Object) { ValueNode actualArgument = arguments.get(param.index()); param.setStamp(param.stamp().join(actualArgument.stamp())); @@ -147,7 +147,7 @@ new ReplaceIntrinsicsPhase(providers.getReplacements()).apply(graph); // Convert deopt to guards. - new ConvertDeoptimizeToGuardPhase().apply(graph); + new ConvertDeoptimizeToGuardPhase().apply(graph, phaseContext); PartialEscapePhase partialEscapePhase = new PartialEscapePhase(false, canonicalizer); @@ -164,7 +164,7 @@ canonicalizer.apply(graph, phaseContext); boolean inliningProgress = false; - for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { if (!graph.getMark().equals(mark)) { mark = lookupProcessMacroSubstitutions(graph, mark); } @@ -175,7 +175,7 @@ } // Convert deopt to guards. - new ConvertDeoptimizeToGuardPhase().apply(graph); + new ConvertDeoptimizeToGuardPhase().apply(graph, phaseContext); new EarlyReadEliminationPhase(canonicalizer).apply(graph, phaseContext); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -43,7 +43,6 @@ import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -81,14 +80,24 @@ this.compilationNotify = graalTruffleRuntime.getCompilationNotify(); this.backend = runtime.getHostBackend(); Replacements truffleReplacements = graalTruffleRuntime.getReplacements(); - ConstantReflectionProvider constantReflection = new TruffleConstantReflectionProvider(backend.getProviders().getConstantReflection(), backend.getProviders().getMetaAccess()); - this.providers = backend.getProviders().copyWith(truffleReplacements).copyWith(constantReflection); + Providers backendProviders = backend.getProviders(); + ConstantReflectionProvider constantReflection = new TruffleConstantReflectionProvider(backendProviders.getConstantReflection(), backendProviders.getMetaAccess()); + if (!TruffleCompilerOptions.FastPE.getValue()) { + backendProviders = backendProviders.copyWith(truffleReplacements); + } + this.providers = backendProviders.copyWith(constantReflection); this.suites = backend.getSuites().getDefaultSuites(); this.lirSuites = backend.getSuites().getDefaultLIRSuites(); ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault().withSkippedExceptionTypes(skippedExceptionTypes); + this.config = GraphBuilderConfiguration.getDefault().withSkippedExceptionTypes(skippedExceptionTypes); + if (TruffleCompilerOptions.FastPE.getValue()) { + GraphBuilderPhase phase = (GraphBuilderPhase) backend.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); + this.config.getInvocationPlugins().setDefaults(phase.getGraphBuilderConfig().getInvocationPlugins()); + } + this.truffleCache = new TruffleCacheImpl(providers, eagerConfig, TruffleCompilerImpl.Optimizations); this.partialEvaluator = new PartialEvaluator(providers, config, truffleCache, Graal.getRequiredCapability(SnippetReflectionProvider.class)); @@ -120,27 +129,21 @@ compilationNotify.notifyCompilationStarted(compilable); try { - GraphBuilderSuiteInfo info = createGraphBuilderSuite(); + PhaseSuite graphBuilderSuite = createGraphBuilderSuite(); try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) { - graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES, info.plugins); + graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES); } if (Thread.currentThread().isInterrupted()) { return; } - if (!TruffleCompilerOptions.TruffleInlineAcrossTruffleBoundary.getValue()) { - // Do not inline across Truffle boundaries. - for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.class)) { - mct.invoke().setUseForInlining(false); - } - } - compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph); - CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), info.suite, compilable.getSpeculationLog(), compilable); + CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), graphBuilderSuite, compilable.getSpeculationLog(), compilable); compilationNotify.notifyCompilationSuccess(compilable, graph, compilationResult); } catch (Throwable t) { + System.out.println("compilation failed!?"); compilationNotify.notifyCompilationFailed(compilable, graph, t); throw t; } @@ -158,8 +161,8 @@ CodeCacheProvider codeCache = providers.getCodeCache(); CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); CompilationResult compilationResult = new CompilationResult(name); - result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, graphBuilderSuite == null ? createGraphBuilderSuite().suite : graphBuilderSuite, - Optimizations, getProfilingInfo(graph), speculationLog, suites, lirSuites, compilationResult, CompilationResultBuilderFactory.Default); + result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, graphBuilderSuite, Optimizations, getProfilingInfo(graph), speculationLog, suites, + lirSuites, compilationResult, CompilationResultBuilderFactory.Default); } catch (Throwable e) { throw Debug.handle(e); } @@ -203,24 +206,12 @@ return result; } - static class GraphBuilderSuiteInfo { - final PhaseSuite suite; - final GraphBuilderPlugins plugins; - - public GraphBuilderSuiteInfo(PhaseSuite suite, GraphBuilderPlugins plugins) { - this.suite = suite; - this.plugins = plugins; - } - } - - private GraphBuilderSuiteInfo createGraphBuilderSuite() { + private PhaseSuite createGraphBuilderSuite() { PhaseSuite suite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); - GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous(); iterator.remove(); - GraphBuilderPlugins plugins = graphBuilderPhase.getGraphBuilderPlugins(); - iterator.add(new GraphBuilderPhase(config, plugins)); - return new GraphBuilderSuiteInfo(suite, plugins); + iterator.add(new GraphBuilderPhase(config)); + return suite; } public void processAssumption(Set newAssumptions, Assumption assumption, List manual) { diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Mar 02 19:11:22 2015 +0100 @@ -104,6 +104,9 @@ @Option(help = "Enable asynchronous truffle compilation in background thread", type = OptionType.Expert) public static final OptionValue TruffleBackgroundCompilation = new OptionValue<>(true); + @Option(help = "Manually set the number of compiler threads", type = OptionType.Expert) + public static final StableOptionValue TruffleCompilerThreads = new StableOptionValue<>(0); + @Option(help = "Enable inlining across Truffle boundary", type = OptionType.Expert) public static final OptionValue TruffleInlineAcrossTruffleBoundary = new OptionValue<>(false); @@ -119,6 +122,9 @@ @Option(help = "", type = OptionType.Debug) public static final OptionValue TruffleArgumentTypeSpeculation = new StableOptionValue<>(true); + @Option(help = "", type = OptionType.Debug) + public static final StableOptionValue TruffleUseFrameWithoutBoxing = new StableOptionValue<>(true); + // tracing @Option(help = "Print potential performance problems", type = OptionType.Debug) public static final OptionValue TraceTrufflePerformanceWarnings = new OptionValue<>(false); @@ -181,6 +187,6 @@ public static final OptionValue TruffleCompilationStatisticDetails = new OptionValue<>(false); @Option(help = "Experimental new version of the partial evaluator.", type = OptionType.Debug) - public static final OptionValue FastPE = new OptionValue<>(false); + public static final OptionValue FastPE = new OptionValue<>(true); // @formatter:on } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Mon Mar 02 19:11:22 2015 +0100 @@ -84,7 +84,7 @@ } private void registerParentInCalls(ExpansionTree parentTree, StructuredGraph graph) { - for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.TYPE)) { callToParentTree.put(target, parentTree); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,7 +32,6 @@ private final double frequency; private final boolean recursiveCall; - private int graalDeepNodeCount = -1; private String failedReason; private int queryIndex = -1; private double score; @@ -103,19 +102,7 @@ properties.put("frequency", String.format("%8.4f", getFrequency())); properties.put("score", String.format("%8.4f", getScore())); properties.put(String.format("index=%3d, force=%s, callSites=%2d", queryIndex, (isForced() ? "Y" : "N"), getCallSites()), ""); - if (graalDeepNodeCount != -1) { - properties.put("graalCount", String.format("%5d", graalDeepNodeCount)); - } properties.put("reason", failedReason); return properties; } - - public void setGraalDeepNodeCount(int graalDeepNodeCount) { - this.graalDeepNodeCount = graalDeepNodeCount; - } - - public int getGraalDeepNodeCount() { - return graalDeepNodeCount; - } - } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Mon Mar 02 19:11:22 2015 +0100 @@ -50,13 +50,15 @@ } protected void registerTruffleSubstitutions() { - registerSubstitutions(CompilerAsserts.class, CompilerAssertsSubstitutions.class); - registerSubstitutions(CompilerDirectives.class, CompilerDirectivesSubstitutions.class); - registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class); - registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); - registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class); - registerSubstitutions(FrameWithoutBoxing.class, FrameWithoutBoxingSubstitutions.class); - registerSubstitutions(UnsafeAccessImpl.class, UnsafeAccessSubstitutions.class); + if (!TruffleCompilerOptions.FastPE.getValue()) { + registerSubstitutions(CompilerAsserts.class, CompilerAssertsSubstitutions.class); + registerSubstitutions(CompilerDirectives.class, CompilerDirectivesSubstitutions.class); + registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class); + registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); + registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class); + registerSubstitutions(FrameWithoutBoxing.class, FrameWithoutBoxingSubstitutions.class); + registerSubstitutions(UnsafeAccessImpl.class, UnsafeAccessSubstitutions.class); + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationFailureListener.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationFailureListener.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationFailureListener.java Mon Mar 02 19:11:22 2015 +0100 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.nodes.*; import com.oracle.graal.truffle.*; @@ -39,7 +40,7 @@ @Override public void notifyCompilationFailed(OptimizedCallTarget target, StructuredGraph graph, Throwable t) { - if (isPermanentBailout(t)) { + if (isPermanentBailout(t) || GraalOptions.PrintBailout.getValue()) { Map properties = new LinkedHashMap<>(); properties.put("Reason", t.toString()); log(0, "opt fail", target.toString(), properties); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,6 +27,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -38,8 +39,10 @@ @NodeInfo public final class AssumptionNode extends MacroNode implements Simplifiable { + public static final NodeClass TYPE = NodeClass.create(AssumptionNode.class); + public AssumptionNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); assert super.arguments.size() == 1; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +33,10 @@ @NodeInfo public final class BailoutNode extends MacroNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(BailoutNode.class); + public BailoutNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); assert arguments.size() == 1; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IsCompilationConstantNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IsCompilationConstantNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IsCompilationConstantNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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,31 +22,36 @@ */ package com.oracle.graal.truffle.nodes; +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.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.replacements.nodes.*; @NodeInfo -public class IsCompilationConstantNode extends MacroStateSplitNode implements Canonicalizable { +public final class IsCompilationConstantNode extends FloatingNode implements Lowerable, Canonicalizable { + + public static final NodeClass TYPE = NodeClass.create(IsCompilationConstantNode.class); - public IsCompilationConstantNode(Invoke invoke) { - super(invoke); - assert arguments.size() == 1; + @Input ValueNode value; + + public IsCompilationConstantNode(ValueNode value) { + super(TYPE, StampFactory.forKind(Kind.Boolean)); + this.value = value; } @Override public void lower(LoweringTool tool) { - /* Invoke will return false. */ - replaceWithInvoke().lower(tool); + graph().replaceFloating(this, ConstantNode.forBoolean(false, graph())); } @Override public Node canonical(CanonicalizerTool tool) { - ValueNode arg0 = arguments.get(0); + ValueNode arg0 = value; if (arg0 instanceof BoxNode) { arg0 = ((BoxNode) arg0).getValue(); } @@ -55,4 +60,7 @@ } return this; } + + @NodeIntrinsic + public static native boolean check(Object value); } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,10 +37,11 @@ * case the addition would overflow the 32 bit range. */ @NodeInfo -public class IntegerAddExactNode extends AddNode implements IntegerExactArithmeticNode { +public final class IntegerAddExactNode extends AddNode implements IntegerExactArithmeticNode { + public static final NodeClass TYPE = NodeClass.create(IntegerAddExactNode.class); public IntegerAddExactNode(ValueNode x, ValueNode y) { - super(x, y); + super(TYPE, x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +24,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode { +public final class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode { + public static final NodeClass TYPE = NodeClass.create(IntegerAddExactSplitNode.class); public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { - super(stamp, x, y, next, overflowSuccessor); + super(TYPE, stamp, x, y, next, overflowSuccessor); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -31,14 +32,15 @@ @NodeInfo public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(IntegerExactArithmeticSplitNode.class); @Successor AbstractBeginNode overflowSuccessor; @Successor AbstractBeginNode next; @Input ValueNode x; @Input ValueNode y; - public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { - super(stamp); + protected IntegerExactArithmeticSplitNode(NodeClass c, Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(c, stamp); this.x = x; this.y = y; this.overflowSuccessor = overflowSuccessor; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -36,10 +37,11 @@ * in case the addition would overflow the 32 bit range. */ @NodeInfo -public class IntegerMulExactNode extends MulNode implements IntegerExactArithmeticNode { +public final class IntegerMulExactNode extends MulNode implements IntegerExactArithmeticNode { + public static final NodeClass TYPE = NodeClass.create(IntegerMulExactNode.class); public IntegerMulExactNode(ValueNode x, ValueNode y) { - super(x, y); + super(TYPE, x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +24,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode { +public final class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode { + public static final NodeClass TYPE = NodeClass.create(IntegerMulExactSplitNode.class); public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { - super(stamp, x, y, next, overflowSuccessor); + super(TYPE, stamp, x, y, next, overflowSuccessor); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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.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.nodeinfo.*; @@ -35,14 +36,15 @@ import com.oracle.truffle.api.*; @NodeInfo(shortName = "*H") -public class IntegerMulHighNode extends BinaryNode implements ArithmeticLIRLowerable { +public final class IntegerMulHighNode extends BinaryNode implements ArithmeticLIRLowerable { + public static final NodeClass TYPE = NodeClass.create(IntegerMulHighNode.class); public IntegerMulHighNode(ValueNode x, ValueNode y) { this((IntegerStamp) x.stamp().unrestricted(), x, y); } public IntegerMulHighNode(IntegerStamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + super(TYPE, stamp, x, y); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -37,10 +38,11 @@ * case the addition would overflow the 32 bit range. */ @NodeInfo -public class IntegerSubExactNode extends SubNode implements IntegerExactArithmeticNode { +public final class IntegerSubExactNode extends SubNode implements IntegerExactArithmeticNode { + public static final NodeClass TYPE = NodeClass.create(IntegerSubExactNode.class); public IntegerSubExactNode(ValueNode x, ValueNode y) { - super(x, y); + super(TYPE, x, y); assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,15 +24,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode { +public final class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode { + public static final NodeClass TYPE = NodeClass.create(IntegerSubExactSplitNode.class); public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { - super(stamp, x, y, next, overflowSuccessor); + super(TYPE, stamp, x, y, next, overflowSuccessor); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * 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.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.nodeinfo.*; @@ -35,14 +36,16 @@ import com.oracle.truffle.api.*; @NodeInfo(shortName = "|*H|") -public class UnsignedMulHighNode extends BinaryNode implements ArithmeticLIRLowerable { +public final class UnsignedMulHighNode extends BinaryNode implements ArithmeticLIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(UnsignedMulHighNode.class); public UnsignedMulHighNode(ValueNode x, ValueNode y) { this((IntegerStamp) x.stamp().unrestricted(), x, y); } public UnsignedMulHighNode(IntegerStamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); + super(TYPE, stamp, x, y); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/CompilationConstantNode.java Mon Mar 02 18:44:14 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +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.nodes.asserts; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; - -@NodeInfo -public final class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable { - - public CompilationConstantNode(Invoke invoke) { - super(invoke, "The value could not be reduced to a compile time constant."); - assert arguments.size() == 1; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (arguments.get(0).isConstant()) { - return arguments.get(0); - } - return this; - } -} diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ */ package com.oracle.graal.truffle.nodes.asserts; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -30,8 +31,10 @@ @NodeInfo public final class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(NeverInlineMacroNode.class); + public NeverInlineMacroNode(Invoke invoke) { - super(invoke); + super(TYPE, invoke); } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,34 +22,34 @@ */ package com.oracle.graal.truffle.nodes.asserts; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.nodes.*; @NodeInfo -public class NeverPartOfCompilationNode extends MacroStateSplitNode implements IterableNodeType { +public final class NeverPartOfCompilationNode extends FixedWithNextNode implements IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(NeverPartOfCompilationNode.class); protected final String message; - public NeverPartOfCompilationNode(Invoke invoke) { - this(invoke, "This code path should never be part of a compilation."); - } - - public NeverPartOfCompilationNode(Invoke invoke, String message) { - super(invoke); + public NeverPartOfCompilationNode(String message) { + super(TYPE, StampFactory.forVoid()); this.message = message; } - public final String getMessage() { - return message + " " + arguments.toString(); + public String getMessage() { + return message; } public static void verifyNotFoundIn(final StructuredGraph graph) { - for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) { + for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.TYPE)) { Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage()); throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception); } } + + @NodeIntrinsic + public static native void apply(@ConstantNodeParameter String message); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,17 +23,19 @@ package com.oracle.graal.truffle.nodes.frame; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @NodeInfo -public class ForceMaterializeNode extends FixedWithNextNode implements LIRLowerable { +public final class ForceMaterializeNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(ForceMaterializeNode.class); @Input ValueNode object; public ForceMaterializeNode(ValueNode object) { - super(StampFactory.forVoid()); + super(TYPE, StampFactory.forVoid()); this.object = object; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,18 +25,19 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.frame.*; /** * Intrinsic node for materializing a Truffle frame. */ @NodeInfo(nameTemplate = "MaterializeFrame{p#frame/s}") -public class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType { +public final class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType { + public static final NodeClass TYPE = NodeClass.create(MaterializeFrameNode.class); @Input ValueNode frame; public MaterializeFrameNode(ValueNode frame) { - super(frame.stamp()); + super(TYPE, frame.stamp()); this.frame = frame; } @@ -45,5 +46,5 @@ } @NodeIntrinsic - public static native T materialize(FrameWithoutBoxing frame); + public static native T materialize(VirtualFrame frame); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,11 +48,12 @@ @NodeInfo public final class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(NewFrameNode.class); @Input ValueNode descriptor; @Input ValueNode arguments; public NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode arguments) { - super(stamp); + super(TYPE, stamp); this.descriptor = descriptor; this.arguments = arguments; } @@ -92,16 +93,17 @@ return field; } } - throw new RuntimeException("Frame field not found: " + fieldName); + return null; } @NodeInfo public static final class VirtualOnlyInstanceNode extends VirtualInstanceNode { + public static final NodeClass TYPE = NodeClass.create(VirtualOnlyInstanceNode.class); protected boolean allowMaterialization; public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { - super(type, fields, true); + super(TYPE, type, fields, true); } @Override @@ -156,8 +158,8 @@ VirtualObjectNode virtualFrame = new VirtualOnlyInstanceNode(frameType, frameFields); VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize); - VirtualObjectNode virtualFramePrimitiveArray = new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize); - VirtualObjectNode virtualFrameTagArray = new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFramePrimitiveArray = (primitiveLocalsField == null ? null : new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize)); + VirtualObjectNode virtualFrameTagArray = (primitiveLocalsField == null ? null : new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize)); ValueNode[] objectArrayEntryState = new ValueNode[frameSize]; ValueNode[] primitiveArrayEntryState = new ValueNode[frameSize]; @@ -168,25 +170,37 @@ ConstantNode objectDefault = ConstantNode.forConstant(getSnippetReflection().forObject(frameDescriptor.getDefaultValue()), tool.getMetaAccessProvider(), graph()); ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph()); Arrays.fill(objectArrayEntryState, objectDefault); - Arrays.fill(tagArrayEntryState, tagDefault); - for (int i = 0; i < frameSize; i++) { - primitiveArrayEntryState[i] = initialPrimitiveValue(frameDescriptor.getSlots().get(i).getKind()); + if (virtualFrameTagArray != null) { + Arrays.fill(tagArrayEntryState, tagDefault); + } + if (virtualFramePrimitiveArray != null) { + for (int i = 0; i < frameSize; i++) { + primitiveArrayEntryState[i] = initialPrimitiveValue(frameDescriptor.getSlots().get(i).getKind()); + } } graph().getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); } tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, Collections. emptyList()); - tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, Collections. emptyList()); - tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, Collections. emptyList()); + if (virtualFramePrimitiveArray != null) { + tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, Collections. emptyList()); + } + if (virtualFrameTagArray != null) { + tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, Collections. emptyList()); + } - assert frameFields.length == 5; + assert frameFields.length == 5 || frameFields.length == 3; ValueNode[] frameEntryState = new ValueNode[frameFields.length]; List frameFieldList = Arrays.asList(frameFields); frameEntryState[frameFieldList.indexOf(descriptorField)] = getDescriptor(); frameEntryState[frameFieldList.indexOf(argumentsField)] = getArguments(); frameEntryState[frameFieldList.indexOf(localsField)] = virtualFrameObjectArray; - frameEntryState[frameFieldList.indexOf(primitiveLocalsField)] = virtualFramePrimitiveArray; - frameEntryState[frameFieldList.indexOf(tagsField)] = virtualFrameTagArray; + if (primitiveLocalsField != null) { + frameEntryState[frameFieldList.indexOf(primitiveLocalsField)] = virtualFramePrimitiveArray; + } + if (tagsField != null) { + frameEntryState[frameFieldList.indexOf(tagsField)] = virtualFrameTagArray; + } tool.createVirtualObject(virtualFrame, frameEntryState, Collections. emptyList()); tool.replaceWithVirtual(virtualFrame); } @@ -230,5 +244,5 @@ } @NodeIntrinsic - public static native FrameWithoutBoxing allocate(@ConstantNodeParameter Class frameType, FrameDescriptor descriptor, Object[] args); + public static native VirtualFrame allocate(@ConstantNodeParameter Class frameType, FrameDescriptor descriptor, Object[] args); } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,14 +30,15 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.truffle.nodes.*; -import com.oracle.graal.truffle.nodes.asserts.*; /** * Macro node for CompilerDirectives#unsafeGetInt*. */ @NodeInfo -public final class CustomizedUnsafeLoadMacroNode extends NeverPartOfCompilationNode implements Canonicalizable { +public final class CustomizedUnsafeLoadMacroNode extends MacroStateSplitNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(CustomizedUnsafeLoadMacroNode.class); private static final int ARGUMENT_COUNT = 4; private static final int OBJECT_ARGUMENT_INDEX = 0; @@ -46,7 +47,7 @@ private static final int LOCATION_ARGUMENT_INDEX = 3; public CustomizedUnsafeLoadMacroNode(Invoke invoke) { - super(invoke, "The location argument could not be resolved to a constant."); + super(TYPE, invoke); assert arguments.size() == ARGUMENT_COUNT; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,14 +28,15 @@ import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.truffle.nodes.*; -import com.oracle.graal.truffle.nodes.asserts.*; /** * Macro node for method CompilerDirectives#unsafePut*. */ @NodeInfo -public final class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable, StateSplit { +public final class CustomizedUnsafeStoreMacroNode extends MacroStateSplitNode implements Canonicalizable, StateSplit { + public static final NodeClass TYPE = NodeClass.create(CustomizedUnsafeStoreMacroNode.class); private static final int ARGUMENT_COUNT = 4; private static final int OBJECT_ARGUMENT_INDEX = 0; private static final int OFFSET_ARGUMENT_INDEX = 1; @@ -43,7 +44,7 @@ private static final int LOCATION_ARGUMENT_INDEX = 3; public CustomizedUnsafeStoreMacroNode(Invoke invoke) { - super(invoke, "The location argument could not be resolved to a constant."); + super(TYPE, invoke); assert arguments.size() == ARGUMENT_COUNT; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,19 +25,21 @@ 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.nodeinfo.*; 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.graal.replacements.nodes.*; /** * Macro node for method CompilerDirectives#unsafeCast. */ @NodeInfo -public class UnsafeTypeCastMacroNode extends NeverPartOfCompilationNode implements Simplifiable { +public final class UnsafeTypeCastMacroNode extends MacroStateSplitNode implements Simplifiable { + public static final NodeClass TYPE = NodeClass.create(UnsafeTypeCastMacroNode.class); private static final int OBJECT_ARGUMENT_INDEX = 0; private static final int CLASS_ARGUMENT_INDEX = 1; private static final int CONDITION_ARGUMENT_INDEX = 2; @@ -45,7 +47,7 @@ private static final int ARGUMENT_COUNT = 4; public UnsafeTypeCastMacroNode(Invoke invoke) { - super(invoke, "The class of the unsafe cast could not be reduced to a compile time constant."); + super(TYPE, invoke); assert arguments.size() == ARGUMENT_COUNT; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -43,7 +43,7 @@ @Override protected void run(StructuredGraph graph) { - for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { if (methodCallTarget.isAlive()) { InvokeKind invokeKind = methodCallTarget.invokeKind(); if (invokeKind.isDirect()) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,7 +37,7 @@ @Override protected void run(StructuredGraph graph) { - for (NewFrameNode virtualFrame : graph.getNodes(NewFrameNode.class)) { + for (NewFrameNode virtualFrame : graph.getNodes(NewFrameNode.TYPE)) { for (MethodCallTargetNode callTarget : virtualFrame.usages().filter(MethodCallTargetNode.class)) { if (callTarget.invoke() != null) { String properties = callTarget.getDebugProperties().toString(); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Mon Mar 02 19:11:22 2015 +0100 @@ -23,43 +23,15 @@ package com.oracle.graal.truffle.substitutions; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.truffle.nodes.asserts.*; import com.oracle.truffle.api.*; @ClassSubstitution(CompilerAsserts.class) public class CompilerAssertsSubstitutions { - @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); - - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native byte compilationConstant(byte value); - - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native char compilationConstant(char value); + @MethodSubstitution + public static void neverPartOfCompilation(@SuppressWarnings("unused") String message) { + NeverPartOfCompilationNode.apply("Never part of compilation"); + } - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native short compilationConstant(short value); - - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native int compilationConstant(int value); - - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native long compilationConstant(long value); - - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native float compilationConstant(float value); - - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native double compilationConstant(double value); - - @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) - public static native Object compilationConstant(Object value); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Mon Mar 02 19:11:22 2015 +0100 @@ -73,8 +73,10 @@ @MacroSubstitution(macro = BailoutNode.class, isStatic = true) public static native void bailout(String reason); - @MacroSubstitution(macro = IsCompilationConstantNode.class, isStatic = true) - public static native boolean isCompilationConstant(Object value); + @MethodSubstitution + public static boolean isCompilationConstant(Object value) { + return IsCompilationConstantNode.check(value); + } @MethodSubstitution public static void materialize(Object obj) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,7 +33,7 @@ public class OptimizedCallTargetSubstitutions { @MethodSubstitution - private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) { + private static VirtualFrame createFrame(FrameDescriptor descriptor, Object[] args) { return NewFrameNode.allocate(FrameWithoutBoxing.class, descriptor, args); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,15 +26,15 @@ import java.util.concurrent.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; 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.java.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.InvocationPlugins.Registration; +import com.oracle.graal.java.InvocationPlugins.Registration.Receiver; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -47,12 +47,26 @@ import com.oracle.truffle.api.frame.*; /** - * Provider of {@link GraphBuilderPlugin}s for Truffle classes. + * Provides {@link InvocationPlugin}s for Truffle classes. */ public class TruffleGraphBuilderPlugins { - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + + registerOptimizedAssumptionPlugins(metaAccess, plugins); + registerExactMathPlugins(metaAccess, plugins); + registerCompilerDirectivesPlugins(metaAccess, plugins); + registerOptimizedCallTargetPlugins(metaAccess, plugins); + registerUnsafeAccessImplPlugins(metaAccess, plugins); - // OptimizedAssumption.class + if (TruffleCompilerOptions.TruffleUseFrameWithoutBoxing.getValue()) { + registerFrameWithoutBoxingPlugins(metaAccess, plugins); + } else { + registerFrameWithBoxingPlugins(metaAccess, plugins); + } + + } + + public static void registerOptimizedAssumptionPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, OptimizedAssumption.class); r.register1("isValid", Receiver.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode arg) { @@ -60,25 +74,55 @@ Constant constant = arg.asConstant(); OptimizedAssumption assumption = builder.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant); builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(assumption.isValid()))); - builder.getAssumptions().record(new AssumptionValidAssumption(assumption)); + if (assumption.isValid()) { + builder.getAssumptions().record(new AssumptionValidAssumption(assumption)); + } } else { - throw new BailoutException("assumption could not be reduced to a constant"); + throw builder.bailout("assumption could not be reduced to a constant"); } return true; } }); + } - // ExactMath.class - r = new Registration(plugins, metaAccess, ExactMath.class); - r.register2("addExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { - builder.push(Kind.Int.getStackKind(), builder.append(new IntegerAddExactNode(x, y))); - return true; - } - }); + public static void registerExactMathPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, ExactMath.class); + for (Kind kind : new Kind[]{Kind.Int, Kind.Long}) { + r.register2("addExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(kind.getStackKind(), builder.append(new IntegerAddExactNode(x, y))); + return true; + } + }); + r.register2("subtractExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(kind.getStackKind(), builder.append(new IntegerSubExactNode(x, y))); + return true; + } + }); + r.register2("multiplyExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(kind.getStackKind(), builder.append(new IntegerMulExactNode(x, y))); + return true; + } + }); + r.register2("multiplyHigh", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(kind.getStackKind(), builder.append(new IntegerMulHighNode(x, y))); + return true; + } + }); + r.register2("multiplyHighUnsigned", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(kind.getStackKind(), builder.append(new UnsignedMulHighNode(x, y))); + return true; + } + }); + } + } - // CompilerDirectives.class - r = new Registration(plugins, metaAccess, CompilerDirectives.class); + public static void registerCompilerDirectivesPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class); r.register0("inInterpreter", new InvocationPlugin() { public boolean apply(GraphBuilderContext builder) { builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(false))); @@ -122,18 +166,19 @@ r.register1("bailout", String.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode message) { if (message.isConstant()) { - throw new BailoutException(message.asConstant().toValueString()); + throw builder.bailout(message.asConstant().toValueString()); } - throw new BailoutException("bailout (message is not compile-time constant, so no additional information is available)"); + throw builder.bailout("bailout (message is not compile-time constant, so no additional information is available)"); } }); r.register1("isCompilationConstant", Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode value) { if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) { builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(true))); - return true; + } else { + builder.push(Kind.Boolean.getStackKind(), builder.append(new IsCompilationConstantNode(value))); } - return false; + return true; } }); r.register1("materialize", Object.class, new InvocationPlugin() { @@ -143,23 +188,74 @@ } }); - // OptimizedCallTarget.class - r = new Registration(plugins, metaAccess, OptimizedCallTarget.class); + r = new Registration(plugins, metaAccess, CompilerAsserts.class); + r.register1("partialEvaluationConstant", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ValueNode curValue = value; + if (curValue instanceof BoxNode) { + BoxNode boxNode = (BoxNode) curValue; + curValue = boxNode.getValue(); + } + if (curValue.isConstant()) { + return true; + } else { + StringBuilder sb = new StringBuilder(); + sb.append(curValue); + if (curValue instanceof ValuePhiNode) { + ValuePhiNode valuePhi = (ValuePhiNode) curValue; + sb.append(" ("); + for (Node n : valuePhi.inputs()) { + sb.append(n); + sb.append("; "); + } + sb.append(")"); + } + throw builder.bailout("Partial evaluation did not reduce value to a constant, is a regular compiler node: " + sb.toString()); + } + } + }); + } + + public static void registerOptimizedCallTargetPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, OptimizedCallTarget.class); r.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { - builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(FrameWithoutBoxing.class)), arg1, arg2))); + Class frameClass = TruffleCompilerOptions.TruffleUseFrameWithoutBoxing.getValue() ? FrameWithoutBoxing.class : FrameWithBoxing.class; + builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(frameClass)), arg1, arg2))); return true; } }); + } - // FrameWithoutBoxing.class - r = new Registration(plugins, metaAccess, FrameWithoutBoxing.class); + public static void registerFrameWithoutBoxingPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, FrameWithoutBoxing.class); + registerMaterialize(r); + registerUnsafeCast(r); + registerUnsafeLoadStorePlugins(r, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object); + } + + public static void registerFrameWithBoxingPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, FrameWithBoxing.class); + registerMaterialize(r); + registerUnsafeCast(r); + } + + public static void registerUnsafeAccessImplPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, UnsafeAccessImpl.class); + registerUnsafeCast(r); + registerUnsafeLoadStorePlugins(r, Kind.Boolean, Kind.Byte, Kind.Int, Kind.Short, Kind.Long, Kind.Float, Kind.Double, Kind.Object); + } + + private static void registerMaterialize(Registration r) { r.register1("materialize", Receiver.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode frame) { - builder.append(new MaterializeFrameNode(frame)); + builder.push(Kind.Object, builder.append(new MaterializeFrameNode(frame))); return true; } }); + } + + private static void registerUnsafeCast(Registration r) { r.register4("unsafeCast", Object.class, Class.class, boolean.class, boolean.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) { if (clazz.isConstant() && nonNull.isConstant()) { @@ -168,7 +264,16 @@ if (javaType == null) { builder.push(Kind.Object, object); } else { - Stamp piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0); + Stamp piStamp = null; + if (javaType.isArray()) { + if (nonNull.asJavaConstant().asInt() != 0) { + piStamp = StampFactory.exactNonNull(javaType); + } else { + piStamp = StampFactory.exact(javaType); + } + } else { + piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0); + } LogicNode compareNode = CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), constantReflection); boolean skipAnchor = false; if (compareNode instanceof LogicConstantNode) { @@ -189,12 +294,6 @@ throw GraalInternalError.shouldNotReachHere("unsafeCast arguments could not reduce to a constant: " + clazz + ", " + nonNull); } }); - - registerUnsafeLoadStorePlugins(r, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object); - - // CompilerDirectives.class - r = new Registration(plugins, metaAccess, UnsafeAccessImpl.class); - registerUnsafeLoadStorePlugins(r, Kind.Boolean, Kind.Byte, Kind.Int, Kind.Short, Kind.Long, Kind.Float, Kind.Double, Kind.Object); } protected static void registerUnsafeLoadStorePlugins(Registration r, Kind... kinds) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +31,9 @@ * This class encapsulated the materialized state of an escape analyzed object. */ @NodeInfo -public class MaterializedObjectState extends EscapeObjectState implements Node.ValueNumberable { +public final class MaterializedObjectState extends EscapeObjectState implements Node.ValueNumberable { + public static final NodeClass TYPE = NodeClass.create(MaterializedObjectState.class); @Input ValueNode materializedValue; public ValueNode materializedValue() { @@ -40,7 +41,7 @@ } public MaterializedObjectState(VirtualObjectNode object, ValueNode materializedValue) { - super(object); + super(TYPE, object); this.materializedValue = materializedValue; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +33,9 @@ * This class encapsulated the virtual state of an escape analyzed object. */ @NodeInfo -public class VirtualObjectState extends EscapeObjectState implements Node.ValueNumberable { +public final class VirtualObjectState extends EscapeObjectState implements Node.ValueNumberable { + public static final NodeClass TYPE = NodeClass.create(VirtualObjectState.class); @Input NodeInputList values; public NodeInputList values() { @@ -42,13 +43,13 @@ } public VirtualObjectState(VirtualObjectNode object, ValueNode[] values) { - super(object); + super(TYPE, object); assert object.entryCount() == values.length; this.values = new NodeInputList<>(this, values); } public VirtualObjectState(VirtualObjectNode object, List values) { - super(object); + super(TYPE, object); assert object.entryCount() == values.size(); this.values = new NodeInputList<>(this, values); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; @@ -111,6 +112,12 @@ }; ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); assert VirtualUtil.assertNonReachable(graph, obsoleteNodes); + for (Node node : obsoleteNodes) { + if (node.isAlive()) { + node.replaceAtUsages(null); + GraphUtil.killWithUnusedFloatingInputs(node); + } + } } @Override diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Mon Mar 02 19:11:22 2015 +0100 @@ -130,23 +130,16 @@ * * @param node The fixed node that should be deleted. */ - public void deleteFixedNode(final FixedWithNextNode node) { + public void deleteNode(final Node node) { add("delete fixed node", (graph, obsoleteNodes) -> { - GraphUtil.unlinkFixedNode(node); - assert obsoleteNodes.add(node); + if (node instanceof FixedWithNextNode) { + GraphUtil.unlinkFixedNode((FixedWithNextNode) node); + } + obsoleteNodes.add(node); }); } /** - * Removes the given fixed node from the control flow. - * - * @param node The fixed node that should be deleted. - */ - public void unlinkFixedNode(final FixedWithNextNode node) { - add("unlink fixed node", graph -> GraphUtil.unlinkFixedNode(node)); - } - - /** * Replaces the given node at its usages without deleting it. If the current node is a fixed * node it will be disconnected from the control flow, so that it will be deleted by a * subsequent {@link DeadCodeEliminationPhase} @@ -165,11 +158,9 @@ } node.replaceAtUsages(replacement); if (node instanceof FixedWithNextNode) { - FixedNode next = ((FixedWithNextNode) node).next(); - ((FixedWithNextNode) node).setNext(null); - node.replaceAtPredecessor(next); - assert obsoleteNodes.add(node); + GraphUtil.unlinkFixedNode((FixedWithNextNode) node); } + obsoleteNodes.add(node); }); } @@ -181,6 +172,7 @@ * @param newInput The value to replace with. */ public void replaceFirstInput(final Node node, final Node oldInput, final Node newInput) { + assert node.isAlive() && oldInput.isAlive() && !newInput.isDeleted(); add("replace first input", new Effect() { @Override public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { @@ -194,13 +186,4 @@ } }); } - - /** - * Performs a custom action. - * - * @param action The action that should be performed when the effects are applied. - */ - public void customAction(final Runnable action) { - add("customAction", graph -> action.run()); - } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Mon Mar 02 19:11:22 2015 +0100 @@ -94,7 +94,7 @@ ValueNode value = getScalarAlias(store.value()); boolean result = false; if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(store); + effects.deleteNode(store); result = true; } state.killReadCache(store.field()); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Mon Mar 02 19:11:22 2015 +0100 @@ -120,6 +120,7 @@ ValueNode[] entries = obj.getEntries(); ValueNode representation = virtual.getMaterializedRepresentation(fixed, entries, obj.getLocks()); obj.escape(representation, state); + PartialEscapeClosure.updateStatesForMaterialized(this, obj); if (representation instanceof AllocatedObjectNode) { objects.add((AllocatedObjectNode) representation); locks.add(LockState.asList(obj.getLocks())); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Mar 02 19:11:22 2015 +0100 @@ -224,7 +224,7 @@ } } - private static void updateStatesForMaterialized(PartialEscapeBlockState state, ObjectState obj) { + public static void updateStatesForMaterialized(PartialEscapeBlockState state, ObjectState obj) { // update all existing states with the newly materialized object for (ObjectState objState : state.objectStates.values()) { if (objState.isVirtual()) { @@ -649,6 +649,7 @@ if (uniqueVirtualObject) { // all inputs refer to the same object: just make the phi node an alias addAndMarkAlias(objStates[0].virtual, phi); + mergeEffects.deleteNode(phi); return false; } else { // all inputs are virtual: check if they're compatible and without identity @@ -680,6 +681,7 @@ if (compatible) { VirtualObjectNode virtual = getValueObjectVirtual(phi, getObjectState(states.get(0), phi.valueAt(0)).virtual); mergeEffects.addFloatingNode(virtual, "valueObjectNode"); + mergeEffects.deleteNode(phi); boolean materialized = mergeObjectStates(virtual, objStates, states); addAndMarkAlias(virtual, virtual); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Mon Mar 02 19:11:22 2015 +0100 @@ -75,7 +75,7 @@ StoreFieldNode store = (StoreFieldNode) node; ValueNode value = getScalarAlias(store.value()); if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(store); + effects.deleteNode(store); deleted = true; } state.killReadCache(store.field()); @@ -108,7 +108,7 @@ ValueNode value = getScalarAlias(write.value()); if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); + effects.deleteNode(write); deleted = true; } processIdentity(state, write.location().getLocationIdentity()); @@ -141,7 +141,7 @@ ValueNode value = getScalarAlias(write.value()); if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); + effects.deleteNode(write); deleted = true; } processIdentity(state, write.getLocationIdentity()); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Mon Mar 02 19:11:22 2015 +0100 @@ -62,7 +62,7 @@ } for (Node node : obsoleteNodes) { - if (node instanceof FixedNode) { + if (node instanceof FixedNode && !node.isDeleted()) { assert !flood.isMarked(node) : node; } } @@ -87,7 +87,7 @@ } boolean success = true; for (Node node : obsoleteNodes) { - if (flood.isMarked(node)) { + if (!node.isDeleted() && flood.isMarked(node)) { TTY.println("offending node path:"); Node current = node; TTY.print(current.toString()); @@ -109,12 +109,24 @@ return success; } - public static void trace(String format, Object... obj) { - if (TraceEscapeAnalysis.getValue() && Debug.isLogEnabled()) { + public static void trace(String format, Object obj) { + if (Debug.isEnabled() && TraceEscapeAnalysis.getValue() && Debug.isLogEnabled()) { Debug.logv(format, obj); } } + public static void trace(String format, Object obj, Object obj2) { + if (Debug.isEnabled() && TraceEscapeAnalysis.getValue() && Debug.isLogEnabled()) { + Debug.logv(format, obj, obj2); + } + } + + public static void trace(String format, Object obj, Object obj2, Object obj3) { + if (Debug.isEnabled() && TraceEscapeAnalysis.getValue() && Debug.isLogEnabled()) { + Debug.logv(format, obj, obj2, obj3); + } + } + public static boolean matches(StructuredGraph graph, String filter) { if (filter != null) { return matchesHelper(graph, filter); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -117,9 +117,7 @@ @Override public void replaceWithVirtual(VirtualObjectNode virtual) { closure.addAndMarkAlias(virtual, current); - if (current instanceof FixedWithNextNode) { - effects.deleteFixedNode((FixedWithNextNode) current); - } + effects.deleteNode(current); deleted = true; } @@ -132,7 +130,7 @@ @Override public void delete() { - effects.deleteFixedNode((FixedWithNextNode) current); + effects.deleteNode(current); deleted = true; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,7 +26,7 @@ /** * Returns a Signed whose value is {@code (this + val)}. - * + * * @param val value to be added to this Signed. * @return {@code this + val} */ @@ -34,7 +34,7 @@ /** * Returns a Signed whose value is {@code (this - val)}. - * + * * @param val value to be subtracted from this Signed. * @return {@code this - val} */ @@ -42,7 +42,7 @@ /** * Returns a Signed whose value is {@code (this * val)}. - * + * * @param val value to be multiplied by this Signed. * @return {@code this * val} */ @@ -50,7 +50,7 @@ /** * Returns a Signed whose value is {@code (this / val)}. - * + * * @param val value by which this Signed is to be divided. * @return {@code this / val} */ @@ -58,7 +58,7 @@ /** * Returns a Signed whose value is {@code (this % val)}. - * + * * @param val value by which this Signed is to be divided, and the remainder computed. * @return {@code this % val} */ @@ -66,7 +66,7 @@ /** * Returns a Signed whose value is {@code (this << n)}. - * + * * @param n shift distance, in bits. * @return {@code this << n} */ @@ -74,7 +74,7 @@ /** * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed. - * + * * @param n shift distance, in bits. * @return {@code this >> n} */ @@ -83,7 +83,7 @@ /** * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed * if and only if this and val are both negative.) - * + * * @param val value to be AND'ed with this Signed. * @return {@code this & val} */ @@ -92,7 +92,7 @@ /** * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed * if and only if either this or val is negative.) - * + * * @param val value to be OR'ed with this Signed. * @return {@code this | val} */ @@ -101,7 +101,7 @@ /** * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed * if and only if exactly one of this and val are negative.) - * + * * @param val value to be XOR'ed with this Signed. * @return {@code this ^ val} */ @@ -110,14 +110,14 @@ /** * Returns a Signed whose value is {@code (~this)}. (This method returns a negative value if and * only if this Signed is non-negative.) - * + * * @return {@code ~this} */ Signed not(); /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this == val} */ @@ -125,7 +125,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this != val} */ @@ -133,7 +133,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this < val} */ @@ -141,7 +141,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this <= val} */ @@ -149,7 +149,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this > val} */ @@ -157,7 +157,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this >= val} */ @@ -165,7 +165,7 @@ /** * Returns a Signed whose value is {@code (this + val)}. - * + * * @param val value to be added to this Signed. * @return {@code this + val} */ @@ -173,7 +173,7 @@ /** * Returns a Signed whose value is {@code (this - val)}. - * + * * @param val value to be subtracted from this Signed. * @return {@code this - val} */ @@ -181,7 +181,7 @@ /** * Returns a Signed whose value is {@code (this * val)}. - * + * * @param val value to be multiplied by this Signed. * @return {@code this * val} */ @@ -189,7 +189,7 @@ /** * Returns a Signed whose value is {@code (this / val)}. - * + * * @param val value by which this Signed is to be divided. * @return {@code this / val} */ @@ -197,7 +197,7 @@ /** * Returns a Signed whose value is {@code (this % val)}. - * + * * @param val value by which this Signed is to be divided, and the remainder computed. * @return {@code this % val} */ @@ -205,7 +205,7 @@ /** * Returns a Signed whose value is {@code (this << n)}. - * + * * @param n shift distance, in bits. * @return {@code this << n} */ @@ -213,7 +213,7 @@ /** * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed. - * + * * @param n shift distance, in bits. * @return {@code this >> n} */ @@ -222,7 +222,7 @@ /** * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed * if and only if this and val are both negative.) - * + * * @param val value to be AND'ed with this Signed. * @return {@code this & val} */ @@ -231,7 +231,7 @@ /** * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed * if and only if either this or val is negative.) - * + * * @param val value to be OR'ed with this Signed. * @return {@code this | val} */ @@ -240,7 +240,7 @@ /** * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed * if and only if exactly one of this and val are negative.) - * + * * @param val value to be XOR'ed with this Signed. * @return {@code this ^ val} */ @@ -248,7 +248,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this == val} */ @@ -256,7 +256,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this != val} */ @@ -264,7 +264,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this < val} */ @@ -272,7 +272,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this <= val} */ @@ -280,7 +280,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this > val} */ @@ -288,7 +288,7 @@ /** * Compares this Signed with the specified value. - * + * * @param val value to which this Signed is to be compared. * @return {@code this >= val} */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,7 +26,7 @@ /** * Returns a Unsigned whose value is {@code (this + val)}. - * + * * @param val value to be added to this Unsigned. * @return {@code this + val} */ @@ -34,7 +34,7 @@ /** * Returns a Unsigned whose value is {@code (this - val)}. - * + * * @param val value to be subtracted from this Unsigned. * @return {@code this - val} */ @@ -42,7 +42,7 @@ /** * Returns a Unsigned whose value is {@code (this * val)}. - * + * * @param val value to be multiplied by this Unsigned. * @return {@code this * val} */ @@ -50,7 +50,7 @@ /** * Returns a Unsigned whose value is {@code (this / val)}. - * + * * @param val value by which this Unsigned is to be divided. * @return {@code this / val} */ @@ -58,7 +58,7 @@ /** * Returns a Unsigned whose value is {@code (this % val)}. - * + * * @param val value by which this Unsigned is to be divided, and the remainder computed. * @return {@code this % val} */ @@ -66,7 +66,7 @@ /** * Returns a Unsigned whose value is {@code (this << n)}. - * + * * @param n shift distance, in bits. * @return {@code this << n} */ @@ -74,7 +74,7 @@ /** * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed. - * + * * @param n shift distance, in bits. * @return {@code this >> n} */ @@ -82,7 +82,7 @@ /** * Returns a Unsigned whose value is {@code (this & val)}. - * + * * @param val value to be AND'ed with this Unsigned. * @return {@code this & val} */ @@ -90,7 +90,7 @@ /** * Returns a Unsigned whose value is {@code (this | val)}. - * + * * @param val value to be OR'ed with this Unsigned. * @return {@code this | val} */ @@ -98,7 +98,7 @@ /** * Returns a Unsigned whose value is {@code (this ^ val)}. - * + * * @param val value to be XOR'ed with this Unsigned. * @return {@code this ^ val} */ @@ -106,14 +106,14 @@ /** * Returns a Unsigned whose value is {@code (~this)}. - * + * * @return {@code ~this} */ Unsigned not(); /** * Compares this Unsigned with the specified value. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this == val} */ @@ -121,7 +121,7 @@ /** * Compares this Unsigned with the specified value. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this != val} */ @@ -129,7 +129,7 @@ /** * Compares this Unsigned with the specified value. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this < val} */ @@ -137,7 +137,7 @@ /** * Compares this Unsigned with the specified value. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this <= val} */ @@ -145,7 +145,7 @@ /** * Compares this Unsigned with the specified value. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this > val} */ @@ -153,7 +153,7 @@ /** * Compares this Unsigned with the specified value. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this >= val} */ @@ -164,7 +164,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to be added to this Unsigned. * @return {@code this + val} */ @@ -175,7 +175,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to be subtracted from this Unsigned. * @return {@code this - val} */ @@ -186,7 +186,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to be multiplied by this Unsigned. * @return {@code this * val} */ @@ -197,7 +197,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value by which this Unsigned is to be divided. * @return {@code this / val} */ @@ -208,7 +208,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value by which this Unsigned is to be divided, and the remainder computed. * @return {@code this % val} */ @@ -219,7 +219,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param n shift distance, in bits. * @return {@code this << n} */ @@ -230,7 +230,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param n shift distance, in bits. * @return {@code this >> n} */ @@ -241,7 +241,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to be AND'ed with this Unsigned. * @return {@code this & val} */ @@ -252,7 +252,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to be OR'ed with this Unsigned. * @return {@code this | val} */ @@ -263,7 +263,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to be XOR'ed with this Unsigned. * @return {@code this ^ val} */ @@ -274,7 +274,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this == val} */ @@ -285,7 +285,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this != val} */ @@ -296,7 +296,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this < val} */ @@ -307,7 +307,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this <= val} */ @@ -318,7 +318,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this > val} */ @@ -329,7 +329,7 @@ *

    * Note that the right operand is a signed value, while the operation is performed unsigned. * Therefore, the result is only well-defined for positive right operands. - * + * * @param val value to which this Unsigned is to be compared. * @return {@code this >= val} */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ * this node can be canonicalized to a {@link IndexedLocationNode} or {@link ConstantLocationNode}. */ @NodeInfo -public class SnippetLocationNode extends LocationNode implements Canonicalizable { +public final class SnippetLocationNode extends LocationNode implements Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(SnippetLocationNode.class); protected final SnippetReflectionProvider snippetReflection; @@ -58,7 +59,7 @@ } public SnippetLocationNode(@InjectedNodeParameter SnippetReflectionProvider snippetReflection, ValueNode locationIdentity, ValueNode displacement, ValueNode index, ValueNode indexScaling) { - super(StampFactory.object()); + super(TYPE, StampFactory.object()); this.snippetReflection = snippetReflection; this.locationIdentity = locationIdentity; this.displacement = displacement; diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * 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,8 +36,9 @@ * impact on the pointer maps for the GC, so it must not be scheduled or optimized away. */ @NodeInfo -public class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable { +public final class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable { + public static final NodeClass TYPE = NodeClass.create(WordCastNode.class); @Input ValueNode input; public static WordCastNode wordToObject(ValueNode input, Kind wordKind) { @@ -51,7 +52,7 @@ } public WordCastNode(Stamp stamp, ValueNode input) { - super(stamp); + super(TYPE, stamp); this.input = input; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java --- a/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,14 +33,14 @@ /** * Returns the name of the function. - * + * * @return name of the function */ String getName(); /** * Returns the raw function pointer value. - * + * * @return raw function pointer value */ long getRawValue(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,7 +28,7 @@ /** * Experimental API. - * + * * @deprecated annotation has no effect anymore. */ @Retention(RetentionPolicy.CLASS) diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java Mon Mar 02 19:11:22 2015 +0100 @@ -37,7 +37,7 @@ * concrete type is found first when searching the list sequentially for the type of a given generic * value. *

    - * + * *

    * Each {@link #value()} is represented as a java type. A type can specify two annotations: * {@link TypeCheck} and {@link TypeCast}. The {@link TypeCheck} checks whether a given generic @@ -51,30 +51,30 @@ * accept also {@link Integer} values, implicitly converting them to {@link Double} . This example * points out how we express implicit type conversions. *

    - * + * *

    * Example: The {@link TypeSystem} contains the types {@link Boolean}, {@link Integer}, and * {@link Double}. The type {@link Object} is always used implicitly as the generic type represent * all values. - * + * *

    - * 
    + *
      * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
      * public abstract class ExampleTypeSystem {
    - * 
    + *
      *     {@literal @}TypeCheck
      *     public boolean isInteger(Object value) {
      *         return value instanceof Integer || value instanceof Double;
      *     }
    - * 
    + *
      *     {@literal @}TypeCast
      *     public double asInteger(Object value) {
      *         return ((Number)value).doubleValue();
      *     }
      * }
      * 
    - * - * + * + * * @see TypeCast * @see TypeCheck */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java Mon Mar 02 19:11:22 2015 +0100 @@ -31,7 +31,7 @@ /** * References a {@link TypeSystem} on a node. Must be applied on a {@link Node} class. At least one * {@link TypeSystem} must be referenced in a {@link Node}'s type hierarchy. - * + * * @see TypeSystem * @see Node */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,13 +30,13 @@ /** *

    Inserting Extra Nodes into the AST Transparently

    - * + * *

    * The {@link Node} class provides a callback that is invoked whenever a node is adopted in an AST * by insertion or replacement. Node classes can override the {@code onAdopt()} method to run extra * functionality upon adoption. *

    - * + * *

    * This test demonstrates how node instances of a specific class can be automatically wrapped in * extra nodes when they are inserted into the AST. diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,19 +34,19 @@ /** *

    Replacing Nodes at Run Time

    - * + * *

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

    - * + * *

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

    - * + * *

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

    diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Mon Mar 02 19:11:22 2015 +0100 @@ -439,7 +439,7 @@ } private abstract class TestLanguageNode extends Node { - public abstract Object execute(VirtualFrame frame); + public abstract Object execute(VirtualFrame vFrame); @Override public boolean isInstrumentable() { @@ -492,17 +492,17 @@ } @Override - public Object execute(VirtualFrame frame) { - probeNode.enter(child, frame); + public Object execute(VirtualFrame vFrame) { + probeNode.enter(child, vFrame); Object result; try { - result = child.execute(frame); - probeNode.returnValue(child, frame, result); + result = child.execute(vFrame); + probeNode.returnValue(child, vFrame, result); } catch (KillException e) { throw (e); } catch (Exception e) { - probeNode.returnExceptional(child, frame, e); + probeNode.returnExceptional(child, vFrame, e); throw (e); } @@ -521,7 +521,7 @@ } @Override - public Object execute(VirtualFrame frame) { + public Object execute(VirtualFrame vFrame) { return new Integer(this.value); } } @@ -539,8 +539,8 @@ } @Override - public Object execute(VirtualFrame frame) { - return new Integer(((Integer) leftChild.execute(frame)).intValue() + ((Integer) rightChild.execute(frame)).intValue()); + public Object execute(VirtualFrame vFrame) { + return new Integer(((Integer) leftChild.execute(vFrame)).intValue() + ((Integer) rightChild.execute(vFrame)).intValue()); } } @@ -563,8 +563,8 @@ } @Override - public Object execute(VirtualFrame frame) { - return body.execute(frame); + public Object execute(VirtualFrame vFrame) { + return body.execute(vFrame); } @Override @@ -591,12 +591,12 @@ instrument = Instrument.create(new SimpleEventListener() { @Override - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { enterCount++; } @Override - public void returnAny(Node node, VirtualFrame frame) { + public void returnAny(Node node, VirtualFrame vFrame) { leaveCount++; } }, "Instrumentation Test Counter"); @@ -695,7 +695,7 @@ probe.attach(Instrument.create(new SimpleEventListener() { @Override - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { count++; } }, "Instrumentation Test MultiCounter")); diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,7 +32,6 @@ * */ public class CompilerAsserts { - /** * Assertion that this code position should never be reached during compilation. It can be used * for exceptional code paths or rare code paths that should never be included in a compilation @@ -40,98 +39,38 @@ * directive. */ 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 - */ - public static boolean compilationConstant(boolean value) { - return value; + neverPartOfCompilation(""); } /** - * Assertion that the corresponding value is reduced to a constant during compilation. + * Assertion that this code position should never be reached during compilation. It can be used + * for exceptional code paths or rare code paths that should never be included in a compilation + * unit. See {@link CompilerDirectives#transferToInterpreter()} for the corresponding compiler + * directive. * - * @param value the value that must be constant during compilation - * @return the value given as parameter + * @param message text associated with the bailout exception */ - public static byte compilationConstant(byte value) { - return value; - } - - /** - * 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 - */ - public static char compilationConstant(char value) { - return value; + public static void neverPartOfCompilation(String message) { + CompilerDirectives.bailout(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 */ - public static short compilationConstant(short value) { - return value; - } - - /** - * 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 - */ - public static int compilationConstant(int value) { - return value; - } - - /** - * 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 - */ - public static long compilationConstant(long value) { - return value; + public static void compilationConstant(Object value) { + if (!CompilerDirectives.isCompilationConstant(value)) { + neverPartOfCompilation("Value is not compilation constant"); + } } /** - * 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 - */ - public static float compilationConstant(float value) { - return value; - } - - /** - * Assertion that the corresponding value is reduced to a constant during compilation. + * Assertion that the corresponding value is reduced to a constant during the initial partial + * evaluation phase. * * @param value the value that must be constant during compilation - * @return the value given as parameter */ - public static double compilationConstant(double value) { - return value; - } - - /** - * 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 - */ - public static Object compilationConstant(Object value) { - return value; + public static void partialEvaluationConstant(Object value) { } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Mon Mar 02 19:11:22 2015 +0100 @@ -80,33 +80,20 @@ /** * Returns a boolean indicating whether or not a given value is seen as constant in optimized * code. If this method is called in the interpreter this method will always return - * false. This API may be used in combination with {@link #inCompiledCode()} to - * implement compilation constant assertions in the following way: - * - *
    -     * 
    -     * void assertCompilationConstant(Object value) {
    -     *   if (inCompiledCode()) {
    -     *     if (!isCompilationConstant(value)) {
    -     *       throw new AssertionError("Given value is not constant");
    -     *     }
    -     *   }
    -     * }
    -     * 
    -     * 
    + * true. * * Note that optimizations that a compiler will apply to code that is conditional on * isCompilationConstant may be limited. For this reason * isCompilationConstant is not recommended for use to select between alternate * implementations of functionality depending on whether a value is constant. Instead, it is - * intended for use as a diagnostic mechanism, such as illustrated above. + * intended for use as a diagnostic mechanism. * * @param value * @return {@code true} when given value is seen as compilation constant, {@code false} if not * compilation constant. */ public static boolean isCompilationConstant(Object value) { - return false; + return CompilerDirectives.inInterpreter(); } /** diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,4 +33,10 @@ Float, Boolean, Byte; + + public final byte tag; + + private FrameSlotKind() { + this.tag = (byte) ordinal(); + } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,7 +28,7 @@ /** * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by * a guard or statically known). - * + * * @param frameSlot the slot of the variable * @throws IllegalStateException if the slot kind does not match * @see Frame#getObject(FrameSlot) @@ -44,7 +44,7 @@ /** * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by * a guard or statically known). - * + * * @param frameSlot the slot of the variable * @throws IllegalStateException if the slot kind does not match * @see Frame#getByte(FrameSlot) @@ -60,7 +60,7 @@ /** * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by * a guard or statically known). - * + * * @param frameSlot the slot of the variable * @throws IllegalStateException if the slot kind does not match * @see Frame#getBoolean(FrameSlot) @@ -76,7 +76,7 @@ /** * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by * a guard or statically known). - * + * * @param frameSlot the slot of the variable * @throws IllegalStateException if the slot kind does not match * @see Frame#getInt(FrameSlot) @@ -92,7 +92,7 @@ /** * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by * a guard or statically known). - * + * * @param frameSlot the slot of the variable * @throws IllegalStateException if the slot kind does not match * @see Frame#getLong(FrameSlot) @@ -108,7 +108,7 @@ /** * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by * a guard or statically known). - * + * * @param frameSlot the slot of the variable * @throws IllegalStateException if the slot kind does not match * @see Frame#getDouble(FrameSlot) @@ -124,7 +124,7 @@ /** * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by * a guard or statically known). - * + * * @param frameSlot the slot of the variable * @throws IllegalStateException if the slot kind does not match * @see Frame#getFloat(FrameSlot) diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,13 +24,15 @@ */ package com.oracle.truffle.api.instrument; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.impl.*; import com.oracle.truffle.api.nodes.*; // TODO (mlvdv) migrate some of this to external documentation. +// TODO (mlvdv) move all this to a factory implemented in .impl (together with Probe), +// then break out some of the nested classes into package privates. /** * A dynamically added/removed binding between a {@link Probe}, which provides notification of * {@linkplain TruffleEventListener execution events} taking place at a {@link Node} in a Guest @@ -44,8 +46,8 @@ *
  • Create an Instrument via factory method {@link Instrument#create(TruffleEventListener)}.
  • *
  • "Attach" the Instrument to a Probe via {@link Probe#attach(Instrument)}, at which point event * notifications begin to arrive at the listener.
  • - *
  • When no longer needed, "detach" the Instrument via {@link Instrument#dispose()}, at which - * point event notifications to the listener cease, and the Instrument becomes unusable.
  • + *
  • When no longer needed, "detach" the Instrument via {@link TruffleEventInstrument#dispose()}, + * at which point event notifications to the listener cease, and the Instrument becomes unusable.
  • * *

    *

    Options for creating listeners:

    @@ -123,8 +125,8 @@ * error to attempt attaching a previously attached instrument. *
  • Attaching an instrument modifies every existing clone of the AST to which it is being * attached, which can trigger deoptimization.
  • - *
  • The method {@link Instrument#dispose()} makes an instrument inactive by removing it from the - * Probe to which it was attached and rendering it permanently inert.
  • + *
  • The method {@link TruffleEventInstrument#dispose()} makes an instrument inactive by removing + * it from the Probe to which it was attached and rendering it permanently inert.
  • *
  • Disposal removes the implementation of an instrument from all ASTs to which it was attached, * which can trigger deoptimization.
  • * @@ -142,7 +144,7 @@ * @see Probe * @see TruffleEventListener */ -public final class Instrument { +public abstract class Instrument { /** * Creates an instrument that will route execution events to a listener. @@ -152,25 +154,23 @@ * @return a new instrument, ready for attachment at a probe */ public static Instrument create(TruffleEventListener listener, String instrumentInfo) { - return new Instrument(listener, instrumentInfo); + return new TruffleEventInstrument(listener, instrumentInfo); } /** * Creates an instrument that will route execution events to a listener. */ public static Instrument create(TruffleEventListener listener) { - return new Instrument(listener, null); + return new TruffleEventInstrument(listener, null); } + // TODO (mlvdv) experimental /** - * Tool-supplied listener for events. + * For implementation testing. */ - private final TruffleEventListener toolEventListener; - - /** - * Optional documentation, mainly for debugging. - */ - private final String instrumentInfo; + public static Instrument create(TruffleOptListener listener) { + return new TruffleOptInstrument(listener, null); + } /** * Has this instrument been disposed? stays true once set. @@ -179,8 +179,12 @@ private Probe probe = null; - private Instrument(TruffleEventListener listener, String instrumentInfo) { - this.toolEventListener = listener; + /** + * Optional documentation, mainly for debugging. + */ + private final String instrumentInfo; + + private Instrument(String instrumentInfo) { this.instrumentInfo = instrumentInfo; } @@ -216,35 +220,176 @@ return isDisposed; } - InstrumentNode addToChain(InstrumentNode nextNode) { - return new InstrumentNode(nextNode); - } + abstract InstrumentNode addToChain(InstrumentNode nextNode); /** * Removes this instrument from an instrument chain. */ - InstrumentNode removeFromChain(InstrumentNode instrumentNode) { - boolean found = false; - if (instrumentNode != null) { - if (instrumentNode.getInstrument() == this) { - // Found the match at the head of the chain - return instrumentNode.nextInstrument; + abstract InstrumentNode removeFromChain(InstrumentNode instrumentNode); + + private static final class TruffleEventInstrument extends Instrument { + + /** + * Tool-supplied listener for events. + */ + private final TruffleEventListener toolEventListener; + + private TruffleEventInstrument(TruffleEventListener listener, String instrumentInfo) { + super(instrumentInfo); + this.toolEventListener = listener; + } + + @Override + InstrumentNode addToChain(InstrumentNode nextNode) { + return new TruffleEventInstrumentNode(nextNode); + } + + @Override + InstrumentNode removeFromChain(InstrumentNode instrumentNode) { + boolean found = false; + if (instrumentNode != null) { + if (instrumentNode.getInstrument() == this) { + // Found the match at the head of the chain + return instrumentNode.nextInstrument; + } + // Match not at the head of the chain; remove it. + found = instrumentNode.removeFromChain(TruffleEventInstrument.this); + } + if (!found) { + throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + } + return instrumentNode; + } + + @NodeInfo(cost = NodeCost.NONE) + private final class TruffleEventInstrumentNode extends InstrumentNode { + + private TruffleEventInstrumentNode(InstrumentNode nextNode) { + super(nextNode); + } + + public void enter(Node node, VirtualFrame vFrame) { + TruffleEventInstrument.this.toolEventListener.enter(node, vFrame); + if (nextInstrument != null) { + nextInstrument.enter(node, vFrame); + } + } + + public void returnVoid(Node node, VirtualFrame vFrame) { + TruffleEventInstrument.this.toolEventListener.returnVoid(node, vFrame); + if (nextInstrument != null) { + nextInstrument.returnVoid(node, vFrame); + } + } + + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + TruffleEventInstrument.this.toolEventListener.returnValue(node, vFrame, result); + if (nextInstrument != null) { + nextInstrument.returnValue(node, vFrame, result); + } + } + + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + TruffleEventInstrument.this.toolEventListener.returnExceptional(node, vFrame, exception); + if (nextInstrument != null) { + nextInstrument.returnExceptional(node, vFrame, exception); + } + } + + public String instrumentationInfo() { + final String info = getInstrumentInfo(); + return info != null ? info : toolEventListener.getClass().getSimpleName(); } - // Match not at the head of the chain; remove it. - found = instrumentNode.removeFromChain(Instrument.this); + } + + } + + public interface TruffleOptListener { + void notifyIsCompiled(boolean isCompiled); + } + + private static final class TruffleOptInstrument extends Instrument { + + private final TruffleOptListener toolOptListener; + + private TruffleOptInstrument(TruffleOptListener listener, String instrumentInfo) { + super(instrumentInfo); + this.toolOptListener = listener; + } + + @Override + InstrumentNode addToChain(InstrumentNode nextNode) { + return new TruffleOptInstrumentNode(nextNode); + } + + @Override + InstrumentNode removeFromChain(InstrumentNode instrumentNode) { + boolean found = false; + if (instrumentNode != null) { + if (instrumentNode.getInstrument() == this) { + // Found the match at the head of the chain + return instrumentNode.nextInstrument; + } + // Match not at the head of the chain; remove it. + found = instrumentNode.removeFromChain(TruffleOptInstrument.this); + } + if (!found) { + throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + } + return instrumentNode; } - if (!found) { - throw new IllegalStateException("Couldn't find instrument node to remove: " + this); + + @NodeInfo(cost = NodeCost.NONE) + private final class TruffleOptInstrumentNode extends InstrumentNode { + + private boolean isCompiled; + + private TruffleOptInstrumentNode(InstrumentNode nextNode) { + super(nextNode); + this.isCompiled = CompilerDirectives.inCompiledCode(); + } + + public void enter(Node node, VirtualFrame vFrame) { + if (this.isCompiled != CompilerDirectives.inCompiledCode()) { + this.isCompiled = CompilerDirectives.inCompiledCode(); + TruffleOptInstrument.this.toolOptListener.notifyIsCompiled(this.isCompiled); + } + if (nextInstrument != null) { + nextInstrument.enter(node, vFrame); + } + } + + public void returnVoid(Node node, VirtualFrame vFrame) { + if (nextInstrument != null) { + nextInstrument.returnVoid(node, vFrame); + } + } + + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + if (nextInstrument != null) { + nextInstrument.returnValue(node, vFrame, result); + } + } + + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + if (nextInstrument != null) { + nextInstrument.returnExceptional(node, vFrame, exception); + } + } + + public String instrumentationInfo() { + final String info = getInstrumentInfo(); + return info != null ? info : toolOptListener.getClass().getSimpleName(); + } } - return instrumentNode; + } @NodeInfo(cost = NodeCost.NONE) - final class InstrumentNode extends Node implements TruffleEventListener, InstrumentationNode { + abstract class InstrumentNode extends Node implements TruffleEventListener, InstrumentationNode { + @Child protected InstrumentNode nextInstrument; - @Child private InstrumentNode nextInstrument; - - private InstrumentNode(InstrumentNode nextNode) { + protected InstrumentNode(InstrumentNode nextNode) { this.nextInstrument = nextNode; } @@ -286,40 +431,10 @@ return nextInstrument.removeFromChain(instrument); } - public void enter(Node node, VirtualFrame frame) { - Instrument.this.toolEventListener.enter(node, frame); - if (nextInstrument != null) { - nextInstrument.enter(node, frame); - } - } - - public void returnVoid(Node node, VirtualFrame frame) { - Instrument.this.toolEventListener.returnVoid(node, frame); - if (nextInstrument != null) { - nextInstrument.returnVoid(node, frame); - } + protected String getInstrumentInfo() { + return Instrument.this.instrumentInfo; } - public void returnValue(Node node, VirtualFrame frame, Object result) { - Instrument.this.toolEventListener.returnValue(node, frame, result); - if (nextInstrument != null) { - nextInstrument.returnValue(node, frame, result); - } - } - - public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { - Instrument.this.toolEventListener.returnExceptional(node, frame, exception); - if (nextInstrument != null) { - nextInstrument.returnExceptional(node, frame, exception); - } - } - - public String instrumentationInfo() { - if (Instrument.this.instrumentInfo != null) { - return Instrument.this.instrumentInfo; - } - return toolEventListener.getClass().getSimpleName(); - } } } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Mon Mar 02 19:11:22 2015 +0100 @@ -28,6 +28,7 @@ import java.util.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.utilities.*; @@ -80,6 +81,8 @@ */ private static final List> probes = new ArrayList<>(); + @CompilationFinal private static SyntaxTagTrap tagTrap = null; + private static final class FindSourceVisitor implements NodeVisitor { Source source = null; @@ -105,12 +108,6 @@ } /** - * The tag trap is a global setting; it only affects {@linkplain Probe probes} with the - * {@linkplain SyntaxTag tag} specified . - */ - private static SyntaxTagTrap globalTagTrap = null; - - /** * Enables instrumentation at selected nodes in all subsequently constructed ASTs. */ public static void registerASTProber(ASTProber prober) { @@ -156,8 +153,8 @@ } /** - * Returns all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole collection if - * the specified tag is {@code null}. + * Returns all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole collection of + * probes if the specified tag is {@code null}. * * @return A collection of probes containing the given tag. */ @@ -175,46 +172,22 @@ } /** - * Sets the current "tag trap". This causes a callback to be triggered whenever execution - * reaches a {@link Probe} (either existing or subsequently created) with the specified tag. - * There can only be one tag trap set at a time. + * Sets the current "tag trap"; there can be no more than one set at a time. + *
      + *
    • A non-null trap sets a callback to be triggered whenever execution reaches a + * {@link Probe} (either existing or subsequently created) with the specified tag.
    • + *
    • Setting the trap to null clears the existing trap.
    • + *
    • Setting a non-null trap when one is already set will clear the previously set trap.
    • + *
    * * @param newTagTrap The {@link SyntaxTagTrap} to set. - * @throws IllegalStateException if a trap is currently set. */ - public static void setTagTrap(SyntaxTagTrap newTagTrap) throws IllegalStateException { - assert newTagTrap != null; - if (globalTagTrap != null) { - throw new IllegalStateException("trap already set"); - } - globalTagTrap = newTagTrap; - - final SyntaxTag newTag = newTagTrap.getTag(); + public static void setTagTrap(SyntaxTagTrap newTagTrap) { + tagTrap = newTagTrap; for (WeakReference ref : probes) { final Probe probe = ref.get(); - if (probe != null && probe.tags.contains(newTag)) { - probe.trapActive = true; - probe.probeStateUnchanged.invalidate(); - } - } - } - - /** - * Clears the current {@link SyntaxTagTrap}. - * - * @throws IllegalStateException if no trap is currently set. - */ - public static void clearTagTrap() { - if (globalTagTrap == null) { - throw new IllegalStateException("no trap set"); - } - globalTagTrap = null; - - for (WeakReference ref : probes) { - final Probe probe = ref.get(); - if (probe != null && probe.trapActive) { - probe.trapActive = false; - probe.probeStateUnchanged.invalidate(); + if (probe != null) { + probe.notifyTrapSet(); } } } @@ -222,12 +195,21 @@ private final SourceSection sourceSection; private final ArrayList tags = new ArrayList<>(); private final List> probeNodeClones = new ArrayList<>(); - private final CyclicAssumption probeStateUnchanged = new CyclicAssumption("Probe state unchanged"); + + /* + * Invalidated whenever something changes in the Probe and its Instrument chain, so need deopt + */ + private final CyclicAssumption probeStateUnchangedCyclic = new CyclicAssumption("Probe state unchanged"); - /** - * {@code true} iff the global trap is set and this probe has the matching tag. + /* + * The assumption that nothing had changed in this probe, the last time anybody checked (when + * there may have been a deopt). Every time a check fails, gets replaced by a new unchanged + * assumption. */ - private boolean trapActive = false; + @CompilationFinal private Assumption probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption(); + + // Must invalidate whenever this changes. + @CompilationFinal private boolean isTrapActive = false; /** * Intended for use only by {@link ProbeNode}. @@ -261,10 +243,10 @@ for (ProbeListener listener : probeListeners) { listener.probeTaggedAs(this, tag, tagValue); } - if (globalTagTrap != null && tag == globalTagTrap.getTag()) { - this.trapActive = true; + if (tagTrap != null && tag == tagTrap.getTag()) { + this.isTrapActive = true; + invalidateProbeUnchanged(); } - probeStateUnchanged.invalidate(); } } @@ -288,7 +270,7 @@ probeNode.addInstrument(instrument); } } - probeStateUnchanged.invalidate(); + invalidateProbeUnchanged(); } /** @@ -305,29 +287,6 @@ } /** - * Receives notification that a new clone of the instrument chain associated with this - * {@link Probe} has been created as a side-effect of AST cloning. - */ - void registerProbeNodeClone(ProbeNode probeNode) { - probeNodeClones.add(new WeakReference<>(probeNode)); - } - - /** - * Gets the currently active {@linkplain SyntaxTagTrap tagTrap}; {@code null} if not set. - */ - SyntaxTagTrap getTrap() { - return trapActive ? globalTagTrap : null; - } - - /** - * Gets the {@link Assumption} that the instrumentation-related state of this {@link Probe} has - * not changed since this method was last called. - */ - Assumption getUnchangedAssumption() { - return probeStateUnchanged.getAssumption(); - } - - /** * Internal method for removing and rendering inert a specific instrument previously attached at * this Probe. * @@ -342,7 +301,46 @@ probeNode.removeInstrument(instrument); } } - probeStateUnchanged.invalidate(); + invalidateProbeUnchanged(); + } + + /** + * Receives notification that a new clone of the instrument chain associated with this + * {@link Probe} has been created as a side-effect of AST cloning. + */ + void registerProbeNodeClone(ProbeNode probeNode) { + probeNodeClones.add(new WeakReference<>(probeNode)); + } + + /** + * Gets the currently active {@linkplain SyntaxTagTrap tagTrap}; {@code null} if not set. + */ + SyntaxTagTrap getTrap() { + checkProbeUnchanged(); + return isTrapActive ? tagTrap : null; + } + + /** + * To be called wherever in the Probe/Instrument chain there are dependencies on the probe + * state's @CompilatonFinal fields. + */ + void checkProbeUnchanged() { + try { + probeStateUnchangedAssumption.check(); + } catch (InvalidAssumptionException ex) { + // Failure creates an implicit deoptimization + // Get the assumption associated with the new probe state + this.probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption(); + } + } + + private void invalidateProbeUnchanged() { + probeStateUnchangedCyclic.invalidate(); + } + + private void notifyTrapSet() { + this.isTrapActive = tagTrap != null && this.isTaggedAs(tagTrap.getTag()); + invalidateProbeUnchanged(); } private String getTagsDescription() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -24,7 +24,6 @@ */ package com.oracle.truffle.api.instrument; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; @@ -176,13 +175,6 @@ // Never changed once set. @CompilationFinal private Probe probe = null; - /** - * An assumption that the state of the {@link Probe} with which this chain is associated has - * not changed since the last time checking such an assumption failed and a reference to a - * new assumption (associated with a new state of the {@link Probe} was retrieved. - */ - private Assumption probeUnchangedAssumption; - private ProbeFullNode() { this.firstInstrument = null; } @@ -201,17 +193,6 @@ private void setProbe(Probe probe) { this.probe = probe; - this.probeUnchangedAssumption = probe.getUnchangedAssumption(); - } - - private void checkProbeUnchangedAssumption() { - try { - probeUnchangedAssumption.check(); - } catch (InvalidAssumptionException ex) { - // Failure creates an implicit deoptimization - // Get the assumption associated with the new probe state - this.probeUnchangedAssumption = probe.getUnchangedAssumption(); - } } @Override @@ -235,43 +216,41 @@ } } - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { + this.probe.checkProbeUnchanged(); final SyntaxTagTrap trap = probe.getTrap(); if (trap != null) { - checkProbeUnchangedAssumption(); - trap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), frame.materialize()); + trap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize()); } if (firstInstrument != null) { - checkProbeUnchangedAssumption(); - firstInstrument.enter(node, frame); + firstInstrument.enter(node, vFrame); } } - public void returnVoid(Node node, VirtualFrame frame) { + public void returnVoid(Node node, VirtualFrame vFrame) { + this.probe.checkProbeUnchanged(); if (firstInstrument != null) { - checkProbeUnchangedAssumption(); - firstInstrument.returnVoid(node, frame); + firstInstrument.returnVoid(node, vFrame); } } - public void returnValue(Node node, VirtualFrame frame, Object result) { + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + this.probe.checkProbeUnchanged(); if (firstInstrument != null) { - checkProbeUnchangedAssumption(); - firstInstrument.returnValue(node, frame, result); + firstInstrument.returnValue(node, vFrame, result); } } - public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + this.probe.checkProbeUnchanged(); if (firstInstrument != null) { - checkProbeUnchangedAssumption(); - firstInstrument.returnExceptional(node, frame, exception); + firstInstrument.returnExceptional(node, vFrame, exception); } } public String instrumentationInfo() { return "Standard probe"; } - } /** @@ -305,20 +284,20 @@ throw new IllegalStateException("Instruments may not be removed at a \"lite-probed\" location"); } - public void enter(Node node, VirtualFrame frame) { - eventListener.enter(node, frame); + public void enter(Node node, VirtualFrame vFrame) { + eventListener.enter(node, vFrame); } - public void returnVoid(Node node, VirtualFrame frame) { - eventListener.returnVoid(node, frame); + public void returnVoid(Node node, VirtualFrame vFrame) { + eventListener.returnVoid(node, vFrame); } - public void returnValue(Node node, VirtualFrame frame, Object result) { - eventListener.returnValue(node, frame, result); + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + eventListener.returnValue(node, vFrame, result); } - public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { - eventListener.returnExceptional(node, frame, exception); + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + eventListener.returnExceptional(node, vFrame, exception); } public String instrumentationInfo() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,7 +32,7 @@ * (for example for mostly expression-oriented languages) or even for specific languages. *

    * Disclaimer: experimental interface under development. - * + * * @see Probe */ public enum StandardSyntaxTag implements SyntaxTag { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventListener.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventListener.java Mon Mar 02 19:11:22 2015 +0100 @@ -36,22 +36,22 @@ /** * Receive notification that an AST node's execute method is about to be called. */ - void enter(Node node, VirtualFrame frame); + void enter(Node node, VirtualFrame vFrame); /** * Receive notification that an AST Node's {@code void}-valued execute method has just returned. */ - void returnVoid(Node node, VirtualFrame frame); + void returnVoid(Node node, VirtualFrame vFrame); /** * Receive notification that an AST Node'sexecute method has just returned a value (boxed if * primitive). */ - void returnValue(Node node, VirtualFrame frame, Object result); + void returnValue(Node node, VirtualFrame vFrame, Object result); /** * Receive notification that an AST Node's execute method has just thrown an exception. */ - void returnExceptional(Node node, VirtualFrame frame, Exception exception); + void returnExceptional(Node node, VirtualFrame vFrame, Exception exception); } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventListener.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventListener.java Mon Mar 02 19:11:22 2015 +0100 @@ -34,16 +34,16 @@ */ public class DefaultEventListener implements TruffleEventListener { - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { } - public void returnVoid(Node node, VirtualFrame frame) { + public void returnVoid(Node node, VirtualFrame vFrame) { } - public void returnValue(Node node, VirtualFrame frame, Object result) { + public void returnValue(Node node, VirtualFrame vFrame, Object result) { } - public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventListener.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventListener.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventListener.java Mon Mar 02 19:11:22 2015 +0100 @@ -38,7 +38,7 @@ */ public abstract class SimpleEventListener implements TruffleEventListener { - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { } /** @@ -46,21 +46,21 @@ * means: with or without a return value (ignored) or via exception (ignored). * * @param node - * @param frame + * @param vFrame */ - public void returnAny(Node node, VirtualFrame frame) { + public void returnAny(Node node, VirtualFrame vFrame) { } - public final void returnVoid(Node node, VirtualFrame frame) { - returnAny(node, frame); + public final void returnVoid(Node node, VirtualFrame vFrame) { + returnAny(node, vFrame); } - public final void returnValue(Node node, VirtualFrame frame, Object result) { - returnAny(node, frame); + public final void returnValue(Node node, VirtualFrame vFrame, Object result) { + returnAny(node, vFrame); } - public final void returnExceptional(Node node, VirtualFrame frame, Exception e) { - returnAny(node, frame); + public final void returnExceptional(Node node, VirtualFrame vFrame, Exception e) { + returnAny(node, vFrame); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java Mon Mar 02 19:11:22 2015 +0100 @@ -33,4 +33,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExplodeLoop { + boolean merge() default false; } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Mar 02 19:11:22 2015 +0100 @@ -41,7 +41,6 @@ public abstract class Node implements NodeInterface, Cloneable { @CompilationFinal private Node parent; - @CompilationFinal private SourceSection sourceSection; /** @@ -573,11 +572,7 @@ public final void atomic(Runnable closure) { RootNode rootNode = getRootNode(); - if (rootNode != null) { - synchronized (rootNode) { - closure.run(); - } - } else { + synchronized (rootNode != null ? rootNode : GIL) { closure.run(); } } @@ -585,14 +580,10 @@ public final T atomic(Callable closure) { try { RootNode rootNode = getRootNode(); - if (rootNode != null) { - synchronized (rootNode) { - return closure.call(); - } - } else { + synchronized (rootNode != null ? rootNode : GIL) { return closure.call(); } - } catch (RuntimeException e) { + } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { throw new RuntimeException(e); @@ -625,4 +616,6 @@ } return ""; } + + private static final Object GIL = new Object(); } diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Mar 02 19:11:22 2015 +0100 @@ -696,6 +696,42 @@ return false; } + /** + * Executes a closure for every non-null child of the parent node. + * + * @return {@code true} if all children were visited, {@code false} otherwise + */ + public static boolean forEachChild(Node parent, NodeVisitor visitor) { + Objects.requireNonNull(visitor); + NodeClass parentNodeClass = NodeClass.get(parent.getClass()); + + for (NodeField field : parentNodeClass.getChildFields()) { + Object child = field.getObject(parent); + if (child != null) { + if (!visitor.visit((Node) child)) { + return false; + } + } + } + + for (NodeField field : parentNodeClass.getChildrenFields()) { + Object arrayObject = field.getObject(parent); + if (arrayObject != null) { + Object[] array = (Object[]) arrayObject; + for (int i = 0; i < array.length; i++) { + Object child = array[i]; + if (child != null) { + if (!visitor.visit((Node) child)) { + return false; + } + } + } + } + } + + return true; + } + /** Returns all declared fields in the class hierarchy. */ private static Field[] getAllFields(Class clazz) { Field[] declaredFields = clazz.getDeclaredFields(); diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,7 +32,7 @@ /** * This visitor method is called for every node in the tree. Its return value determines if the * children of this node should be excluded in the iteration. - * + * * @param node the node that is currently visited * @return {@code true} if the children should be visited too, {@code false} otherwise */ diff -r 00d7b0adaf66 -r 96ab2078eeaf 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 Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -72,7 +72,7 @@ * language specific implementations may want to return true here to indicate that * gathering call site specific profiling information might make sense for this {@link RootNode} * . - * + * * @return true if cloning is allowed else false. */ public boolean isCloningAllowed() { @@ -91,7 +91,7 @@ /** * Executes this function using the specified frame and returns the result value. - * + * * @param frame the frame of the currently executing guest language method * @return the value of the execution */ @@ -114,14 +114,14 @@ * the correct ExecutionContext to be determined for a RootNode (and * so also for a {@link RootCallTarget} and a {@link FrameInstance} obtained from the call * stack) without prior knowledge of the language it has come from. - * + * * Used for instance to determine the language of a RootNode: - * + * *

          * 
          * rootNode.getExecutionContext().getLanguageShortName();
          *  
    - * + * * Returns null by default. */ public ExecutionContext getExecutionContext() { @@ -151,7 +151,7 @@ *

    * Implementations should ensure that instrumentation is never applied more than once to an AST, * as this is not guaranteed to be error-free. - * + * * @see Probe#registerASTProber(com.oracle.truffle.api.instrument.ASTProber) */ public void applyInstrumentation() { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Mon Mar 02 19:11:22 2015 +0100 @@ -39,7 +39,7 @@ /** * Creates the exception with the alternative result that cannot be represented as a value of * the return type. - * + * * @param result the alternative result */ public UnexpectedResultException(Object result) { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java Mon Mar 02 19:11:22 2015 +0100 @@ -39,7 +39,7 @@ * additional types that are necessary to serialize a truffle AST for a specific truffle * implementation. If a type is not supported by this constant pool implementation a * {@link UnsupportedConstantPoolTypeException} should be thrown. - * + * * @param clazz the {@link Class} of the value * @param value the value to be stored. Must be at least a subclass of the given clazz. * @return the constant pool index @@ -54,7 +54,7 @@ * are necessary to serialize a truffle AST for a specific truffle implementation. If a type is * not supported by this constant pool implementation a * {@link UnsupportedConstantPoolTypeException} should be thrown. - * + * * @param clazz the {@link Class} of the value in the constant pool. * @param cpi the previously returned index * @return the value stored inside the constant pool @@ -66,7 +66,7 @@ /** * Stores a Class instance in the constant pool and returns the constant pool index. - * + * * @param value the class to store * @return the new or existing constant pool index of the Class */ @@ -74,7 +74,7 @@ /** * Returns the {@link Class} instance to the given constant pool index. - * + * * @param cpi the constant pool index * @return stored value * @throws IllegalArgumentException if the constant pool indes is invalid. @@ -83,7 +83,7 @@ /** * Stores an int value in the constant pool and returns the constant pool index. - * + * * @param value the value to store * @return the new or existing constant pool index of the value */ @@ -91,7 +91,7 @@ /** * Returns the stored int value to the given constant pool index from the constant pool. - * + * * @param cpi the constant pool index * @return stored value * @throws IllegalArgumentException if the constant pool index is invalid. @@ -100,7 +100,7 @@ /** * Stores a long value in the constant pool and returns the constant pool index. - * + * * @param value the value to store * @return the new or existing constant pool index of the value */ @@ -108,7 +108,7 @@ /** * Returns the stored long value to the given constant pool index from the constant pool. - * + * * @param cpi the constant pool index * @return the stored value * @throws IllegalArgumentException if the constant pool index is invalid. @@ -117,7 +117,7 @@ /** * Stores a double value in the constant pool and returns the constant pool index. - * + * * @param value the value to store * @return the new or existing constant pool index of the value */ @@ -125,7 +125,7 @@ /** * Returns the stored double value to the given constant pool index from the constant pool. - * + * * @param cpi the constant pool index * @return the stored value * @throws IllegalArgumentException if the constant pool index is invalid. @@ -134,7 +134,7 @@ /** * Stores a float value in the constant pool and returns the constant pool index. - * + * * @param value the value to store * @return the new or existing constant pool index of the value */ @@ -142,7 +142,7 @@ /** * Returns the stored float value to the given constant pool index from the constant pool. - * + * * @param cpi the constant pool index * @return the stored value * @throws IllegalArgumentException if the constant pool index is invalid. diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Mon Mar 02 19:11:22 2015 +0100 @@ -27,13 +27,11 @@ import java.io.*; import java.util.*; import java.util.Map.Entry; -import java.util.concurrent.atomic.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.instrument.impl.*; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.source.*; /** @@ -160,7 +158,7 @@ curSource = source; curLineTable = new Long[source.getLineCount()]; } - curLineTable[lineNo - 1] = entry.getValue().count.longValue(); + curLineTable[lineNo - 1] = entry.getValue().count; } if (curSource != null) { result.put(curSource, curLineTable); @@ -206,7 +204,7 @@ while (curLineNo < lineNo) { displayLine(out, null, curSource, curLineNo++); } - displayLine(out, entry.getValue().count, curSource, curLineNo++); + displayLine(out, entry.getValue(), curSource, curLineNo++); } if (curSource != null) { while (curLineNo <= curSource.getLineCount()) { @@ -215,11 +213,11 @@ } } - private static void displayLine(PrintStream out, AtomicLong value, Source source, int lineNo) { - if (value == null) { + private static void displayLine(PrintStream out, CoverageRecord record, Source source, int lineNo) { + if (record == null) { out.format("%14s", " "); } else { - out.format("(%12d)", value.longValue()); + out.format("(%12d)", record.count); } out.format(" %3d: ", lineNo); out.println(source.getCode(lineNo)); @@ -227,33 +225,25 @@ /** * A listener for events at each instrumented AST location. This listener counts - * "execution calls" to the instrumented node and is stateful. State in listeners must - * be considered carefully since ASTs, along with all instrumentation (including event listener - * such as this) are routinely cloned by the Truffle runtime. AST cloning is shallow - * (for non- {@link Child} nodes), so in this case the actual count is shared among all - * the clones; the count is also held in a table indexed by source line. - *

    - * In contrast, a primitive field would not be shared among clones and resulting counts - * would not be accurate. + * "execution calls" to the instrumented node. */ - private final class CoverageEventListener extends DefaultEventListener { + private final class CoverageRecord extends DefaultEventListener { - /** - * Shared by all clones of the associated instrument and by the table of counters for the - * line. - */ - private final AtomicLong count; + private final SourceSection srcSection; // The text of the code being counted + private Instrument instrument; // The attached Instrument, in case need to remove. + private long count = 0; - CoverageEventListener(AtomicLong count) { - this.count = count; + CoverageRecord(SourceSection srcSection) { + this.srcSection = srcSection; } @Override - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { if (isEnabled()) { - count.getAndIncrement(); + count++; } } + } private static final class LineLocationEntryComparator implements Comparator> { @@ -282,35 +272,23 @@ if (record != null) { // Another node starts on same line; count only the first (textually) if (srcSection.getCharIndex() > record.srcSection.getCharIndex()) { - // Record already in place, corresponds to code earlier on line + // Existing record, corresponds to code earlier on line return; } else { - // Record already in place, corresponds to later code; replace it + // Existing record, corresponds to code at a later position; replace it record.instrument.dispose(); } } - final AtomicLong count = new AtomicLong(); - final CoverageEventListener eventListener = new CoverageEventListener(count); - final Instrument instrument = Instrument.create(eventListener, CoverageTracker.class.getSimpleName()); + + final CoverageRecord coverage = new CoverageRecord(srcSection); + final Instrument instrument = Instrument.create(coverage, CoverageTracker.class.getSimpleName()); + coverage.instrument = instrument; instruments.add(instrument); probe.attach(instrument); - coverageMap.put(lineLocation, new CoverageRecord(srcSection, instrument, count)); + coverageMap.put(lineLocation, coverage); } } } } - private class CoverageRecord { - - final SourceSection srcSection; // The text of the code being counted - final Instrument instrument; // The attached Instrument, in case need to remove. - final AtomicLong count; - - CoverageRecord(SourceSection srcSection, Instrument instrument, AtomicLong count) { - this.srcSection = srcSection; - this.instrument = instrument; - this.count = count; - } - } - } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/LineToProbesMap.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/LineToProbesMap.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/LineToProbesMap.java Mon Mar 02 19:11:22 2015 +0100 @@ -32,7 +32,7 @@ import com.oracle.truffle.api.source.*; /** - * An {@link InstrumentationTool} that builds a map of every {@Probe} attached to some AST, + * An {@link InstrumentationTool} that builds a map of every {@link Probe} attached to some AST, * indexed by {@link Source} and line number. */ public final class LineToProbesMap extends InstrumentationTool { diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java Mon Mar 02 19:11:22 2015 +0100 @@ -97,7 +97,7 @@ */ private final TruffleEventListener eventListener = new DefaultEventListener() { @Override - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { if (isEnabled()) { final Class nodeClass = node.getClass(); /* diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java Mon Mar 02 19:11:22 2015 +0100 @@ -30,24 +30,24 @@ /** * Abstract utility class to speculate on conditions. Condition profiles are intended to be used as * part of if conditions. - * + * * Example usage: - * + * *

      * private final ConditionProfile zero = ConditionProfile.createBinaryProfile();
    - * 
    + *
      * int value = ...;
      * if (zero.profile(value == 0)) {
      *   return 0;
      * } else {
      *   return value;
      * }
    - * 
    + *
      * 
    - * + * * All instances of {@code ConditionProfile} (and subclasses) must be held in {@code final} fields * for compiler optimizations to take effect. - * + * * @see #createCountingProfile() * @see #createBinaryProfile() */ @@ -62,7 +62,7 @@ * true and false. This information is reported to the underlying optimization system using * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are * intended to be used as part of if conditions. - * + * * @see ConditionProfile * @see #createBinaryProfile() */ @@ -73,7 +73,7 @@ /** * Returns a {@link ConditionProfile} that speculates on conditions to be never true or to be * never false. Condition profiles are intended to be used as part of if conditions. - * + * * @see ConditionProfile * @see ConditionProfile#createCountingProfile() */ diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java Mon Mar 02 19:11:22 2015 +0100 @@ -51,25 +51,26 @@ @SuppressWarnings("unchecked") @Override public Object profile(Object value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Byte && value instanceof Byte && (byte) cachedValue == (byte) value) { - return cachedValue; - } else if (cachedValue instanceof Short && value instanceof Short && (short) cachedValue == (short) value) { - return cachedValue; - } else if (cachedValue instanceof Integer && value instanceof Integer && (int) cachedValue == (int) value) { - return cachedValue; - } else if (cachedValue instanceof Long && value instanceof Long && (long) cachedValue == (long) value) { - return cachedValue; - } else if (cachedValue instanceof Float && value instanceof Float && exactCompare((float) cachedValue, (float) value)) { - return cachedValue; - } else if (cachedValue instanceof Double && value instanceof Double && exactCompare((double) cachedValue, (double) value)) { - return cachedValue; - } else if (cachedValue instanceof Boolean && value instanceof Boolean && (boolean) cachedValue == (boolean) value) { - return cachedValue; - } else if (cachedValue instanceof Character && value instanceof Character && (char) cachedValue == (char) value) { - return cachedValue; - } else if (cachedValue == value) { - return cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Byte && value instanceof Byte && (byte) snapshot == (byte) value) { + return snapshot; + } else if (snapshot instanceof Short && value instanceof Short && (short) snapshot == (short) value) { + return snapshot; + } else if (snapshot instanceof Integer && value instanceof Integer && (int) snapshot == (int) value) { + return snapshot; + } else if (snapshot instanceof Long && value instanceof Long && (long) snapshot == (long) value) { + return snapshot; + } else if (snapshot instanceof Float && value instanceof Float && exactCompare((float) snapshot, (float) value)) { + return snapshot; + } else if (snapshot instanceof Double && value instanceof Double && exactCompare((double) snapshot, (double) value)) { + return snapshot; + } else if (snapshot instanceof Boolean && value instanceof Boolean && (boolean) snapshot == (boolean) value) { + return snapshot; + } else if (snapshot instanceof Character && value instanceof Character && (char) snapshot == (char) value) { + return snapshot; + } else if (snapshot == value) { + return snapshot; } else { cacheMiss(value); } @@ -78,9 +79,10 @@ } public byte profile(byte value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Byte && (byte) cachedValue == value) { - return (byte) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Byte && (byte) snapshot == value) { + return (byte) snapshot; } else { cacheMiss(value); } @@ -89,9 +91,10 @@ } public short profile(short value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Short && (short) cachedValue == value) { - return (short) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Short && (short) snapshot == value) { + return (short) snapshot; } else { cacheMiss(value); } @@ -100,9 +103,10 @@ } public int profile(int value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Integer && (int) cachedValue == value) { - return (int) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Integer && (int) snapshot == value) { + return (int) snapshot; } else { cacheMiss(value); } @@ -111,9 +115,10 @@ } public long profile(long value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Long && (long) cachedValue == value) { - return (long) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Long && (long) snapshot == value) { + return (long) snapshot; } else { cacheMiss(value); } @@ -122,9 +127,10 @@ } public float profile(float value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Float && exactCompare((float) cachedValue, value)) { - return (float) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Float && exactCompare((float) snapshot, value)) { + return (float) snapshot; } else { cacheMiss(value); } @@ -133,9 +139,10 @@ } public double profile(double value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Double && exactCompare((double) cachedValue, value)) { - return (double) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Double && exactCompare((double) snapshot, value)) { + return (double) snapshot; } else { cacheMiss(value); } @@ -144,9 +151,10 @@ } public boolean profile(boolean value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Boolean && (boolean) cachedValue == value) { - return (boolean) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Boolean && (boolean) snapshot == value) { + return (boolean) snapshot; } else { cacheMiss(value); } @@ -155,9 +163,10 @@ } public char profile(char value) { - if (cachedValue != GENERIC) { - if (cachedValue instanceof Character && (char) cachedValue == value) { - return (char) cachedValue; + Object snapshot = this.cachedValue; + if (snapshot != GENERIC) { + if (snapshot instanceof Character && (char) snapshot == value) { + return (char) snapshot; } else { cacheMiss(value); } @@ -183,6 +192,7 @@ } private void cacheMiss(Object value) { + // TODO should we try to handle this more atomically? CompilerDirectives.transferToInterpreterAndInvalidate(); if (cachedValue == UNINITIALIZED) { cachedValue = value; @@ -208,17 +218,18 @@ } private String formatValue() { - if (cachedValue == null) { + Object snapshot = this.cachedValue; + if (snapshot == null) { return "null"; - } else if (cachedValue == UNINITIALIZED) { + } else if (snapshot == UNINITIALIZED) { return "uninitialized"; - } else if (cachedValue == GENERIC) { + } else if (snapshot == GENERIC) { return "generic"; - } else if (cachedValue instanceof Byte || cachedValue instanceof Short || cachedValue instanceof Integer || cachedValue instanceof Long || cachedValue instanceof Float || - cachedValue instanceof Double || cachedValue instanceof Boolean || cachedValue instanceof Character) { - return String.format("%s=%s", cachedValue.getClass().getSimpleName(), cachedValue); + } else if (snapshot instanceof Byte || snapshot instanceof Short || snapshot instanceof Integer || snapshot instanceof Long || snapshot instanceof Float || snapshot instanceof Double || + snapshot instanceof Boolean || snapshot instanceof Character) { + return String.format("%s=%s", snapshot.getClass().getSimpleName(), snapshot); } else { - return String.format("%s@%x", cachedValue.getClass().getSimpleName(), Objects.hash(cachedValue)); + return String.format("%s@%x", snapshot.getClass().getSimpleName(), Objects.hash(snapshot)); } } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java Mon Mar 02 19:11:22 2015 +0100 @@ -26,18 +26,18 @@ /** * Utility class to speculate on certain properties of values. - * + * * Example usage: - * + * *
      * private final ValueProfile classProfile = ValueProfile.createClassProfile();
    - * 
    + *
      * return classProfile.profile(value);
      * 
    - * + * * All instances of {@code ValueProfile} (and subclasses) must be held in {@code final} fields for * compiler optimizations to take effect. - * + * * @see #createPrimitiveProfile() * @see #createIdentityProfile() * @see #createClassProfile() diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java --- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Mon Mar 02 19:11:22 2015 +0100 @@ -275,8 +275,7 @@ */ @Override @TruffleBoundary - public final Property getProperty(Object key) { - // return this.propertyMap.get(propertyName); + public Property getProperty(Object key) { PropertyMap current = this.propertyMap; while (current.getLastProperty() != null) { if (current.getLastProperty().getKey().equals(key)) { @@ -284,7 +283,6 @@ } current = current.getParentMap(); } - return null; } @@ -355,9 +353,8 @@ */ private ShapeImpl addPropertyInternal(Property prop) { CompilerAsserts.neverPartOfCompilation(); - assert prop.isShadow() || !(this.hasProperty(prop.getKey())) : "duplicate property"; + assert prop.isShadow() || !(this.hasProperty(prop.getKey())) : "duplicate property " + prop.getKey(); assert !getPropertyListInternal(false).contains(prop); - // invalidatePropertyAssumption(prop.getName()); AddPropertyTransition addTransition = new AddPropertyTransition(prop); ShapeImpl cachedShape = queryTransition(addTransition); @@ -655,7 +652,7 @@ newShape = newShape.applyTransition(previous, true); } - getTransitionMapForWrite().put(transition, newShape); + addIndirectTransition(transition, newShape); return newShape; } else { return null; @@ -901,7 +898,7 @@ private Property[] createPropertiesArray() { propertyListAllocCount.inc(); Property[] propertiesArray = new Property[getPropertyCount()]; - List ownProperties = getPropertyList(ALL); + List ownProperties = getPropertyList(); assert ownProperties.size() == getPropertyCount(); for (int i = 0; i < getPropertyCount(); i++) { propertiesArray[i] = ownProperties.get(i); @@ -1101,7 +1098,7 @@ /** * Match all filter. */ - public static final Pred ALL = new Pred() { + private static final Pred ALL = new Pred() { public boolean test(Property t) { return true; } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -84,58 +84,58 @@ } @Override - public Object executeGeneric(VirtualFrame frame) { + public Object executeGeneric(VirtualFrame vFrame) { - probeNode.enter(child, frame); + probeNode.enter(child, vFrame); Object result; try { - result = child.executeGeneric(frame); - probeNode.returnValue(child, frame, result); + result = child.executeGeneric(vFrame); + probeNode.returnValue(child, vFrame, result); } catch (Exception e) { - probeNode.returnExceptional(child, frame, e); + probeNode.returnExceptional(child, vFrame, e); throw (e); } return result; } @Override - public long executeLong(VirtualFrame frame) throws UnexpectedResultException { - return SLTypesGen.expectLong(executeGeneric(frame)); + public long executeLong(VirtualFrame vFrame) throws UnexpectedResultException { + return SLTypesGen.expectLong(executeGeneric(vFrame)); } @Override - public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { - return SLTypesGen.expectBigInteger(executeGeneric(frame)); + public BigInteger executeBigInteger(VirtualFrame vFrame) throws UnexpectedResultException { + return SLTypesGen.expectBigInteger(executeGeneric(vFrame)); } @Override - public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { - return SLTypesGen.expectBoolean(executeGeneric(frame)); + public boolean executeBoolean(VirtualFrame vFrame) throws UnexpectedResultException { + return SLTypesGen.expectBoolean(executeGeneric(vFrame)); } @Override - public String executeString(VirtualFrame frame) throws UnexpectedResultException { - return SLTypesGen.expectString(executeGeneric(frame)); + public String executeString(VirtualFrame vFrame) throws UnexpectedResultException { + return SLTypesGen.expectString(executeGeneric(vFrame)); } @Override - public SLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException { - probeNode.enter(child, frame); + public SLFunction executeFunction(VirtualFrame vFrame) throws UnexpectedResultException { + probeNode.enter(child, vFrame); SLFunction result; try { - result = child.executeFunction(frame); - probeNode.returnValue(child, frame, result); + result = child.executeFunction(vFrame); + probeNode.returnValue(child, vFrame, result); } catch (Exception e) { - probeNode.returnExceptional(child, frame, e); + probeNode.returnExceptional(child, vFrame, e); throw (e); } return result; } @Override - public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { - return SLTypesGen.expectSLNull(executeGeneric(frame)); + public SLNull executeNull(VirtualFrame vFrame) throws UnexpectedResultException { + return SLTypesGen.expectSLNull(executeGeneric(vFrame)); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java Mon Mar 02 18:44:14 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java Mon Mar 02 19:11:22 2015 +0100 @@ -78,16 +78,16 @@ } @Override - public void executeVoid(VirtualFrame frame) { - probeNode.enter(child, frame); + public void executeVoid(VirtualFrame vFrame) { + probeNode.enter(child, vFrame); try { - child.executeVoid(frame); - probeNode.returnVoid(child, frame); + child.executeVoid(vFrame); + probeNode.returnVoid(child, vFrame); } catch (KillException e) { throw (e); } catch (Exception e) { - probeNode.returnExceptional(child, frame, e); + probeNode.returnExceptional(child, vFrame, e); throw (e); } } diff -r 00d7b0adaf66 -r 96ab2078eeaf hotspot/.cproject --- a/hotspot/.cproject Mon Mar 02 18:44:14 2015 +0100 +++ b/hotspot/.cproject Mon Mar 02 19:11:22 2015 +0100 @@ -45,7 +45,6 @@ -