# HG changeset patch # User Stefan Anzinger # Date 1424544933 -3600 # Node ID db19eba20b9c6b52c5d139d9467e6b4f37a78814 # Parent 82b5899f20cbfbff3bd5bcdd6194f5ac5732300f# Parent 34c0014aaf5bc73c2eb2c4e3610d6d7f34d78148 Merge diff -r 82b5899f20cb -r db19eba20b9c .hgtags --- a/.hgtags Sat Feb 21 19:47:33 2015 +0100 +++ b/.hgtags Sat Feb 21 19:55:33 2015 +0100 @@ -525,3 +525,4 @@ ae5b662550836e851c39e4fbb5c80517fc62488f graal-0.5 3b60f720b955c466d913abb0113af9b38962950b graal-0.6 1b0ef9634252c422b6f9839fc62eebc112545486 gpu-0.1 +9a12234da10cfa6934617274c203672389a1bbdd baseline-0.1 diff -r 82b5899f20cb -r db19eba20b9c CHANGELOG.md --- a/CHANGELOG.md Sat Feb 21 19:47:33 2015 +0100 +++ b/CHANGELOG.md Sat Feb 21 19:55:33 2015 +0100 @@ -7,6 +7,7 @@ ### Graal * Add utilities ModifiersProvider#isConcrete, ResolvedJavaMethod#hasBytecodes, ResolvedJavaMethod#hasReceiver to Graal API. * Add `GraalDirectives` API, containing methods to influence compiler behavior for unittests and microbenchmarks. +* Introduce `LIRSuites`, an extensible configuration for the low-level compiler pipeline. * ... ### Truffle @@ -18,12 +19,21 @@ * Instrumentation: A new example "instrumentation tool" is a language-agnostic collector of code coverage information (CoverageTracker); there are two other examples. ### Truffle-DSL -* All methods enclosed in a @TypeSystem must now be static. -* All methods enclosed in generated type system classes are static. -* Deprecated the public singleton used in the generated type system classes. -* NodeFactory implementations are no longer generated by default. Use {Node}Gen#create instead of {Node}Factory#create to create new instances of nodes. +* Implemented a new generated code layout that reduces the code size. +* Changed all methods enclosed in a @TypeSystem must now be static. +* Changed all methods enclosed in generated type system classes are now static. +* Deprecated the type system constant used in the generated type system classes. +* Changed NodeFactory implementations are no longer generated by default. Use {Node}Gen#create instead of {Node}Factory#create to create new instances of nodes. * Added @GenerateNodeFactory to generate NodeFactory implementations for this node and its subclasses. - +* Deprecated @NodeAssumptions for removal in the next release. +* Deprecated experimental @Implies for removal in the next release. +* Added new package c.o.t.api.dsl.examples to the c.o.t.api.dsl project containing documented and debug-able Truffle-DSL use cases. +* Changed "typed execute methods" are no longer required for use as specialization return type or parameter. It is now sufficient to declare them in the @TypeSystem. +* Added @Cached annotation to express specialization local state. +* Added Specialization#limit to declare a limit expression for the maximum number of specialization instantiations. +* Changed syntax and semantics of Specialization#assumptions and Specialization#guards. They now use a Java like expression syntax. +* Changed guard expressions that do not bind any dynamic parameter are invoked just once per specialization instantiation. They are now asserted to be true on the fast path. +* Renamed @ImportGuards to @ImportStatic. ## Version 0.6 19-Dec-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/shortlog/graal-0.6) diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.api.code; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.io.*; import java.lang.invoke.*; import java.util.*; @@ -31,20 +29,25 @@ import com.oracle.graal.api.meta.*; /** - * Class for recording optimistic assumptions made during compilation. + * Class for recording assumptions made during compilation. */ public final class Assumptions implements Serializable, Iterable { private static final long serialVersionUID = 5152062717588239131L; /** - * Abstract base class for assumptions. + * Abstract base class for assumptions. An assumption assumes a property of the runtime that may + * be invalidated by subsequent execution (e.g., that a class has no subclasses implementing + * {@link NoFinalizableSubclass Object.finalize()}). */ public abstract static class Assumption implements Serializable { private static final long serialVersionUID = -1936652569665112915L; } + /** + * An assumption that a given class has no subclasses implementing {@link Object#finalize()}). + */ public static final class NoFinalizableSubclass extends Assumption { private static final long serialVersionUID = 6451169735564055081L; @@ -77,7 +80,7 @@ } /** - * An assumption about a unique subtype of a given type. + * An assumption that a given type has a given unique subtype. */ public static final class ConcreteSubtype extends Assumption { @@ -125,7 +128,7 @@ } /** - * An assumption about a unique implementation of a virtual method. + * An assumption that a given virtual method has a given unique implementation. */ public static final class ConcreteMethod extends Assumption { @@ -174,45 +177,12 @@ @Override public String toString() { - return "ConcreteMethod[method=" + method.format("%H.%n(%p)") + ", context=" + context.toJavaName() + ", impl=" + impl.format("%H.%n(%p)") + "]"; + return "ConcreteMethod[method=" + method.format("%H.%n(%p)%r") + ", context=" + context.toJavaName() + ", impl=" + impl.format("%H.%n(%p)%r") + "]"; } } /** - * An assumption that specified that a method was used during the compilation. - */ - public static final class MethodContents extends Assumption { - - private static final long serialVersionUID = -4821594103928571659L; - - public final ResolvedJavaMethod method; - - public MethodContents(ResolvedJavaMethod method) { - this.method = method; - } - - @Override - public int hashCode() { - return 31 + method.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MethodContents) { - MethodContents other = (MethodContents) obj; - return other.method.equals(method); - } - return false; - } - - @Override - public String toString() { - return "MethodContents[method=" + method.format("%H.%n(%p)") + "]"; - } - } - - /** - * Assumption that a call site's method handle did not change. + * An assumption that a given call site's method handle did not change. */ public static final class CallSiteTargetValue extends Assumption { @@ -250,18 +220,7 @@ } } - /** - * Array with the assumptions. This field is directly accessed from C++ code in the - * Graal/HotSpot implementation. - */ - private Assumption[] list; - private boolean useOptimisticAssumptions; - private int count; - - public Assumptions(boolean useOptimisticAssumptions) { - this.useOptimisticAssumptions = useOptimisticAssumptions; - list = new Assumption[4]; - } + private final Set assumptions = new HashSet<>(); /** * Returns whether any assumptions have been registered. @@ -269,11 +228,7 @@ * @return {@code true} if at least one assumption has been registered, {@code false} otherwise. */ public boolean isEmpty() { - return count == 0; - } - - public boolean useOptimisticAssumptions() { - return useOptimisticAssumptions; + return assumptions.isEmpty(); } @Override @@ -282,25 +237,15 @@ } @Override - public String toString() { - return identityHashCodeString(this); - } - - @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof Assumptions) { Assumptions that = (Assumptions) obj; - if (useOptimisticAssumptions != that.useOptimisticAssumptions || count != that.count) { + if (!this.assumptions.equals(that.assumptions)) { return false; } - for (int i = 0; i < count; i++) { - if (!list[i].equals(that.list[i])) { - return false; - } - } return true; } return false; @@ -308,28 +253,7 @@ @Override public Iterator iterator() { - return new Iterator() { - - int index; - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - @Override - public Assumption next() { - if (index >= count) { - throw new NoSuchElementException(); - } - return list[index++]; - } - - @Override - public boolean hasNext() { - return index < count; - } - }; + return assumptions.iterator(); } /** @@ -338,7 +262,6 @@ * @param receiverType the type that is assumed to have no finalizable subclasses */ public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { - assert useOptimisticAssumptions; record(new NoFinalizableSubclass(receiverType)); } @@ -350,7 +273,6 @@ * @param subtype the one concrete subtype */ public void recordConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) { - assert useOptimisticAssumptions; record(new ConcreteSubtype(context, subtype)); } @@ -363,64 +285,30 @@ * @param impl the concrete method that is the only possible target for the virtual call */ public void recordConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) { - assert useOptimisticAssumptions; record(new ConcreteMethod(method, context, impl)); } - /** - * Records that {@code method} was used during the compilation. - * - * @param method a method whose contents were used - */ - public void recordMethodContents(ResolvedJavaMethod method) { - record(new MethodContents(method)); - } - public void record(Assumption assumption) { - if (list == null) { - list = new Assumption[4]; - } else { - for (int i = 0; i < count; ++i) { - if (assumption.equals(list[i])) { - return; - } - } - } - if (list.length == count) { - Assumption[] newList = new Assumption[list.length * 2]; - for (int i = 0; i < list.length; ++i) { - newList[i] = list[i]; - } - list = newList; - } - list[count] = assumption; - count++; + assumptions.add(assumption); } - public Assumption[] getAssumptions() { - return list; + /** + * Gets a copy of the assumptions recorded in this object as an array. + */ + public Assumption[] toArray() { + return assumptions.toArray(new Assumption[assumptions.size()]); } - public void record(Assumptions assumptions) { - for (int i = 0; i < assumptions.count; i++) { - record(assumptions.list[i]); - } + /** + * Copies assumptions recorded by another {@link Assumptions} object into this object. + */ + public void record(Assumptions other) { + assert other != this; + assumptions.addAll(other.assumptions); } - public void print(PrintStream out) { - List nonNullList = new ArrayList<>(); - if (list != null) { - for (int i = 0; i < list.length; ++i) { - Assumption a = list[i]; - if (a != null) { - nonNullList.add(a); - } - } - } - - out.printf("%d assumptions:%n", nonNullList.size()); - for (Assumption a : nonNullList) { - out.println(a.toString()); - } + @Override + public String toString() { + return "Assumptions[" + assumptions + "]"; } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,6 +28,7 @@ import java.io.*; import java.util.*; +import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; import com.oracle.graal.api.meta.*; @@ -528,7 +529,14 @@ private ArrayList annotations; - private Assumptions assumptions; + private Assumption[] assumptions; + + /** + * The list of the methods whose bytecodes were used as input to the compilation. If + * {@code null}, then the compilation did not record method dependencies. Otherwise, the first + * element of this array is the root method of the compilation. + */ + private ResolvedJavaMethod[] methods; public CompilationResult() { this(null); @@ -546,6 +554,9 @@ @Override public String toString() { + if (methods != null) { + return getClass().getName() + "[" + methods[0].format("%H.%n(%p)%r") + "]"; + } return identityHashCodeString(this); } @@ -564,12 +575,12 @@ this.targetCodeSize == that.targetCodeSize && Objects.equals(this.name, that.name) && Objects.equals(this.annotations, that.annotations) && - Objects.equals(this.assumptions, that.assumptions) && Objects.equals(this.dataSection, that.dataSection) && Objects.equals(this.exceptionHandlers, that.exceptionHandlers) && Objects.equals(this.dataPatches, that.dataPatches) && Objects.equals(this.infopoints, that.infopoints) && Objects.equals(this.marks, that.marks) && + Arrays.equals(this.assumptions, that.assumptions) && Arrays.equals(targetCode, that.targetCode)) { return true; } @@ -606,12 +617,62 @@ this.entryBCI = entryBCI; } - public void setAssumptions(Assumptions assumptions) { + /** + * Sets the assumptions made during compilation. + */ + public void setAssumptions(Assumption[] assumptions) { this.assumptions = assumptions; } - public Assumptions getAssumptions() { - return assumptions; + /** + * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the assumptions made during + * compilation. + */ + public Collection getAssumptions() { + return assumptions == null ? Collections.emptyList() : Arrays.asList(assumptions); + } + + /** + * Sets the methods whose bytecodes were used as input to the compilation. + * + * @param rootMethod the root method of the compilation + * @param inlinedMethods the methods inlined during compilation + */ + public void setMethods(ResolvedJavaMethod rootMethod, Collection inlinedMethods) { + assert rootMethod != null; + assert inlinedMethods != null; + if (inlinedMethods.contains(rootMethod)) { + methods = inlinedMethods.toArray(new ResolvedJavaMethod[inlinedMethods.size()]); + for (int i = 0; i < methods.length; i++) { + if (methods[i].equals(rootMethod)) { + if (i != 0) { + ResolvedJavaMethod tmp = methods[0]; + methods[0] = methods[i]; + methods[i] = tmp; + } + break; + } + } + } else { + methods = new ResolvedJavaMethod[1 + inlinedMethods.size()]; + methods[0] = rootMethod; + int i = 1; + for (ResolvedJavaMethod m : inlinedMethods) { + methods[i++] = m; + } + } + } + + /** + * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the methods whose bytecodes + * were used as input to the compilation. + * + * @return {@code null} if the compilation did not record method dependencies otherwise the + * methods whose bytecodes were used as input to the compilation with the first element + * being the root method of the compilation + */ + public Collection getMethods() { + return methods == null ? null : Arrays.asList(methods); } public DataSection getDataSection() { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ForeignCallLinkage.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/MemoryBarriers.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterAttributes.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Sat Feb 21 19:55:33 2015 +0100
@@ -29,7 +29,7 @@
 
 /**
  * Manages a list of unique deoptimization reasons.
- * 
+ *
  */
 public abstract class SpeculationLog {
     private volatile Object lastFailed;
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Sat Feb 21 19:55:33 2015 +0100
@@ -97,7 +97,7 @@
         } else {
             ResolvedJavaType uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                if (assumptions.useOptimisticAssumptions()) {
+                if (assumptions != null) {
                     assumptions.recordConcreteSubtype(targetType, uniqueSubtype);
                     exact = uniqueSubtype;
                 } else {
diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ControlFlowAnchorDirectiveTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -106,7 +106,7 @@
 
     @Test
     public void testDuplicate() {
-        test("verifyDuplicateSnippet", 42);
+        // test("verifyDuplicateSnippet", 42);
         test("preventDuplicateSnippet", 42);
     }
 
diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/IterationDirectiveTest.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/OpaqueDirectiveTest.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ProbabilityDirectiveTest.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExceptionHandler.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Sat Feb 21 19:47:33 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,803 +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.baseline;
-
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.alloc.*;
-import com.oracle.graal.compiler.common.calc.*;
-import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.java.*;
-import com.oracle.graal.java.BciBlockMapping.BciBlock;
-import com.oracle.graal.java.BciBlockMapping.LocalLiveness;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.lir.alloc.lsra.*;
-import com.oracle.graal.lir.framemap.*;
-import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.lir.stackslotalloc.*;
-import com.oracle.graal.phases.*;
-
-public class BaselineBytecodeParser extends AbstractBytecodeParser implements BytecodeParserTool {
-    private Backend backend;
-    protected LIRGeneratorTool gen;
-    private LIRGenerationResult lirGenRes;
-    private BytecodeLIRBuilder lirBuilder;
-    @SuppressWarnings("unused") private BciBlock[] loopHeaders;
-    private LocalLiveness liveness;
-    private BciBlockBitMap blockVisited;
-
-    private static class BciBlockBitMap {
-        BitSet bitSet;
-
-        public BciBlockBitMap(BciBlockMapping blockMap) {
-            bitSet = new BitSet(blockMap.getBlocks().length);
-        }
-
-        public boolean get(BciBlock block) {
-            return bitSet.get(block.getId());
-        }
-
-        public void set(BciBlock block) {
-            bitSet.set(block.getId());
-        }
-    }
-
-    public BaselineBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts,
-                    BaselineFrameStateBuilder frameState, Backend backend) {
-
-        super(metaAccess, method, graphBuilderConfig, optimisticOpts);
-        this.backend = backend;
-        this.setCurrentFrameState(frameState);
-    }
-
-    public LIRGenerationResult getLIRGenerationResult() {
-        return lirGenRes;
-    }
-
-    protected void build() {
-        if (PrintProfilingInformation.getValue()) {
-            TTY.println("Profiling info for " + method.format("%H.%n(%p)"));
-            TTY.println(MetaUtil.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), "  "));
-        }
-
-        try (Indent indent = Debug.logAndIndent("build graph for %s", method)) {
-
-            BciBlockMapping blockMap;
-            try (Scope ds = Debug.scope("BciBlockMapping")) {
-                // compute the block map, setup exception handlers and get the entrypoint(s)
-                blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis(), false);
-            } catch (Throwable e) {
-                throw Debug.handle(e);
-            }
-
-            loopHeaders = blockMap.getLoopHeaders();
-            liveness = blockMap.liveness;
-            blockVisited = new BciBlockBitMap(blockMap);
-
-            if (method.isSynchronized()) {
-                throw GraalInternalError.unimplemented("Handle synchronized methods");
-            }
-
-            frameState = new BaselineFrameStateBuilder(method);
-            frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true);
-
-            currentBlock = blockMap.startBlock;
-            blockMap.startBlock.setEntryState(0, frameState);
-            if (blockMap.startBlock.isLoopHeader) {
-                throw GraalInternalError.unimplemented("Handle start block as loop header");
-            }
-
-            // add loops ? how do we add looks when we haven't parsed the bytecode?
-
-            // create the control flow graph
-            BaselineControlFlowGraph cfg = BaselineControlFlowGraph.compute(blockMap);
-
-            // create the LIR
-            List> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blockMap.getBlocks().length, blockMap.startBlock);
-            List> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blockMap.getBlocks().length, blockMap.startBlock);
-            LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder);
-
-            RegisterConfig registerConfig = null;
-            FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig);
-            TargetDescription target = backend.getTarget();
-            CallingConvention cc = CodeUtil.getCallingConvention(backend.getProviders().getCodeCache(), CallingConvention.Type.JavaCallee, method, false);
-            this.lirGenRes = backend.newLIRGenerationResult(lir, frameMapBuilder, method, null);
-            this.gen = backend.newLIRGenerator(cc, lirGenRes);
-            this.lirBuilder = backend.newBytecodeLIRBuilder(gen, this);
-
-            try (Scope ds = Debug.scope("BackEnd", lir)) {
-                try (Scope s = Debug.scope("LIRGen", gen)) {
-
-                    // possibly add all the arguments to slots in the local variable array
-
-                    for (BciBlock block : blockMap.getBlocks()) {
-                        emitBlock(block);
-                    }
-
-                    gen.beforeRegisterAllocation();
-                    Debug.dump(lir, "After LIR generation");
-                } catch (Throwable e) {
-                    throw Debug.handle(e);
-                }
-
-                try (Scope s = Debug.scope("Allocator")) {
-                    if (backend.shouldAllocateRegisters()) {
-                        LinearScan.allocate(target, lirGenRes);
-                    }
-                }
-                try (Scope s1 = Debug.scope("BuildFrameMap")) {
-                    // build frame map
-                    lirGenRes.buildFrameMap(new SimpleStackSlotAllocator());
-                    Debug.dump(lir, "After FrameMap building");
-                }
-                try (Scope s1 = Debug.scope("MarkLocations")) {
-                    if (backend.shouldAllocateRegisters()) {
-                        // currently we mark locations only if we do register allocation
-                        LocationMarker.markLocations(lir, lirGenRes.getFrameMap());
-                    }
-                }
-
-            } catch (Throwable e) {
-                throw Debug.handle(e);
-            }
-        } catch (Throwable e) {
-            throw Debug.handle(e);
-        }
-    }
-
-    private void emitBlock(BciBlock b) {
-        if (lirGenRes.getLIR().getLIRforBlock(b) == null) {
-            for (BciBlock pred : b.getPredecessors()) {
-                if (!b.isLoopHeader() || !pred.isLoopEnd()) {
-                    emitBlock(pred);
-                }
-            }
-            processBlock(b);
-        }
-    }
-
-    @Override
-    protected void handleUnresolvedLoadConstant(JavaType type) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedCheckCast(JavaType type, Value object) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedInstanceOf(JavaType type, Value object) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedNewInstance(JavaType type) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedNewObjectArray(JavaType type, Value length) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedNewMultiArray(JavaType type, List dims) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedLoadField(JavaField field, Value receiver) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedStoreField(JavaField field, Value value, Value receiver) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void handleUnresolvedExceptionType(JavaType type) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genLoadIndexed(Value index, Value array, Kind kind) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genStoreIndexed(Value array, Value index, Kind kind, Value value) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genIntegerAdd(Kind kind, Value x, Value y) {
-        return gen.emitAdd(x, y, false);
-    }
-
-    @Override
-    protected Value genIntegerSub(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genIntegerMul(Kind kind, Value x, Value y) {
-        return gen.emitMul(x, y, false);
-    }
-
-    @Override
-    protected Value genFloatAdd(Kind kind, Value x, Value y, boolean isStrictFP) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genFloatSub(Kind kind, Value x, Value y, boolean isStrictFP) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genFloatMul(Kind kind, Value x, Value y, boolean isStrictFP) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genFloatDiv(Kind kind, Value x, Value y, boolean isStrictFP) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genFloatRem(Kind kind, Value x, Value y, boolean isStrictFP) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genIntegerDiv(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genIntegerRem(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genNegateOp(Value x) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genLeftShift(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genRightShift(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genUnsignedRightShift(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genAnd(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genOr(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genXor(Kind kind, Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genNormalizeCompare(Value x, Value y, boolean isUnorderedLess) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genFloatConvert(FloatConvert op, Value input) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genNarrow(Value input, int bitCount) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genSignExtend(Value input, int bitCount) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genZeroExtend(Value input, int bitCount) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genObjectEquals(Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genIntegerEquals(Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genIf(Value x, Condition cond, Value y) {
-        assert currentBlock.getSuccessors().size() == 2;
-        BciBlock trueBlock = currentBlock.getSuccessors().get(0);
-        BciBlock falseBlock = currentBlock.getSuccessors().get(1);
-        if (trueBlock == falseBlock) {
-            genGoto();
-            return;
-        }
-
-        double probability = branchProbability();
-
-        LabelRef trueDestination = getSuccessor(0);
-        LabelRef falseDestination = getSuccessor(1);
-
-        gen.emitCompareBranch(x.getKind(), x, y, cond, false, trueDestination, falseDestination, probability);
-    }
-
-    @Override
-    protected Value genIntegerLessThan(Value x, Value y) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genUnique(Value x) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genThrow() {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value createCheckCast(ResolvedJavaType type, Value object, JavaTypeProfile profileForTypeCheck, boolean b) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value createInstanceOf(ResolvedJavaType type, Value object, JavaTypeProfile profileForTypeCheck) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genConditional(Value x) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value createNewInstance(ResolvedJavaType type, boolean fillContents) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value createNewArray(ResolvedJavaType elementType, Value length, boolean fillContents) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value createNewMultiArray(ResolvedJavaType type, List dims) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genLoadField(Value receiver, ResolvedJavaField field) {
-        if (field.isStatic()) {
-            Value classRef = lirBuilder.getClassConstant(field.getDeclaringClass());
-            long displacement = lirBuilder.getFieldOffset(field);
-            Value address = gen.emitAddress(classRef, displacement, Value.ILLEGAL, 0);
-            LIRKind readKind = backend.getTarget().getLIRKind(field.getKind());
-            LIRFrameState state = createFrameState(frameState);
-            return gen.emitLoad(readKind, address, state);
-        }
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void emitNullCheck(Value receiver) {
-        gen.emitNullCheck(receiver, createFrameState(frameState));
-    }
-
-    @Override
-    protected void emitBoundsCheck(Value index, Value length) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genArrayLength(Value array) {
-        emitNullCheck(array);
-        long displacement = lirBuilder.getArrayLengthOffset();
-        Value address = gen.emitAddress(array, displacement, Value.ILLEGAL, 0);
-        LIRKind readKind = backend.getTarget().getLIRKind(Kind.Int);
-        LIRFrameState state = createFrameState(frameState);
-        return gen.emitLoad(readKind, address, state);
-    }
-
-    private LIRFrameState createFrameState(BaselineFrameStateBuilder state) {
-        LabelRef exceptionEdge = null;
-        BytecodeFrame caller = null;
-        boolean duringCall = false;
-        int numLocals = state.localsSize();
-        int numStack = state.stackSize();
-        int numLocks = state.lockDepth();
-        JavaValue[] values = new JavaValue[numLocals + numStack + numLocks];
-
-        for (int i = 0; i < numLocals; i++) {
-            values[i] = (JavaValue) state.localAt(i);
-        }
-
-        for (int i = 0; i < numStack; i++) {
-            values[numLocals + i] = (JavaValue) state.stackAt(i);
-        }
-
-        for (int i = 0; i < numStack; i++) {
-            values[numLocals + numStack + i] = (JavaValue) state.lockAt(i);
-        }
-
-        BytecodeFrame frame = new BytecodeFrame(caller, method, bci(), state.rethrowException(), duringCall, values, numLocals, numStack, numLocks);
-        return new LIRFrameState(frame, null, exceptionEdge);
-    }
-
-    @Override
-    protected Value genStoreField(Value receiver, ResolvedJavaField field, Value value) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genInvokeStatic(JavaMethod target) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genInvokeInterface(JavaMethod target) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genInvokeDynamic(JavaMethod target) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genInvokeVirtual(JavaMethod target) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genInvokeSpecial(JavaMethod target) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genReturn(Value x) {
-        gen.emitReturn(x);
-    }
-
-    @Override
-    protected Value genMonitorEnter(Value x) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value genMonitorExit(Value x, Value returnValue) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genJsr(int dest) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genRet(int localIndex) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected void genIntegerSwitch(Value value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
-        // TODO Auto-generated method stub
-        throw GraalInternalError.unimplemented("Auto-generated method stub");
-    }
-
-    @Override
-    protected Value appendConstant(JavaConstant constant) {
-        return gen.emitLoadConstant(constant.getLIRKind(), constant);
-    }
-
-    @Override
-    protected Value append(Value v) {
-        return v;
-    }
-
-    private void createTarget(BciBlock block) {
-        assert block != null && frameState != null;
-        assert !block.isExceptionEntry || frameState.stackSize() == 1;
-
-        if (!blockVisited.get(block)) {
-            /*
-             * 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.
-             */
-            blockVisited.set(block);
-            if (block.getPredecessorCount() > 1) {
-                /*
-                 * If there are more than one predecessors we have to ensure that we are not passing
-                 * constants to the new framestate otherwise we will get interfacing problems.
-                 */
-                moveConstantsToVariables();
-            }
-            block.setEntryState(0, frameState.copy());
-            block.getEntryState(0).clearNonLiveLocals(block, liveness, true);
-
-            Debug.log("createTarget %s: first visit", block);
-            return;
-        }
-
-        // We already saw this block before, so we have to merge states.
-        if (!((BaselineFrameStateBuilder) block.getEntryState(0)).isCompatibleWith(frameState)) {
-            throw new BailoutException("stacks do not match; bytecodes would not verify");
-        }
-
-        if (block.isLoopHeader) {
-            assert currentBlock == null || currentBlock.getId() >= block.getId() : "must be backward branch";
-            if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) {
-                // this is the only successor of the current block so we can adjust
-                adaptFramestate((BaselineFrameStateBuilder) block.getEntryState(0));
-                return;
-            }
-            GraalInternalError.unimplemented("Loops not yet supported");
-        }
-        assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
-
-        /*
-         * 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.
-         */
-        if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) {
-            // this is the only successor of the current block so we can adjust
-            adaptFramestate((BaselineFrameStateBuilder) block.getEntryState(0));
-            return;
-        }
-        GraalInternalError.unimplemented("second block visit not yet implemented");
-
-        // merge frame states e.g. block.entryState.merge(mergeNode, target.state);
-
-        Debug.log("createTarget %s: merging state", block);
-    }
-
-    private void moveConstantsToVariables() {
-        Debug.log("moveConstantsToVariables: framestate before: %s", frameState);
-        for (int i = 0; i < frameState.stackSize(); i++) {
-            Value src = frameState.stackAt(i);
-            if (src instanceof JavaConstant) {
-                AllocatableValue dst = gen.newVariable(src.getLIRKind());
-                gen.emitMove(dst, src);
-                frameState.storeStack(i, dst);
-                Debug.log("introduce new variabe %s for stackslot %d (end of block %s", dst, i, currentBlock);
-            }
-        }
-        for (int i = 0; i < frameState.localsSize(); i++) {
-            Value src = frameState.localAt(i);
-            if (src instanceof JavaConstant) {
-                AllocatableValue dst = gen.newVariable(src.getLIRKind());
-                gen.emitMove(dst, src);
-                frameState.storeLocal(i, dst);
-                Debug.log("introduce new variabe %s for local %d (end of block %s", dst, i, currentBlock);
-            }
-        }
-        Debug.log("moveConstantsToVariables: framestate after: %s", frameState);
-    }
-
-    private static void adaptValues(Value dst, Value src, PhiResolver resolver) {
-        if (dst == null) {
-            return;
-        }
-        assert src != null : "Source is null but Destination is not!";
-
-        if (!dst.equals(src)) {
-            resolver.move(dst, src);
-        }
-    }
-
-    private void adaptFramestate(BaselineFrameStateBuilder other) {
-        assert frameState.isCompatibleWith(other) : "framestates not compatible!";
-        PhiResolver resolver = new PhiResolver(gen);
-        for (int i = 0; i < frameState.stackSize(); i++) {
-            Value src = frameState.stackAt(i);
-            Value dst = other.stackAt(i);
-            adaptValues(dst, src, resolver);
-        }
-        for (int i = 0; i < frameState.localsSize(); i++) {
-            Value src = frameState.localAt(i);
-            Value dst = other.localAt(i);
-            adaptValues(dst, src, resolver);
-        }
-        resolver.dispose();
-    }
-
-    protected void processBlock(BciBlock block) {
-        frameState = (BaselineFrameStateBuilder) block.getEntryState(0);
-        setCurrentFrameState(frameState);
-        currentBlock = block;
-        iterateBytecodesForBlock(block);
-    }
-
-    private boolean isBlockEnd() {
-        List l = gen.getResult().getLIR().getLIRforBlock(currentBlock);
-        if (l.isEmpty()) {
-            return false;
-        }
-        return l.get(l.size() - 1) instanceof BlockEndOp;
-    }
-
-    @Override
-    protected void iterateBytecodesForBlock(BciBlock block) {
-        gen.doBlockStart(block);
-
-        if (block == gen.getResult().getLIR().getControlFlowGraph().getStartBlock()) {
-            assert block.getPredecessorCount() == 0;
-            lirBuilder.emitPrologue(method);
-        } else {
-            assert block.getPredecessorCount() > 0;
-        }
-
-        if (block.isLoopHeader) {
-            /*
-             * 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(0, frameState.copy());
-
-        }
-        int endBCI = stream.endBCI();
-
-        stream.setBCI(block.startBci);
-        int bci = block.startBci;
-        BytecodesParsed.add(block.endBci - bci);
-
-        while (bci < endBCI) {
-
-            // read the opcode
-            int opcode = stream.currentBC();
-            // traceState();
-            traceInstruction(bci, opcode, bci == block.startBci);
-
-            processBytecode(bci, opcode);
-
-            stream.next();
-            bci = stream.currentBCI();
-
-            if (isBlockEnd()) {
-                break;
-            }
-
-            if (bci < endBCI) {
-                if (bci > block.endBci) {
-                    if (block.numNormalSuccessors() == 1) {
-                        assert !block.getSuccessor(0).isExceptionEntry;
-                        // we fell through to the next block, add a goto and break
-                        genGoto();
-                    }
-                    break;
-                }
-            }
-        }
-
-        assert LIR.verifyBlock(gen.getResult().getLIR(), block);
-        gen.doBlockEnd(block);
-    }
-
-    public void storeLocal(int i, Value x) {
-        frameState.storeLocal(i, x);
-    }
-
-    LabelRef getSuccessor(int index) {
-        createTarget(currentBlock.getSuccessor(index));
-        return LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, index);
-    }
-
-    @Override
-    protected void genGoto() {
-        gen.emitJump(getSuccessor(0));
-    }
-
-}
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java	Sat Feb 21 19:47:33 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.baseline;
-
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.bytecode.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.java.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.*;
-
-/**
- * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
- */
-@SuppressWarnings("all")
-public class BaselineCompiler {
-
-    public BaselineCompiler(GraphBuilderConfiguration graphBuilderConfig, MetaAccessProvider metaAccess) {
-        this.graphBuilderConfig = graphBuilderConfig;
-        this.metaAccess = metaAccess;
-    }
-
-    private final MetaAccessProvider metaAccess;
-
-    private final GraphBuilderConfiguration graphBuilderConfig;
-
-    public CompilationResult generate(ResolvedJavaMethod method, int entryBCI, Backend backend, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner,
-                    CompilationResultBuilderFactory factory, OptimisticOptimizations optimisticOpts, Replacements replacements) {
-        assert method.getCode() != null : "method must contain bytecodes: " + method;
-        TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method);
-
-        BaselineFrameStateBuilder frameState = new BaselineFrameStateBuilder(method);
-
-        BaselineBytecodeParser parser = new BaselineBytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, frameState, backend);
-
-        // build blocks and LIR instructions
-        try {
-            parser.build();
-        } finally {
-            filter.remove();
-        }
-
-        // emitCode
-        Assumptions assumptions = new Assumptions(OptAssumptions.getValue());
-        GraalCompiler.emitCode(backend, assumptions, parser.getLIRGenerationResult(), compilationResult, installedCodeOwner, factory);
-
-        return compilationResult;
-    }
-}
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java	Sat Feb 21 19:47:33 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +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.baseline;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.java.*;
-import com.oracle.graal.java.BciBlockMapping.BciBlock;
-
-public final class BaselineControlFlowGraph implements AbstractControlFlowGraph {
-
-    private BciBlock[] blocks;
-    private Collection> loops;
-
-    public static BaselineControlFlowGraph compute(BciBlockMapping blockMap) {
-        try (Scope ds = Debug.scope("BaselineCFG", blockMap)) {
-            BaselineControlFlowGraph cfg = new BaselineControlFlowGraph(blockMap);
-            cfg.computePredecessors();
-            cfg.computeLoopInformation(blockMap);
-            AbstractControlFlowGraph.computeDominators(cfg);
-
-            assert CFGVerifier.verify(cfg);
-
-            return cfg;
-        } catch (Throwable e) {
-            throw Debug.handle(e);
-        }
-    }
-
-    private BaselineControlFlowGraph(BciBlockMapping blockMap) {
-        blocks = blockMap.getBlocks();
-        loops = new ArrayList<>();
-    }
-
-    public List getBlocks() {
-        return Arrays.asList(blocks);
-    }
-
-    public Collection> getLoops() {
-        return loops;
-    }
-
-    public BciBlock getStartBlock() {
-        if (blocks.length > 0) {
-            return blocks[0];
-        }
-        return null;
-    }
-
-    /**
-     * Create and populate the predecessor list.
-     */
-    private void computePredecessors() {
-        // set predecessors
-        for (BciBlock block : blocks) {
-            block.setPredecessors(new ArrayList<>(4));
-        }
-        // calculate predecessors
-        for (BciBlock block : blocks) {
-            for (BciBlock succ : block.getSuccessors()) {
-                succ.getPredecessors().add(block);
-            }
-        }
-    }
-
-    private void computeLoopInformation(BciBlockMapping blockMap) {
-        try (Indent indent = Debug.logAndIndent("computeLoopInformation")) {
-            for (BciBlock block : blocks) {
-                calcLoop(block, blockMap);
-                Debug.log("Block: %s, Loop: %s", block, block.getLoop());
-            }
-        }
-    }
-
-    private Loop getLoop(int index, BciBlockMapping blockMap) {
-        BciBlock header = blockMap.getLoopHeader(index);
-        assert header.getLoopDepth() > 0;
-        Loop loop = header.getLoop();
-
-        if (loop == null) {
-            Loop parent = null;
-
-            if (header.getLoopDepth() > 1) {
-                // Recursively create out loops.
-                Iterator i = header.loopIdIterable().iterator();
-                assert i.hasNext() : "BciBlock.loopIdIterable() must return exactly BciBlock.getLoopDepth() elements!";
-                int outerLoopId = i.next();
-                assert index == outerLoopId : "The first loopId must be the id of the loop that is started by this header!";
-                assert i.hasNext() : "BciBlock.loopIdIterable() must return exactly BciBlock.getLoopDepth() elements!";
-                outerLoopId = i.next();
-                parent = getLoop(outerLoopId, blockMap);
-            }
-
-            loop = new BaselineLoop(parent, index, header);
-            loops.add(loop);
-            header.setLoop(loop);
-        }
-        return loop;
-    }
-
-    private void calcLoop(BciBlock block, BciBlockMapping blockMap) {
-        int loopId = block.getLoopId();
-        if (loopId != -1) {
-            block.setLoop(getLoop(loopId, blockMap));
-
-        }
-    }
-
-}
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineFrameStateBuilder.java
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineFrameStateBuilder.java	Sat Feb 21 19:47:33 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +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.baseline;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.java.*;
-
-public class BaselineFrameStateBuilder extends AbstractFrameStateBuilder {
-
-    private static final Value[] EMPTY_ARRAY = new Value[0];
-
-    public BaselineFrameStateBuilder(ResolvedJavaMethod method) {
-        // we always need at least one stack slot (for exceptions)
-        super(method);
-    }
-
-    protected BaselineFrameStateBuilder(BaselineFrameStateBuilder other) {
-        super(other);
-    }
-
-    @Override
-    protected Value[] allocateArray(int length) {
-        return length == 0 ? EMPTY_ARRAY : new Value[length];
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("[locals: [");
-        for (int i = 0; i < locals.length; i++) {
-            sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString());
-        }
-        sb.append("] stack: [");
-        for (int i = 0; i < stackSize; i++) {
-            sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString());
-        }
-        sb.append("] locks: [");
-        for (int i = 0; i < lockedObjects.length; i++) {
-            sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString());
-        }
-        sb.append("]");
-        if (rethrowException) {
-            sb.append(" rethrowException");
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-
-    @Override
-    public BaselineFrameStateBuilder copy() {
-        return new BaselineFrameStateBuilder(this);
-    }
-
-    private static boolean isCompatible(Value x, Value y) {
-        if (x == null && y == null) {
-            return true;
-        }
-        if ((x == null || y == null) || (x.getKind() != y.getKind())) {
-            return false;
-        }
-        return true;
-
-    }
-
-    @Override
-    public boolean isCompatibleWith(BaselineFrameStateBuilder other) {
-        assert method.equals(other.method) && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
-
-        if (stackSize() != other.stackSize()) {
-            return false;
-        }
-        for (int i = 0; i < stackSize(); i++) {
-            if (!isCompatible(stackAt(i), other.stackAt(i))) {
-                return false;
-            }
-        }
-        if (lockedObjects.length != other.lockedObjects.length) {
-            return false;
-        }
-        return true;
-    }
-}
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineLoop.java
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineLoop.java	Sat Feb 21 19:47:33 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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.baseline;
-
-import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.java.BciBlockMapping.BciBlock;
-
-public class BaselineLoop extends Loop {
-
-    protected BaselineLoop(Loop parent, int index, BciBlock header) {
-        super(parent, index, header);
-    }
-
-    @Override
-    public long numBackedges() {
-        // currently only loops with one backedge are supported
-        return 1;
-    }
-
-}
diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeLookupSwitch.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeSwitch.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeTableSwitch.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytes.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Sat Feb 21 19:55:33 2015 +0100
@@ -30,9 +30,6 @@
 // @formatter:off
 public final class GraalOptions {
 
-    @Option(help = "Use experimental baseline compiler configuration.", type = OptionType.Debug)
-    public static final OptionValue UseBaselineCompiler = new OptionValue<>(false);
-
     @Option(help = "Use compiler intrinsifications.", type = OptionType.Debug)
     public static final OptionValue Intrinsify = new OptionValue<>(true);
 
@@ -63,6 +60,9 @@
     @Option(help = "Inlines trivial methods during parsing of the bytecodes.", type = OptionType.Expert)
     public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(false);
 
+    @Option(help = "Traces .", type = OptionType.Debug)
+    public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false);
+
     @Option(help = "Maximum depth when inlining during parsing.", type = OptionType.Debug)
     public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10);
 
@@ -119,23 +119,11 @@
     public static final OptionValue LoopUnswitch = new OptionValue<>(true);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue FullUnrollMaxNodes = new OptionValue<>(300);
-
-    @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue ExactFullUnrollMaxNodes = new OptionValue<>(1200);
-
-    @Option(help = "", type = OptionType.Expert)
     public static final OptionValue MinimumPeelProbability = new OptionValue<>(0.35f);
 
     @Option(help = "", type = OptionType.Expert)
     public static final OptionValue LoopMaxUnswitch = new OptionValue<>(3);
 
-    @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue LoopUnswitchMaxIncrease = new OptionValue<>(50);
-
-    @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue LoopUnswitchUncertaintyBoost = new OptionValue<>(5);
-
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue UseLoopLimitChecks = new OptionValue<>(true);
 
@@ -319,7 +307,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);
@@ -346,6 +334,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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java	Sat Feb 21 19:55:33 2015 +0100
@@ -94,7 +94,7 @@
         throw GraalInternalError.shouldNotReachHere("can't read values of illegal stamp");
     }
 
-    private static IllegalStamp instance = new IllegalStamp();
+    private static final IllegalStamp instance = new IllegalStamp();
 
     static IllegalStamp getInstance() {
         return instance;
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java	Sat Feb 21 19:55:33 2015 +0100
@@ -112,7 +112,7 @@
         throw GraalInternalError.shouldNotReachHere("void stamp has no value");
     }
 
-    private static VoidStamp instance = new VoidStamp();
+    private static final VoidStamp instance = new VoidStamp();
 
     static VoidStamp getInstance() {
         return instance;
diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/ArrayMap.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/IntList.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -24,9 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.common.inlining.*;
@@ -300,14 +300,13 @@
 
     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) {
-        graph = parseEager(snippet);
-        Assumptions assumptions = new Assumptions(false);
-        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        graph = parseEager(snippet, AllowAssumptions.NO);
+        HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
     }
@@ -317,10 +316,8 @@
     }
 
     private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) {
-        graph = parseEager(snippet);
-
-        Assumptions assumptions = new Assumptions(false);
-        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        graph = parseEager(snippet, AllowAssumptions.NO);
+        HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
         canonicalizer.apply(graph, context);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
@@ -334,7 +331,7 @@
         new DeadCodeEliminationPhase().apply(graph);
         canonicalizer.apply(graph, context);
 
-        StructuredGraph referenceGraph = parseEager(referenceSnippet);
+        StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES);
         new InliningPhase(new CanonicalizerPhase(true)).apply(referenceGraph, context);
         new DeadCodeEliminationPhase().apply(referenceGraph);
         new CanonicalizerPhase(true).apply(referenceGraph, context);
diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java	Sat Feb 21 19:55:33 2015 +0100
@@ -44,6 +44,7 @@
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
+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.*;
@@ -69,7 +70,7 @@
 
         PhaseSuite graphBuilderSuite = new PhaseSuite<>();
         graphBuilderSuite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getEagerDefault()));
-        HighTierContext context = new HighTierContext(providers, new Assumptions(false), null, graphBuilderSuite, OptimisticOptimizations.NONE);
+        HighTierContext context = new HighTierContext(providers, null, graphBuilderSuite, OptimisticOptimizations.NONE);
 
         Assume.assumeTrue(VerifyPhase.class.desiredAssertionStatus());
 
@@ -138,7 +139,7 @@
                         if (matches(filters, methodName)) {
                             executor.execute(() -> {
                                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
-                                StructuredGraph graph = new StructuredGraph(method);
+                                StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO);
                                 try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) {
                                     graphBuilderSuite.apply(graph, context);
                                     // update phi stamps
diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -26,8 +26,8 @@
 
 import org.junit.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -35,8 +35,8 @@
 public class CompareCanonicalizerTest extends GraalCompilerTest {
 
     private StructuredGraph getCanonicalizedGraph(String name) {
-        StructuredGraph graph = parseEager(name);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
+        StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
         return graph;
     }
 
@@ -48,13 +48,12 @@
 
     @Test
     public void testCanonicalComparison() {
-        StructuredGraph referenceGraph = parseEager("referenceCanonicalComparison");
+        StructuredGraph referenceGraph = parseEager("referenceCanonicalComparison", AllowAssumptions.NO);
         for (int i = 1; i < 4; i++) {
-            StructuredGraph graph = parseEager("canonicalCompare" + i);
+            StructuredGraph graph = parseEager("canonicalCompare" + i, AllowAssumptions.NO);
             assertEquals(referenceGraph, graph);
         }
-        Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), assumptions));
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders()));
         for (int i = 1; i < 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
@@ -132,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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -25,6 +25,7 @@
 import org.junit.*;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -90,9 +91,9 @@
 
     @Test
     public void testRedundantCompares() {
-        StructuredGraph graph = parseEager("testRedundantComparesSnippet");
+        StructuredGraph graph = parseEager("testRedundantComparesSnippet", AllowAssumptions.YES);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        PhaseContext context = new PhaseContext(getProviders(), null);
+        PhaseContext context = new PhaseContext(getProviders());
 
         new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         canonicalizer.apply(graph, context);
@@ -113,10 +114,10 @@
     @Test
     @Ignore
     public void testInstanceOfCheckCastLowered() {
-        StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet");
+        StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", AllowAssumptions.YES);
 
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        PhaseContext context = new PhaseContext(getProviders(), null);
+        PhaseContext context = new PhaseContext(getProviders());
 
         new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         canonicalizer.apply(graph, context);
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -24,10 +24,10 @@
 
 import org.junit.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.common.inlining.*;
@@ -81,12 +81,12 @@
 
     private void test(final String snippet) {
         try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) {
-            StructuredGraph graph = parseEager(snippet);
-            HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+            StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
+            HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
             new CanonicalizerPhase(true).apply(graph, context);
             Debug.dump(graph, "Graph");
-            StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET);
+            StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
             Debug.dump(referenceGraph, "ReferenceGraph");
             assertEquals(referenceGraph, graph);
         } catch (Throwable e) {
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -24,10 +24,10 @@
 
 import org.junit.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -106,11 +106,11 @@
     }
 
     private StructuredGraph compileSnippet(final String snippet, final int checkcasts, final int afterCanon) {
-        final StructuredGraph graph = parseEager(snippet);
+        final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
         try (Scope s = Debug.scope("NestedCheckCastsTest", graph)) {
             Debug.dump(graph, "After parsing: " + snippet);
             Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count());
-            new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false)));
+            new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
             Assert.assertEquals(afterCanon, graph.getNodes().filter(CheckCastNode.class).count());
             return graph;
         } catch (Throwable e) {
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -35,6 +35,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -60,28 +61,30 @@
         }
     }
 
-    private StructuredGraph parseAndProcess(Class cl, Assumptions assumptions) {
+    private StructuredGraph parseAndProcess(Class cl, AllowAssumptions allowAssumptions) {
         Constructor[] constructors = cl.getConstructors();
         Assert.assertTrue(constructors.length == 1);
         final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
+        StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions);
 
         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
-        new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), assumptions, getProviders().getConstantReflection(), conf, OptimisticOptimizations.ALL).apply(graph);
-        HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), conf, OptimisticOptimizations.ALL).apply(graph);
+        HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
         new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         return graph;
     }
 
-    private void checkForRegisterFinalizeNode(Class cl, boolean shouldContainFinalizer, boolean optimistic) {
-        Assumptions assumptions = new Assumptions(optimistic);
-        StructuredGraph graph = parseAndProcess(cl, assumptions);
+    private void checkForRegisterFinalizeNode(Class cl, boolean shouldContainFinalizer, AllowAssumptions allowAssumptions) {
+        StructuredGraph graph = parseAndProcess(cl, allowAssumptions);
         Assert.assertTrue(graph.getNodes().filter(RegisterFinalizerNode.class).count() == (shouldContainFinalizer ? 1 : 0));
         int noFinalizerAssumption = 0;
-        for (Assumption a : assumptions) {
-            if (a instanceof NoFinalizableSubclass) {
-                noFinalizerAssumption++;
+        Assumptions assumptions = graph.getAssumptions();
+        if (assumptions != null) {
+            for (Assumption a : assumptions) {
+                if (a instanceof NoFinalizableSubclass) {
+                    noFinalizerAssumption++;
+                }
             }
         }
         Assert.assertTrue(noFinalizerAssumption == (shouldContainFinalizer ? 0 : 1));
@@ -95,13 +98,13 @@
     public void test1() throws ClassNotFoundException {
         for (int i = 0; i < 2; i++) {
             ClassTemplateLoader loader = new ClassTemplateLoader();
-            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, false);
-            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, true);
+            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, AllowAssumptions.NO);
+            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, AllowAssumptions.YES);
 
-            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), false, true);
+            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), false, AllowAssumptions.YES);
 
-            checkForRegisterFinalizeNode(loader.findClass("WithFinalizerAAAA"), true, true);
-            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), true, true);
+            checkForRegisterFinalizeNode(loader.findClass("WithFinalizerAAAA"), true, AllowAssumptions.YES);
+            checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), true, AllowAssumptions.YES);
         }
     }
 
diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -24,11 +24,11 @@
 
 import org.junit.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.common.*;
@@ -58,8 +58,8 @@
     private void test(final String snippet) {
         try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) {
 
-            StructuredGraph graph = parseEager(snippet);
-            PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false));
+            StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
+            PhaseContext context = new PhaseContext(getProviders());
             new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
             new FloatingReadPhase().apply(graph);
 
diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sat Feb 21 19:55:33 2015 +0100
@@ -40,7 +40,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.baseline.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.GraalCompiler.Request;
 import com.oracle.graal.compiler.common.*;
@@ -50,11 +49,14 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.phases.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
@@ -69,7 +71,7 @@
  * 

* White box tests for Graal compiler transformations use this pattern: *

    - *
  1. Create a graph by {@linkplain #parseEager(String) parsing} a method.
  2. + *
  3. Create a graph by {@linkplain #parseEager(String, AllowAssumptions) parsing} a method.
  4. *
  5. Manually modify the graph (e.g. replace a parameter node with a constant).
  6. *
  7. Apply a transformation to the graph.
  8. *
  9. Assert that the transformed graph is equal to an expected graph.
  10. @@ -87,7 +89,8 @@ private final Providers providers; private final Backend backend; - private final Suites suites; + private final DerivedOptionValue suites; + private final DerivedOptionValue lirSuites; /** * Can be overridden by unit tests to verify properties of the graph. @@ -163,10 +166,16 @@ return ret; } + protected LIRSuites createLIRSuites() { + LIRSuites ret = backend.getSuites().createLIRSuites(); + return ret; + } + public GraalCompilerTest() { this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); this.providers = getBackend().getProviders(); - this.suites = createSuites(); + this.suites = new DerivedOptionValue<>(this::createSuites); + this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); installSubstitutions(); } @@ -186,7 +195,8 @@ this.backend = runtime.getHostBackend(); } this.providers = backend.getProviders(); - this.suites = createSuites(); + this.suites = new DerivedOptionValue<>(this::createSuites); + this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); installSubstitutions(); } @@ -284,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); @@ -351,7 +361,11 @@ } protected Suites getSuites() { - return suites; + return suites.getValue(); + } + + protected LIRSuites getLIRSuites() { + return lirSuites.getValue(); } protected Providers getProviders() { @@ -467,12 +481,7 @@ checkArgs(method, executeArgs); - InstalledCode compiledMethod = null; - if (UseBaselineCompiler.getValue()) { - compiledMethod = getCodeBaseline(method); - } else { - compiledMethod = getCode(method); - } + InstalledCode compiledMethod = getCode(method); try { return new Result(compiledMethod.executeVarargs(executeArgs), null); } catch (Throwable e) { @@ -482,73 +491,6 @@ } } - protected InstalledCode getCodeBaseline(ResolvedJavaMethod javaMethod) { - return getCodeBaseline(javaMethod, false); - } - - protected InstalledCode getCodeBaseline(ResolvedJavaMethod javaMethod, boolean forceCompile) { - assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod; - - try (Scope bds = Debug.scope("Baseline")) { - Debug.log("getCodeBaseline()"); - } catch (Throwable e) { - throw Debug.handle(e); - } - - if (!forceCompile) { - InstalledCode cached = cache.get(javaMethod); - if (cached != null) { - if (cached.isValid()) { - return cached; - } - } - } - - final int id = compilationId.incrementAndGet(); - - InstalledCode installedCode = null; - try (Scope ds = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) { - final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); - - if (printCompilation) { - TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s ...", id, javaMethod.getDeclaringClass().getName(), javaMethod.getName(), javaMethod.getSignature())); - } - long start = System.currentTimeMillis(); - - CompilationResult compResult = compileBaseline(javaMethod); - - if (printCompilation) { - TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); - } - - try (Scope s = Debug.scope("CodeInstall", getCodeCache(), javaMethod)) { - installedCode = addMethod(javaMethod, compResult); - if (installedCode == null) { - throw new GraalInternalError("Could not install code for " + javaMethod.format("%H.%n(%p)")); - } - } catch (Throwable e) { - throw Debug.handle(e); - } - } catch (Throwable e) { - throw Debug.handle(e); - } - - if (!forceCompile) { - cache.put(javaMethod, installedCode); - } - return installedCode; - } - - private CompilationResult compileBaseline(ResolvedJavaMethod javaMethod) { - try (Scope bds = Debug.scope("CompileBaseline", javaMethod, providers.getCodeCache())) { - BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess()); - OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; - return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default, optimisticOpts, getReplacements()); - } catch (Throwable e) { - throw Debug.handle(e); - } - } - protected void checkArgs(ResolvedJavaMethod method, Object[] args) { JavaType[] sig = method.toParameterTypes(); Assert.assertEquals(sig.length, args.length); @@ -647,7 +589,7 @@ /** * Gets installed code for a given method, compiling it first if necessary. The graph is parsed - * {@link #parseEager(ResolvedJavaMethod) eagerly}. + * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions) eagerly}. */ protected InstalledCode getCode(ResolvedJavaMethod method) { return getCode(method, null); @@ -721,10 +663,10 @@ * is null. * * The default implementation in {@link GraalCompilerTest} is to call - * {@link #parseEager(ResolvedJavaMethod)}. + * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions)}. */ protected StructuredGraph parseForCompile(ResolvedJavaMethod method) { - return parseEager(method); + return parseEager(method, AllowAssumptions.YES); } /** @@ -740,7 +682,8 @@ lastCompiledGraph = graphToCompile; CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graphToCompile.method(), false); Request request = new Request<>(graphToCompile, cc, installedCodeOwner, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), - OptimisticOptimizations.ALL, getProfilingInfo(graphToCompile), getSpeculationLog(), getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + OptimisticOptimizations.ALL, getProfilingInfo(graphToCompile), getSpeculationLog(), getSuites(), getLIRSuites(), new CompilationResult(), + CompilationResultBuilderFactory.Default); return GraalCompiler.compile(request); } @@ -800,16 +743,16 @@ * * @param methodName the name of the method in {@code this.getClass()} to be parsed */ - protected StructuredGraph parseProfiled(String methodName) { - return parseProfiled(getResolvedJavaMethod(methodName)); + protected StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { + return parseProfiled(getResolvedJavaMethod(methodName), allowAssumptions); } /** * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault() default} mode to * produce a graph. */ - protected StructuredGraph parseProfiled(ResolvedJavaMethod m) { - return parse1(m, getDefaultGraphBuilderSuite()); + protected StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + return parse1(m, getDefaultGraphBuilderSuite(), allowAssumptions); } /** @@ -818,31 +761,31 @@ * * @param methodName the name of the method in {@code this.getClass()} to be parsed */ - protected StructuredGraph parseEager(String methodName) { - return parseEager(getResolvedJavaMethod(methodName)); + protected StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions) { + return parseEager(getResolvedJavaMethod(methodName), allowAssumptions); } /** * Parses a Java method in {@linkplain GraphBuilderConfiguration#getEagerDefault() eager} mode * to produce a graph. */ - protected StructuredGraph parseEager(ResolvedJavaMethod m) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerDefault())); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerDefault()), allowAssumptions); } /** * Parses a Java method in {@linkplain GraphBuilderConfiguration#getFullDebugDefault() full * debug} mode to produce a graph. */ - protected StructuredGraph parseDebug(ResolvedJavaMethod m) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault())); + protected StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()), allowAssumptions); } - private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite) { + private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite, AllowAssumptions allowAssumptions) { assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod; try (Scope ds = Debug.scope("Parsing", javaMethod)) { - StructuredGraph graph = new StructuredGraph(javaMethod); - graphBuilderSuite.apply(graph, new HighTierContext(providers, null, null, graphBuilderSuite, OptimisticOptimizations.ALL)); + StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions); + graphBuilderSuite.apply(graph, new HighTierContext(providers, null, graphBuilderSuite, OptimisticOptimizations.ALL)); return graph; } catch (Throwable e) { throw Debug.handle(e); @@ -858,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,10 +26,10 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -180,11 +180,11 @@ } private void testCombinedIf(String snippet, int count) { - StructuredGraph graph = parseEager(snippet); - PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + PhaseContext context = new PhaseContext(getProviders()); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); - MidTierContext midContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); + MidTierContext midContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new ValueAnchorCleanupPhase().apply(graph); @@ -193,19 +193,19 @@ } private void test(String snippet) { - StructuredGraph graph = parseEager(snippet); - ParameterNode param = graph.getNodes(ParameterNode.class).iterator().next(); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + 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); } Debug.dump(graph, "Graph"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) { fs.replaceFirstInput(param, null); param.safeDelete(); } - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static org.junit.Assert.*; import org.junit.*; @@ -36,6 +37,7 @@ import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -58,10 +60,10 @@ @Test public void callInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseEager(method); + final StructuredGraph graph = parseEager(method, AllowAssumptions.YES); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), - OptimisticOptimizations.ALL, getProfilingInfo(graph), null, getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + OptimisticOptimizations.ALL, getProfilingInfo(graph), null, getSuites(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); if (sp instanceof Call) { @@ -73,7 +75,7 @@ @Test public void lineInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseDebug(method); + final StructuredGraph graph = parseDebug(method, AllowAssumptions.from(OptAssumptions.getValue())); int graphLineSPs = 0; for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { if (ipn.getReason() == InfopointReason.LINE_NUMBER) { @@ -84,7 +86,7 @@ CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()); final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, - getProfilingInfo(graph), getSpeculationLog(), getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + getProfilingInfo(graph), getSpeculationLog(), getSuites(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -25,6 +25,7 @@ import org.junit.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -112,9 +113,9 @@ } private StructuredGraph getCanonicalizedGraph(String snippet) { - StructuredGraph graph = parseEager(snippet); - new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders(), null)); - for (FrameState state : graph.getNodes(FrameState.class).snapshot()) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders())); + for (FrameState state : graph.getNodes(FrameState.TYPE).snapshot()) { state.replaceAtUsages(null); state.safeDelete(); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,8 +26,8 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -61,13 +61,12 @@ } private void test(String snippet) { - StructuredGraph graph = parseProfiled(snippet); + StructuredGraph graph = parseProfiled(snippet, AllowAssumptions.NO); Map hints = new HashMap<>(); for (Invoke invoke : graph.getInvokes()) { hints.put(invoke, 1000d); } - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,8 +26,8 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -71,18 +71,17 @@ } private void test(String snippet) { - StructuredGraph graph = parseEager(snippet); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); Map hints = new HashMap<>(); for (Invoke invoke : graph.getInvokes()) { hints.put(invoke, 1000d); } - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; 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.*; @@ -62,7 +62,7 @@ test("testSynchronizedSnippet", new A(), new A()); StructuredGraph graph = getGraph("testSynchronizedSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new LockEliminationPhase().apply(graph); assertDeepEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count()); assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); @@ -80,7 +80,7 @@ test("testSynchronizedMethodSnippet", new A()); StructuredGraph graph = getGraph("testSynchronizedMethodSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new LockEliminationPhase().apply(graph); assertDeepEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count()); assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); @@ -88,9 +88,8 @@ private StructuredGraph getGraph(String snippet) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - StructuredGraph graph = parseEager(method); - Assumptions assumptions = new Assumptions(true); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = parseEager(method, AllowAssumptions.YES); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new CanonicalizerPhase(true).apply(graph, context); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,12 +24,12 @@ import org.junit.*; -import com.oracle.graal.api.code.*; 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.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -121,8 +121,8 @@ } private void test(String snippet, String referenceSnippet) { - final StructuredGraph graph = parseEager(snippet); - final StructuredGraph referenceGraph = parseEager(referenceSnippet); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + final StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); new LoopUnswitchingPhase().apply(graph); @@ -134,9 +134,8 @@ ((StateSplit) stateSplit).setStateAfter(null); } - Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); - new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), assumptions)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders())); try (Scope s = Debug.scope("Test", new DebugDumpScope("Test:" + snippet))) { assertEquals(referenceGraph, graph); } catch (Throwable e) { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -29,12 +29,12 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -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) { @@ -596,11 +596,10 @@ } private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { - final StructuredGraph graph = parseEager(snippet); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); try (Scope d = Debug.scope("FloatingReadTest", graph)) { try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) { - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context); if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { @@ -623,7 +622,7 @@ new FloatingReadPhase().apply(graph); new RemoveValueProxyPhase().apply(graph); - MidTierContext midContext = new MidTierContext(getProviders(), assumptions, getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); + MidTierContext midContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -57,10 +57,10 @@ } private void testReturnCount(String snippet, int returnCount) { - StructuredGraph graph = parseEager(snippet); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,10 +28,10 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -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); } @@ -84,8 +84,8 @@ } private StructuredGraph parseAndProcess(String snippet) { - StructuredGraph graph = parseEager(snippet); - ParameterNode param = graph.getNodes(ParameterNode.class).first(); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + 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()) { @@ -96,8 +96,7 @@ for (Invoke invoke : graph.getInvokes()) { hints.put(invoke, 1000d); } - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); @@ -106,7 +105,7 @@ private void test(String snippet) { StructuredGraph graph = parseAndProcess(snippet); - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.java.*; @@ -136,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(); } @@ -145,7 +146,7 @@ } private void test(String snippet, int rootExits, int nestedExits, int innerExits) { - StructuredGraph graph = parseEager(snippet); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); Debug.dump(graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodePosIteratorTest.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; /** * In the following tests, the correct removal of redundant phis during graph building is tested. @@ -40,7 +41,7 @@ @Test public void test1() { - StructuredGraph graph = parseEager("test1Snippet"); + StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.YES); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -53,7 +54,7 @@ @Test public void test2() { - StructuredGraph graph = parseEager("test2Snippet"); + StructuredGraph graph = parseEager("test2Snippet", AllowAssumptions.YES); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -66,7 +67,7 @@ @Test public void test3() { - StructuredGraph graph = parseEager("test3Snippet"); + StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES); Debug.dump(graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -82,7 +83,7 @@ @Test public void test4() { - StructuredGraph graph = parseEager("test4Snippet"); + StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES); Debug.dump(graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,12 +24,12 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -91,8 +91,8 @@ } private StructuredGraph compileTestSnippet(final String snippet) { - StructuredGraph graph = parseEager(snippet); - PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + PhaseContext context = new PhaseContext(getProviders()); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -57,21 +57,21 @@ } private void test(String snippet, String reference) { - StructuredGraph graph = parseEager(snippet); + 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); } - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); - StructuredGraph referenceGraph = parseEager(reference); - for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) { + StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES); + for (FrameState fs : referenceGraph.getNodes(FrameState.TYPE).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); } - new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), new Assumptions(false))); + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders())); assertEquals(referenceGraph, graph); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,10 +24,10 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; @@ -81,8 +81,8 @@ try (Scope s = Debug.scope("ReadAfterCheckCastTest", new DebugDumpScope(snippet))) { // check shape of graph, with lots of assumptions. will probably fail if graph // structure changes significantly - StructuredGraph graph = parseEager(snippet); - PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + PhaseContext context = new PhaseContext(getProviders()); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); @@ -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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -243,11 +243,10 @@ } private void test(String test, String ref) { - StructuredGraph testGraph = parseEager(test); - Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(getProviders(), assumptions)); - StructuredGraph refGraph = parseEager(ref); - new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(getProviders(), assumptions)); + StructuredGraph testGraph = parseEager(test, AllowAssumptions.NO); + new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(getProviders())); + StructuredGraph refGraph = parseEager(ref, AllowAssumptions.NO); + new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(getProviders())); assertEquals(testGraph, refGraph); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -130,12 +130,11 @@ private void test(final String snippet, final String referenceSnippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests - StructuredGraph graph = parseEager(snippet); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); Debug.dump(graph, "Graph"); - Assumptions assumptions = new Assumptions(false); - PhaseContext context = new PhaseContext(getProviders(), assumptions); + PhaseContext context = new PhaseContext(getProviders()); new CanonicalizerPhase(true).apply(graph, context); - StructuredGraph referenceGraph = parseEager(referenceSnippet); + StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.util.*; @@ -51,7 +52,7 @@ @Test public void testValueProxyInputs() { - StructuredGraph graph = parseEager("testValueProxyInputsSnippet"); + StructuredGraph graph = parseEager("testValueProxyInputsSnippet", AllowAssumptions.YES); for (FrameState fs : graph.getNodes().filter(FrameState.class).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.cfg.*; public class SimpleCFGTest extends GraalCompilerTest { @@ -40,10 +41,10 @@ @Test public void testImplies() { - StructuredGraph graph = new StructuredGraph(); + 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -109,8 +109,8 @@ } private void testZeroReturn(String methodName) { - StructuredGraph graph = parseEager(methodName); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -87,10 +87,10 @@ private void test(final String snippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests - StructuredGraph graph = parseEager(snippet); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,11 +26,11 @@ import org.junit.*; -import com.oracle.graal.api.code.*; 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.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.common.*; @@ -170,20 +170,19 @@ } private void test(String snippet, String referenceSnippet) { - StructuredGraph graph = parseEager(snippet); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); Debug.dump(graph, "Graph"); - Assumptions assumptions = new Assumptions(false); /* * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, * tail-duplication gets activated thus resulting in a graph with more nodes than the * reference graph. */ - new ConditionalEliminationPhase().apply(graph, new PhaseContext(getProviders(), assumptions)); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + new ConditionalEliminationPhase().apply(graph, new PhaseContext(getProviders())); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); // a second canonicalizer is needed to process nested MaterializeNodes - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); - StructuredGraph referenceGraph = parseEager(referenceSnippet); - new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), assumptions)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); + StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders())); assertEquals(referenceGraph, graph); } @@ -230,10 +229,9 @@ } private void testHelper(String snippet, Class clazz) { - StructuredGraph graph = parseEager(snippet); - Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); Debug.dump(graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,11 +34,12 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; public class AllocatorTest extends BackendTest { protected void testAllocation(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) { - final StructuredGraph graph = parseEager(snippet); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); try (Scope s = Debug.scope("AllocatorTest", graph, graph.method(), getCodeCache())) { final RegisterStats stats = new RegisterStats(getLIRGenerationResult(graph).getLIR()); try (Scope s2 = Debug.scope("Assertions", stats.lir)) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.compiler.test.backend; import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; @@ -47,18 +46,16 @@ } protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) { - final Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); - SchedulePhase schedule = null; try (Scope s = Debug.scope("FrontEnd")) { - schedule = GraalCompiler.emitFrontEnd(getProviders(), getBackend().getTarget(), graph, assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, + schedule = GraalCompiler.emitFrontEnd(getProviders(), getBackend().getTarget(), graph, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.method().getProfilingInfo(), null, getSuites()); } catch (Throwable e) { throw Debug.handle(e); } CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), schedule, graph, null, cc, null); + LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), schedule, graph, null, cc, null, getLIRSuites()); return lirGen; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -51,8 +52,8 @@ @Test public void test1() { final ResolvedJavaMethod javaMethod = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseEager(javaMethod); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + final StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.NO); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new DeadCodeEliminationPhase().apply(graph); for (ConstantNode node : ConstantNode.getConstantNodes(graph)) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; public final class MonitorDeoptTest extends GraalCompilerTest { @@ -134,7 +135,7 @@ public void run0() throws Throwable { ResolvedJavaMethod javaMethod = getResolvedJavaMethod("test"); - StructuredGraph graph = parseEager(javaMethod); + StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.YES); removeLoopSafepoint(graph); CompilationResult compilationResult = compile(javaMethod, graph); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,13 +26,13 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; @@ -149,17 +149,16 @@ protected void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - graph = new StructuredGraph(method); + graph = new StructuredGraph(method, AllowAssumptions.NO); try (Scope s = Debug.scope(getClass(), graph, method, getCodeCache())) { - Assumptions assumptions = new Assumptions(false); - new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), assumptions, getProviders().getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), + new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,7 @@ import org.junit.*; -import com.oracle.graal.api.code.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -40,9 +40,8 @@ @Override protected void processMethod(final String snippet) { - graph = parseEager(snippet); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + graph = parseEager(getResolvedJavaMethod(snippet), AllowAssumptions.NO); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new EarlyReadEliminationPhase(new CanonicalizerPhase(true)).apply(graph, context); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,10 +28,10 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.compiler.test.ea.EATestBase.TestClassInt; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -79,13 +79,13 @@ 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) { - graph = parseEager(snippet); - HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + graph = parseEager(snippet, AllowAssumptions.YES); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new IterativeInliningPhase(new CanonicalizerPhase(true)).apply(graph, context); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,9 +28,9 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -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,14 +239,13 @@ 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) { - graph = parseEager(snippet); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + graph = parseEager(snippet, AllowAssumptions.NO); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new PartialEscapePhase(false, true, new CanonicalizerPhase(true), null).apply(graph, context); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,12 +24,12 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; 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.*; @@ -39,7 +39,7 @@ /** * Tests {@link AbstractNewObjectNode#simplify(com.oracle.graal.graph.spi.SimplifierTool)}. - * + * */ public class PoorMansEATest extends GraalCompilerTest { public static class A { @@ -59,15 +59,14 @@ private void test(final String snippet) { try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parseEager(snippet); - Assumptions assumptions = new Assumptions(false); - HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + HighTierContext highTierContext = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); - PhaseContext context = new PhaseContext(getProviders(), assumptions); + PhaseContext context = new PhaseContext(getProviders()); 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -231,10 +232,9 @@ private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) { try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet))) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parseEager(method); + StructuredGraph graph = eagerInfopointMode ? parseDebug(method, AllowAssumptions.YES) : parseEager(method, AllowAssumptions.YES); PhaseSuite graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite(); - Assumptions assumptions = new Assumptions(true); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, graphBuilderSuite, OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), null, graphBuilderSuite, OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); new CanonicalizerPhase(true).apply(graph, context); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java Sat Feb 21 19:55:33 2015 +0100 @@ -35,7 +35,9 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @@ -77,9 +79,11 @@ /* * The graph that is compiled. We leave it empty (no nodes added yet). This means that - * it will be filled according to the graphBuilderSuite defined below. + * it will be filled according to the graphBuilderSuite defined below. We also specify + * that we want the compilation to make optimistic assumptions about runtime state such + * as the loaded class hierarchy. */ - StructuredGraph graph = new StructuredGraph(method); + StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.YES); /* * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If @@ -94,6 +98,11 @@ Suites suites = backend.getSuites().createSuites(); /* + * The low-level phases that are applied to the low-level representation. + */ + LIRSuites lirSuites = backend.getSuites().createLIRSuites(); + + /* * The calling convention for the machine code. You should have a very good reason * before you switch to a different calling convention than the one that the VM provides * by default. @@ -117,7 +126,7 @@ SpeculationLog speculationLog = null; /* Invoke the whole Graal compilation pipeline. */ - GraalCompiler.compileGraph(graph, callingConvention, method, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, + GraalCompiler.compileGraph(graph, callingConvention, method, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, lirSuites, compilationResult, factory); /* diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; @@ -33,6 +32,7 @@ import com.oracle.graal.java.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 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.nodes.util.*; @@ -210,7 +210,7 @@ * Build the Graal graph for the method using the bytecode parser provided by Graal. */ - StructuredGraph graph = new StructuredGraph(method); + StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO); /* * Support for graph dumping, IGV uses this information to show the method name of a * graph. @@ -236,9 +236,8 @@ * wrong. */ OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; - Assumptions assumptions = new Assumptions(false); - GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, null, graphBuilderConfig, optimisticOpts); + GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, graphBuilderConfig, optimisticOpts); graphBuilder.apply(graph); } catch (Throwable ex) { Debug.handle(ex); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import static com.oracle.graal.compiler.GraalCompiler.Options.*; import static com.oracle.graal.compiler.MethodFilter.*; -import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*; import java.util.*; @@ -41,12 +40,13 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.alloc.lsra.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.lir.constopt.*; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; -import com.oracle.graal.lir.stackslotalloc.*; +import com.oracle.graal.lir.phases.*; +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.*; @@ -143,6 +143,7 @@ public final ProfilingInfo profilingInfo; public final SpeculationLog speculationLog; public final Suites suites; + public final LIRSuites lirSuites; public final T compilationResult; public final CompilationResultBuilderFactory factory; @@ -160,12 +161,13 @@ * @param profilingInfo * @param speculationLog * @param suites + * @param lirSuites * @param compilationResult * @param factory */ public Request(StructuredGraph graph, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, TargetDescription target, Map cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, - SpeculationLog speculationLog, Suites suites, T compilationResult, CompilationResultBuilderFactory factory) { + SpeculationLog speculationLog, Suites suites, LIRSuites lirSuites, T compilationResult, CompilationResultBuilderFactory factory) { this.graph = graph; this.cc = cc; this.installedCodeOwner = installedCodeOwner; @@ -178,6 +180,7 @@ this.profilingInfo = profilingInfo; this.speculationLog = speculationLog; this.suites = suites; + this.lirSuites = lirSuites; this.compilationResult = compilationResult; this.factory = factory; } @@ -203,9 +206,9 @@ */ public static T compileGraph(StructuredGraph graph, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, TargetDescription target, Map cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, - ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites, T compilationResult, CompilationResultBuilderFactory factory) { - return compile(new Request<>(graph, cc, installedCodeOwner, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, compilationResult, - factory)); + ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites, LIRSuites lirSuites, T compilationResult, CompilationResultBuilderFactory factory) { + return compile(new Request<>(graph, cc, installedCodeOwner, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, lirSuites, + compilationResult, factory)); } /** @@ -216,9 +219,8 @@ public static T compile(Request r) { assert !r.graph.isFrozen(); try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache())) { - Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); - SchedulePhase schedule = emitFrontEnd(r.providers, r.target, r.graph, assumptions, r.cache, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.speculationLog, r.suites); - emitBackEnd(r.graph, null, r.cc, r.installedCodeOwner, r.backend, r.target, r.compilationResult, r.factory, assumptions, schedule, null); + SchedulePhase schedule = emitFrontEnd(r.providers, r.target, r.graph, r.cache, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.speculationLog, r.suites); + emitBackEnd(r.graph, null, r.cc, r.installedCodeOwner, r.backend, r.target, r.compilationResult, r.factory, schedule, null, r.lirSuites); } catch (Throwable e) { throw Debug.handle(e); } @@ -236,14 +238,14 @@ /** * Builds the graph, optimizes it. */ - public static SchedulePhase emitFrontEnd(Providers providers, TargetDescription target, StructuredGraph graph, Assumptions assumptions, Map cache, + public static SchedulePhase emitFrontEnd(Providers providers, TargetDescription target, StructuredGraph graph, Map cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites) { try (Scope s = Debug.scope("FrontEnd"); TimerCloseable a = FrontEnd.start()) { if (speculationLog != null) { speculationLog.collectFailedSpeculations(); } - HighTierContext highTierContext = new HighTierContext(providers, assumptions, cache, graphBuilderSuite, optimisticOpts); + HighTierContext highTierContext = new HighTierContext(providers, cache, graphBuilderSuite, optimisticOpts); if (graph.start().next() == null) { graphBuilderSuite.apply(graph, highTierContext); new DeadCodeEliminationPhase(Optional).apply(graph); @@ -254,15 +256,16 @@ suites.getHighTier().apply(graph, highTierContext); graph.maybeCompress(); - MidTierContext midTierContext = new MidTierContext(providers, assumptions, target, optimisticOpts, profilingInfo, speculationLog); + MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo, speculationLog); suites.getMidTier().apply(graph, midTierContext); graph.maybeCompress(); - LowTierContext lowTierContext = new LowTierContext(providers, assumptions, target); + LowTierContext lowTierContext = new LowTierContext(providers, target); suites.getLowTier().apply(graph, lowTierContext); graph.maybeCompress(); SchedulePhase schedule = new SchedulePhase(); + schedule.setScheduleConstants(true); schedule.apply(graph); Debug.dump(schedule, "Final HIR schedule"); return schedule; @@ -272,12 +275,12 @@ } public static void emitBackEnd(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Backend backend, - TargetDescription target, T compilationResult, CompilationResultBuilderFactory factory, Assumptions assumptions, SchedulePhase schedule, RegisterConfig registerConfig) { + TargetDescription target, T compilationResult, CompilationResultBuilderFactory factory, SchedulePhase schedule, RegisterConfig registerConfig, LIRSuites lirSuites) { try (TimerCloseable a = BackEnd.start()) { LIRGenerationResult lirGen = null; - lirGen = emitLIR(backend, target, schedule, graph, stub, cc, registerConfig); - try (Scope s = Debug.scope("CodeGen", new Object[]{lirGen, lirGen.getLIR()})) { - emitCode(backend, assumptions, lirGen, compilationResult, installedCodeOwner, factory); + lirGen = emitLIR(backend, target, schedule, graph, stub, cc, registerConfig, lirSuites); + try (Scope s = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { + emitCode(backend, graph.getAssumptions(), graph.method(), graph.getInlinedMethods(), lirGen, compilationResult, installedCodeOwner, factory); } catch (Throwable e) { throw Debug.handle(e); } @@ -297,7 +300,8 @@ } } - public static LIRGenerationResult emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc, RegisterConfig registerConfig) { + public static LIRGenerationResult emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc, + RegisterConfig registerConfig, LIRSuites lirSuites) { List blocks = schedule.getCFG().getBlocks(); Block startBlock = schedule.getCFG().getStartBlock(); assert startBlock != null; @@ -336,67 +340,41 @@ throw Debug.handle(e); } - if (ConstantLoadOptimization.Options.ConstantLoadOptimization.getValue()) { - try (Scope s = Debug.scope("ConstantLoadOptimization", lir)) { - ConstantLoadOptimization.optimize(lirGenRes.getLIR(), lirGen); - Debug.dump(lir, "After constant load optimization"); - } catch (Throwable e) { - throw Debug.handle(e); - } - } - - try (Scope s = Debug.scope("Allocator", nodeLirGen)) { - if (backend.shouldAllocateRegisters()) { - LinearScan.allocate(target, lirGenRes); - } + try (Scope s = Debug.scope("LIRStages", nodeLirGen)) { + return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lirSuites); } catch (Throwable e) { throw Debug.handle(e); } - - try (Scope s1 = Debug.scope("BuildFrameMap")) { - // build frame map - final StackSlotAllocator allocator; - if (LSStackSlotAllocator.Options.LSStackSlotAllocation.getValue()) { - allocator = new LSStackSlotAllocator(); - } else { - allocator = new SimpleStackSlotAllocator(); - } - lirGenRes.buildFrameMap(allocator); - Debug.dump(lir, "After FrameMap building"); - } - try (Scope s1 = Debug.scope("MarkLocations")) { - if (backend.shouldAllocateRegisters()) { - // currently we mark locations only if we do register allocation - LocationMarker.markLocations(lir, lirGenRes.getFrameMap()); - } - } - - try (Scope s = Debug.scope("ControlFlowOptimizations")) { - EdgeMoveOptimizer.optimize(lir); - ControlFlowOptimizer.optimize(lir, codeEmittingOrder); - if (lirGen.canEliminateRedundantMoves()) { - RedundantMoveElimination.optimize(lir, frameMapBuilder); - } - NullCheckOptimizer.optimize(lir, target.implicitNullCheckLimit); - - Debug.dump(lir, "After control flow optimization"); - } catch (Throwable e) { - throw Debug.handle(e); - } - return lirGenRes; } catch (Throwable e) { throw Debug.handle(e); } } - public static void emitCode(Backend backend, Assumptions assumptions, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, - CompilationResultBuilderFactory factory) { + public static > LIRGenerationResult emitLowLevel(TargetDescription target, List codeEmittingOrder, List linearScanOrder, LIRGenerationResult lirGenRes, + LIRGeneratorTool lirGen, LIRSuites lirSuites) { + PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen); + lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, preAllocOptContext); + + AllocationContext allocContext = new AllocationContext(); + lirSuites.getAllocationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, allocContext); + + PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(); + lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, postAllocOptContext); + + return lirGenRes; + } + + public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Set inlinedMethods, LIRGenerationResult lirGenRes, + CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { FrameMap frameMap = lirGenRes.getFrameMap(); CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); crb.finish(); - if (!assumptions.isEmpty()) { - compilationResult.setAssumptions(assumptions); + if (assumptions != null && !assumptions.isEmpty()) { + compilationResult.setAssumptions(assumptions.toArray()); + } + if (inlinedMethods != null) { + compilationResult.setMethods(rootMethod, inlinedMethods); } if (Debug.isMeterEnabled()) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Sat Feb 21 19:55:33 2015 +0100 @@ -65,6 +65,8 @@ public static final OptionValue SuppressZeroDebugValues = new OptionValue<>(false); @Option(help = "Send Graal IR to dump handlers on error", type = OptionType.Debug) public static final OptionValue DumpOnError = new OptionValue<>(false); + @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) + public static final OptionValue InterceptBailout = new OptionValue<>(false); @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) public static final OptionValue LogVerbose = new OptionValue<>(false); // @formatter:on @@ -254,7 +256,7 @@ @Override public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException) { + if (e instanceof BailoutException && !InterceptBailout.getValue()) { return null; } Debug.setConfig(Debug.fixedConfig(Debug.DEFAULT_LOG_LEVEL, Debug.DEFAULT_LOG_LEVEL, false, false, false, false, dumpHandlers, verifyHandlers, output)); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Sat Feb 21 19:55:33 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); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Sat Feb 21 19:55:33 2015 +0100 @@ -74,7 +74,7 @@ } } - private static Pattern tokenizer = Pattern.compile("\\s*([()=]|[A-Za-z][A-Za-z0-9]*)\\s*"); + private static final Pattern tokenizer = Pattern.compile("\\s*([()=]|[A-Za-z][A-Za-z0-9]*)\\s*"); private class RuleParser { private ArrayList capturedTypes = new ArrayList<>(); @@ -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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Sat Feb 21 19:55:33 2015 +0100 @@ -39,32 +39,16 @@ 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); for (int e = 0; e < edges.getDirectCount(); e++) { @@ -73,7 +57,7 @@ } } 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 +75,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 +103,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 +117,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java Sat Feb 21 19:55:33 2015 +0100 @@ -23,6 +23,10 @@ package com.oracle.graal.compiler.phases; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.lir.phases.*; +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.*; @@ -40,4 +44,17 @@ public PhaseSuite createLowTier() { return new LowTier(); } + + public LIRPhaseSuite createPreAllocationOptimizationStage() { + return new PreAllocationOptimizationStage(); + } + + public LIRPhaseSuite createAllocationStage() { + return new AllocationStage(); + } + + public LIRPhaseSuite createPostAllocationOptimizationStage() { + return new PostAllocationOptimizationStage(); + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Sat Feb 21 19:55:33 2015 +0100 @@ -101,8 +101,6 @@ public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory); - public abstract boolean shouldAllocateRegisters(); - public abstract StackIntrospection getStackIntrospection(); /** diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Feb 21 19:55:33 2015 +0100 @@ -467,6 +467,10 @@ log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } + public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { + log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + /** * @see #log(int, String, Object) */ @@ -476,6 +480,12 @@ } } + public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + } + public static void logv(String format, Object... args) { logv(DEFAULT_LOG_LEVEL, format, args); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfigScope.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/LogStream.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTY.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValueMap.java
    --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValueMap.java	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValueMap.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -29,7 +29,7 @@
      */
     public class DebugValueMap {
     
    -    private static List topLevelMaps = new ArrayList<>();
    +    private static final List topLevelMaps = new ArrayList<>();
     
         private long[] values;
         private List children;
    diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/KeyRegistry.java
    --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/KeyRegistry.java	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/KeyRegistry.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -29,12 +29,12 @@
      */
     public class KeyRegistry {
     
    -    private static Map keyMap = new HashMap<>();
    -    private static List debugValues = new ArrayList<>();
    +    private static final Map keyMap = new HashMap<>();
    +    private static final List debugValues = new ArrayList<>();
     
         /**
          * Ensures a given debug value is registered.
    -     * 
    +     *
          * @return the globally unique id for {@code value}
          */
         public static synchronized int register(DebugValue value) {
    @@ -48,7 +48,7 @@
     
         /**
          * Gets a immutable view of the registered debug values.
    -     * 
    +     *
          * @return a list where {@code get(i).getIndex() == i}
          */
         public static synchronized List getDebugValues() {
    diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -485,7 +485,7 @@
         }
     
         public Node findDuplicate(Node node) {
    -        NodeClass nodeClass = node.getNodeClass();
    +        NodeClass nodeClass = node.getNodeClass();
             assert nodeClass.valueNumberable();
             if (nodeClass.isLeafNode()) {
                 // Leaf node: look up in cache
    @@ -625,7 +625,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 +689,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 +708,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 +741,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 +766,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();
    diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -76,6 +76,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 +161,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 +202,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() {
    @@ -332,7 +342,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;
             }
    @@ -497,7 +509,7 @@
             }
         }
     
    -    public final NodeClass getNodeClass() {
    +    public final NodeClass getNodeClass() {
             return nodeClass;
         }
     
    @@ -739,7 +751,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Sat Feb 21 19:55:33 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.*;
    @@ -50,12 +51,9 @@
      * 
  11. The identifier for an {@link IterableNodeType} class.
  12. * */ -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 +71,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; @@ -134,11 +123,11 @@ 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); @@ -183,9 +172,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); @@ -256,7 +245,7 @@ } static int allocatedNodeIterabledIds() { - return nextIterableId; + return nextIterableId.get(); } public EnumSet getAllowedUsageTypes() { @@ -316,7 +305,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 +553,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; } @@ -648,7 +637,7 @@ } } - public Class getJavaClass() { + public Class getJavaClass() { return getClazz(); } @@ -702,7 +691,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 +735,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeIdAccessor.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUnionFind.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUnionFind.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,96 @@ +/* + * 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; + +/** + * Union-find data structure for {@link Node Nodes}. + * + * All operations have an accumulated worst-case complexity of O(a(n)), where a(n) is the inverse of + * the Ackermann function A(n,n). + */ +public class NodeUnionFind extends NodeIdAccessor { + + private int[] rank; + private int[] parent; + + /** + * Create a new union-find data structure for a {@link Graph}. Initially, all nodes are in their + * own equivalence set. + */ + public NodeUnionFind(Graph graph) { + super(graph); + rank = new int[graph.nodeIdCount()]; + parent = new int[graph.nodeIdCount()]; + for (int i = 0; i < parent.length; i++) { + parent[i] = i; + } + } + + /** + * Merge the equivalence sets of two nodes. + * + * After calling this function, find(a) == find(b). + */ + public void union(Node a, Node b) { + union(getNodeId(a), getNodeId(b)); + } + + /** + * Get a representative element of the equivalence set of a node. + * + * This function returns the same representative element for all members of the same equivalence + * set, i.e., find(a) == find(b) if and only if a and b are in the same set. + */ + public Node find(Node a) { + int id = find(getNodeId(a)); + return graph.getNode(id); + } + + public boolean equiv(Node a, Node b) { + return find(getNodeId(a)) == find(getNodeId(b)); + } + + private void union(int a, int b) { + int aRoot = find(a); + int bRoot = find(b); + if (aRoot != bRoot) { + if (rank[aRoot] < rank[bRoot]) { + parent[aRoot] = bRoot; + } else { + parent[bRoot] = aRoot; + if (rank[aRoot] == rank[bRoot]) { + rank[aRoot]++; + } + } + } + } + + private int find(int a) { + int ret = a; + while (ret != parent[ret]) { + parent[ret] = parent[parent[ret]]; + ret = parent[ret]; + } + return ret; + } +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/TypedGraphNodeIterator.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/CanonicalizerTool.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/CanonicalizerTool.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/CanonicalizerTool.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,13 +22,10 @@ */ package com.oracle.graal.graph.spi; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; public interface CanonicalizerTool { - Assumptions assumptions(); - MetaAccessProvider getMetaAccess(); ConstantReflectionProvider getConstantReflection(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Simplifiable.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Sat Feb 21 19:55:33 2015 +0100 @@ -62,11 +62,6 @@ } @Override - public boolean shouldAllocateRegisters() { - return true; - } - - @Override public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; return new AMD64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Sat Feb 21 19:55:33 2015 +0100 @@ -152,21 +152,18 @@ try (InitTimer rt = timer("create Lowerer provider")) { lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); } - // Replacements cannot have speculative optimizations since they have - // to be valid for the entire run of the VM. - Assumptions assumptions = new Assumptions(false); Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, new HotSpotStampProvider()); try (InitTimer rt = timer("create SnippetReflection provider")) { snippetReflection = createSnippetReflection(runtime); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(runtime, assumptions, p, snippetReflection); + replacements = createReplacements(runtime, p, snippetReflection); } try (InitTimer rt = timer("create Disassembler provider")) { 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); } @@ -187,8 +184,8 @@ return new HotSpotDisassemblerProvider(runtime); } - protected Replacements createReplacements(HotSpotGraalRuntimeProvider runtime, Assumptions assumptions, Providers p, SnippetReflectionProvider snippetReflection) { - return new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), assumptions, p.getCodeCache().getTarget()); + protected Replacements createReplacements(HotSpotGraalRuntimeProvider runtime, Providers p, SnippetReflectionProvider snippetReflection) { + return new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), p.getCodeCache().getTarget()); } protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, @@ -212,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) { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableAddressOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCardTableShiftOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPatchReturnAddressOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64TailcallOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Sat Feb 21 19:55:33 2015 +0100 @@ -68,11 +68,6 @@ } @Override - public boolean shouldAllocateRegisters() { - return true; - } - - @Override public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; return new SPARCFrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Sat Feb 21 19:55:33 2015 +0100 @@ -60,14 +60,11 @@ Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); LoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target); - // Replacements cannot have speculative optimizations since they have - // to be valid for the entire run of the VM. - Assumptions assumptions = new Assumptions(false); Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, new HotSpotStampProvider()); HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime); - HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), assumptions, target); + 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); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java Sat Feb 21 19:55:33 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 @@ -36,6 +36,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; @@ -44,6 +45,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Sat Feb 21 19:55:33 2015 +0100 @@ -36,6 +36,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; @@ -43,6 +44,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java Sat Feb 21 19:55:33 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 @@ -41,6 +41,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; @@ -50,6 +51,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Sat Feb 21 19:55:33 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 @@ -47,6 +47,8 @@ @Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER") final class SPARCHotSpotJumpToExceptionHandlerInCallerOp extends SPARCHotSpotEpilogueOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotDeoptimizeCallerOp.class); + @Use(REG) AllocatableValue handlerInCallerPc; @Use(REG) AllocatableValue exception; @Use(REG) AllocatableValue exceptionPc; @@ -54,6 +56,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Sat Feb 21 19:55:33 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,8 +35,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java Sat Feb 21 19:55:33 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,6 +36,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java Sat Feb 21 19:55:33 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 @@ */ @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; @@ -45,6 +46,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Sat Feb 21 19:55:33 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("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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java Sat Feb 21 19:55:33 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("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; @@ -46,6 +47,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Sat Feb 21 19:55:33 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 @@ -43,6 +43,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; @@ -50,9 +51,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java Sat Feb 21 19:55:33 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,10 +41,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java Sat Feb 21 19:55:33 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,15 +27,18 @@ import com.oracle.graal.asm.sparc.SPARCAssembler.Prefetch; 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -39,7 +39,9 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionValue.OverrideScope; @@ -182,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()); @@ -193,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()); @@ -203,15 +205,17 @@ } private StructuredGraph compile(String test, boolean compileAOT) { - StructuredGraph graph = parseEager(test); + StructuredGraph graph = parseEager(test, AllowAssumptions.YES); ResolvedJavaMethod method = graph.method(); try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) { CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); // create suites everytime, as we modify options for the compiler - final Suites suitesLocal = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites(); + SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); + final Suites suitesLocal = suitesProvider.createSuites(); + final LIRSuites lirSuitesLocal = suitesProvider.createLIRSuites(); final CompilationResult compResult = compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), - OptimisticOptimizations.ALL, getProfilingInfo(graph), getSpeculationLog(), suitesLocal, new CompilationResult(), CompilationResultBuilderFactory.Default); + OptimisticOptimizations.ALL, getProfilingInfo(graph), getSpeculationLog(), suitesLocal, lirSuitesLocal, new CompilationResult(), CompilationResultBuilderFactory.Default); addMethod(method, compResult); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; public class ClassSubstitutionsTests extends GraalCompilerTest { @@ -43,7 +44,7 @@ protected StructuredGraph test(final String snippet) { try (Scope s = Debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parseEager(snippet); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); Debug.dump(graph, snippet); @@ -180,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java Sat Feb 21 19:55:33 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 @@ -33,25 +33,20 @@ */ public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest { - /* - * We have to ignore this test for now because currently there is no way to read uncompressed - * pointers in a compressed world via JNI. - */ - @Ignore @Test public void testObjectSubstitutions() { + TestClassA obj = new TestClassA(); + test("getClass0"); test("objectHashCode"); - Object obj = new Object(); - - assertDeepEquals("a string".getClass(), ObjectSubstitutions.getClass("a string")); - assertDeepEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj)); + test("getClass0", "a string"); + test("objectHashCode", obj); } @SuppressWarnings("all") - public static boolean getClass0(Object obj, Class clazz) { - return obj.getClass() == clazz; + public static Class getClass0(Object obj) { + return obj.getClass(); } @SuppressWarnings("all") @@ -59,15 +54,9 @@ return obj.hashCode(); } - /* - * We have to ignore this test for now because currently there is no way to read uncompressed - * pointers in a compressed world via JNI. - */ - @Ignore @Test public void testClassSubstitutions() { test("getModifiers"); - test("isInstance"); test("isInterface"); test("isArray"); test("isPrimitive"); @@ -75,15 +64,12 @@ test("getComponentType"); for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) { - assertDeepEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c)); - assertDeepEquals(c.isInterface(), ClassSubstitutions.isInterface(c)); - assertDeepEquals(c.isArray(), ClassSubstitutions.isArray(c)); - assertDeepEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c)); - assertDeepEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c)); - assertDeepEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c)); - for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { - assertDeepEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o)); - } + test("getModifiers", c); + test("isInterface", c); + test("isArray", c); + test("isPrimitive", c); + test("getSuperClass", c); + test("getComponentType", c); } } @@ -93,11 +79,6 @@ } @SuppressWarnings("all") - public static boolean isInstance(Class clazz) { - return clazz.isInstance(Number.class); - } - - @SuppressWarnings("all") public static boolean isInterface(Class clazz) { return clazz.isInterface(); } @@ -122,11 +103,6 @@ return clazz.getComponentType(); } - /* - * We have to ignore this test for now because currently there is no way to read uncompressed - * pointers in a compressed world via JNI. - */ - @Ignore @Test public void testThreadSubstitutions() { test("currentThread"); @@ -134,13 +110,13 @@ test("threadInterrupted"); Thread currentThread = Thread.currentThread(); - assertDeepEquals(currentThread, ThreadSubstitutions.currentThread()); - assertDeepEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false)); + test("currentThread", currentThread); + test("threadIsInterrupted", currentThread); } @SuppressWarnings("all") - public static Thread currentThread() { - return Thread.currentThread(); + public static boolean currentThread(Thread other) { + return Thread.currentThread() == other; } @SuppressWarnings("all") @@ -161,7 +137,7 @@ SystemSubstitutions.currentTimeMillis(); SystemSubstitutions.nanoTime(); for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { - assertDeepEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o)); + test("systemIdentityHashCode", o); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; public class HotSpotNmethodTest extends GraalCompilerTest { @@ -36,7 +37,7 @@ @Test public void testInstallCodeInvalidation() { final ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod("foo"); - final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo")); + final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", AllowAssumptions.YES)); Assert.assertTrue(nmethod.isValid()); Object result; try { @@ -59,7 +60,7 @@ @Test public void testInstallCodeInvalidationWhileRunning() { final ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod("foo"); - final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo")); + final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", AllowAssumptions.YES)); Object result; try { result = nmethod.executeVarargs(nmethod, null, null); @@ -73,7 +74,7 @@ @Test public void testInstalledCodeCalledFromCompiledCode() { final ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod("foo"); - final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo")); + final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", AllowAssumptions.YES)); Assert.assertTrue(nmethod.isValid()); try { for (int i = 0; i < ITERATION_COUNT; ++i) { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.replacements.test.*; /** @@ -35,11 +36,11 @@ @Test public void test() { - StructuredGraph graph = new StructuredGraph(); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES); test("getNodeClass", ConstantNode.forInt(42, graph)); } - public static NodeClass getNodeClass(Node n) { + public static NodeClass getNodeClass(Node n) { return n.getNodeClass(); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.compiler.test.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { @@ -68,8 +69,8 @@ } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m) { - StructuredGraph graph = super.parseEager(m); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + StructuredGraph graph = super.parseEager(m, allowAssumptions); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.CompileTheWorld.Config; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.printer.*; /** @@ -134,10 +135,10 @@ method.reprofile(); int id = method.allocateCompileId(INVOCATION_ENTRY_BCI); - long ctask = 0L; + long graalEnv = 0L; try (MemoryUsageCloseable c = label == null ? null : new MemoryUsageCloseable(label)) { - CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, ctask, id, false); + CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, graalEnv, id, false); task.runCompilation(); } } @@ -151,9 +152,9 @@ method.reprofile(); int id = method.allocateCompileId(INVOCATION_ENTRY_BCI); - long ctask = 0L; + long graalEnv = 0L; try (AllocSpy as = AllocSpy.open(methodName)) { - CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, ctask, id, false); + CompilationTask task = new CompilationTask(backend, method, INVOCATION_ENTRY_BCI, graalEnv, id, false); task.runCompilation(); } } @@ -164,7 +165,7 @@ private void compileAndTime(String methodName) { // Parse in eager mode to resolve methods/fields/classes - parseEager(methodName); + parseEager(methodName, AllowAssumptions.YES); // Warm up and initialize compiler phases used by this compilation for (int i = 0; i < 10; i++) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,7 +26,6 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.test.*; @@ -39,6 +38,7 @@ import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -244,9 +244,9 @@ private void testHelper(final String snippetName, final int expectedBarriers) throws Exception, SecurityException { ResolvedJavaMethod snippet = getResolvedJavaMethod(snippetName); try (Scope s = Debug.scope("WriteBarrierAdditionTest", snippet)) { - StructuredGraph graph = parseEager(snippet); - HighTierContext highContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); - MidTierContext midContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + HighTierContext highContext = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + MidTierContext midContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); new NodeIntrinsificationPhase(getProviders(), getSnippetReflection()).apply(graph); new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,7 +26,6 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; @@ -37,6 +36,7 @@ import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.hotspot.replacements.arraycopy.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -626,11 +626,11 @@ private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) { try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { - final StructuredGraph graph = parseEager(snippet); - HighTierContext highTierContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + HighTierContext highTierContext = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); - MidTierContext midTierContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); + MidTierContext midTierContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); new GuardLoweringPhase().apply(graph, midTierContext); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Sat Feb 21 19:55:33 2015 +0100 @@ -42,7 +42,6 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.baseline.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -53,8 +52,8 @@ import com.oracle.graal.hotspot.events.EventProvider.CompilerFailureEvent; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; -import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -96,17 +95,16 @@ private static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean(); /** - * The address of the native CompileTask associated with this compilation or 0L if no such - * association exists. + * The address of the GraalEnv associated with this compilation or 0L if no such object exists. */ - private final long ctask; + private final long graalEnv; - public CompilationTask(HotSpotBackend backend, HotSpotResolvedJavaMethod method, int entryBCI, long ctask, int id, boolean installAsDefault) { + public CompilationTask(HotSpotBackend backend, HotSpotResolvedJavaMethod method, int entryBCI, long graalEnv, int id, boolean installAsDefault) { this.backend = backend; this.method = method; this.entryBCI = entryBCI; this.id = id; - this.ctask = ctask; + this.graalEnv = graalEnv; this.installAsDefault = installAsDefault; } @@ -138,6 +136,10 @@ return providers.getSuites().getDefaultSuites(); } + protected LIRSuites getLIRSuites(HotSpotProviders providers) { + return providers.getSuites().getDefaultLIRSuites(); + } + protected PhaseSuite getGraphBuilderSuite(HotSpotProviders providers) { PhaseSuite suite = withSimpleDebugInfoIfRequested(providers.getSuites().getDefaultGraphBuilderSuite()); @@ -193,46 +195,45 @@ // Begin the compilation event. compilationEvent.begin(); - if (UseBaselineCompiler.getValue() == true) { - HotSpotProviders providers = backend.getProviders(); - BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess()); - OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; - result = baselineCompiler.generate(method, -1, backend, new CompilationResult(), method, CompilationResultBuilderFactory.Default, optimisticOpts, providers.getReplacements()); - } else { - Map graphCache = null; - if (GraalOptions.CacheGraphs.getValue()) { - graphCache = new HashMap<>(); - } + Map graphCache = null; + if (GraalOptions.CacheGraphs.getValue()) { + graphCache = new HashMap<>(); + } + + boolean recordEvolMethodDeps = graalEnv == 0 || unsafe.getByte(graalEnv + config.graalEnvJvmtiCanHotswapOrPostBreakpointOffset) != 0; - HotSpotProviders providers = backend.getProviders(); - Replacements replacements = providers.getReplacements(); - graph = replacements.getMethodSubstitution(method); - if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { - graph = new StructuredGraph(method, entryBCI); - } else { - // Compiling method substitution - must clone the graph - graph = graph.copy(); + HotSpotProviders providers = backend.getProviders(); + Replacements replacements = providers.getReplacements(); + graph = replacements.getMethodSubstitution(method); + if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { + graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue())); + if (!recordEvolMethodDeps) { + graph.disableInlinedMethodRecording(); } - InlinedBytecodes.add(method.getCodeSize()); - CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); - if (graph.getEntryBCI() != StructuredGraph.INVOCATION_ENTRY_BCI) { - // for OSR, only a pointer is passed to the method. - JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)}; - CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes, - backend.getTarget(), false); - cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0)); - } - Suites suites = getSuites(providers); - ProfilingInfo profilingInfo = getProfilingInfo(); - OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); - if (isOSR) { - // In OSR compiles, we cannot rely on never executed code profiles, because - // all code after the OSR loop is never executed. - optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); - } - result = compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, - method.getSpeculationLog(), suites, new CompilationResult(), CompilationResultBuilderFactory.Default); + } else { + // Compiling method substitution - must clone the graph + graph = graph.copy(graph.name, method, AllowAssumptions.from(OptAssumptions.getValue()), recordEvolMethodDeps); } + InlinedBytecodes.add(method.getCodeSize()); + CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); + if (graph.getEntryBCI() != StructuredGraph.INVOCATION_ENTRY_BCI) { + // for OSR, only a pointer is passed to the method. + JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)}; + CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes, + backend.getTarget(), false); + cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0)); + } + Suites suites = getSuites(providers); + LIRSuites lirSuites = getLIRSuites(providers); + ProfilingInfo profilingInfo = getProfilingInfo(); + OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); + if (isOSR) { + // In OSR compiles, we cannot rely on never executed code profiles, because + // all code after the OSR loop is never executed. + optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); + } + result = compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, + method.getSpeculationLog(), suites, lirSuites, new CompilationResult(), CompilationResultBuilderFactory.Default); result.setId(getId()); result.setEntryBCI(entryBCI); } catch (Throwable e) { @@ -307,7 +308,9 @@ compilationEvent.commit(); } - if (ctask != 0) { + if (graalEnv != 0) { + long ctask = unsafe.getAddress(graalEnv + config.graalEnvTaskOffset); + assert ctask != 0L; unsafe.putInt(ctask + config.compileTaskNumInlinedBytecodesOffset, processedBytes); } if ((config.ciTime || config.ciTimeEach) && installedCode != null) { @@ -329,7 +332,7 @@ final HotSpotCodeCacheProvider codeCache = backend.getProviders().getCodeCache(); InstalledCode installedCode = null; try (Scope s = Debug.scope("CodeInstall", new DebugDumpScope(String.valueOf(id), true), codeCache, method)) { - installedCode = codeCache.installMethod(method, compResult, ctask, installAsDefault); + installedCode = codeCache.installMethod(method, compResult, graalEnv, installAsDefault); } catch (Throwable e) { throw Debug.handle(e); } @@ -348,11 +351,11 @@ * * @param metaspaceMethod * @param entryBCI - * @param ctask address of native CompileTask object + * @param graalEnv address of native GraalEnv object * @param id CompileTask::_compile_id */ @SuppressWarnings("unused") - private static void compileMetaspaceMethod(long metaspaceMethod, int entryBCI, long ctask, int id) { + private static void compileMetaspaceMethod(long metaspaceMethod, int entryBCI, long graalEnv, int id) { // Ensure a Graal runtime is initialized prior to Debug being initialized as the former // may include processing command line options used by the latter. Graal.getRuntime(); @@ -363,15 +366,15 @@ } HotSpotResolvedJavaMethod method = HotSpotResolvedJavaMethodImpl.fromMetaspace(metaspaceMethod); - compileMethod(method, entryBCI, ctask, id); + compileMethod(method, entryBCI, graalEnv, id); } /** * Compiles a method to machine code. */ - static void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long ctask, int id) { + static void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long graalEnv, int id) { HotSpotBackend backend = runtime().getHostBackend(); - CompilationTask task = new CompilationTask(backend, method, entryBCI, ctask, id, true); + CompilationTask task = new CompilationTask(backend, method, entryBCI, graalEnv, id, true); try (DebugConfigScope dcs = setConfig(new TopLevelDebugConfig())) { task.runCompilation(); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Sat Feb 21 19:55:33 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 diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java Sat Feb 21 19:55:33 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. */ @@ -34,17 +36,32 @@ public final HotSpotResolvedJavaMethod method; public final int entryBCI; public final int id; - public final long ctask; + 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); } - public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long ctask) { + public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long graalEnv) { super(compResult); this.method = method; this.entryBCI = compResult.getEntryBCI(); this.id = compResult.getId(); - this.ctask = ctask; + this.graalEnv = graalEnv; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + id + ":" + method.format("%H.%n(%p)%r@") + entryBCI + "]"; + } + + public String getInstallationFailureMessage() { + return installationFailureMessage; } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Sat Feb 21 19:55:33 2015 +0100 @@ -51,7 +51,13 @@ * Checks the conditions a compilation must satisfy to be installed as a RuntimeStub. */ private boolean checkStubInvariants(CompilationResult compResult) { - assert compResult.getExceptionHandlers().isEmpty(); + assert compResult.getExceptionHandlers().isEmpty() : this; + + // Stubs cannot be recompiled so they cannot be compiled with + // assumptions and there is no point in recording evol_method dependencies + assert compResult.getAssumptions().isEmpty() : "stubs should not use assumptions: " + this; + assert compResult.getMethods() == null : "stubs should not record evol_method dependencies: " + this; + for (DataPatch data : compResult.getDataPatches()) { if (data.reference instanceof ConstantReference) { ConstantReference ref = (ConstantReference) data.reference; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Sat Feb 21 19:55:33 2015 +0100 @@ -67,7 +67,7 @@ @Override protected BytecodeFrame computeFrameForState(FrameState state) { - assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI; + assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI : state.bci; return super.computeFrameForState(state); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Sat Feb 21 19:55:33 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,11 +73,8 @@ try (InitTimer st = timer("graphBuilderPlugins.initialize")) { GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); - GraphBuilderPlugins plugins = phase.getGraphBuilderPlugins(); - Iterable sl = Services.load(GraphBuilderPluginsProvider.class); - for (GraphBuilderPluginsProvider p : sl) { - p.registerPlugins(providers.getMetaAccess(), plugins); - } + InvocationPlugins plugins = phase.getGraphBuilderConfig().getInvocationPlugins(); + registerInvocationPlugins(providers, plugins); } try (InitTimer st = timer("foreignCalls.initialize")) { @@ -103,4 +105,9 @@ } } } + + protected void registerInvocationPlugins(HotSpotProviders providers, InvocationPlugins plugins) { + StandardGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), plugins); + HotSpotGraphBuilderPlugins.registerInvocationPlugins(providers, plugins); + } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -44,8 +44,8 @@ private final HotSpotVMConfig config; - public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, HotSpotVMConfig config, Assumptions assumptions, TargetDescription target) { - super(providers, snippetReflection, assumptions, target); + public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, HotSpotVMConfig config, TargetDescription target) { + super(providers, snippetReflection, target); this.config = config; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Feb 21 19:55:33 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; @@ -1082,6 +1081,8 @@ @HotSpotVMConstant(name = "JVM_ACC_MONITOR_MATCH") @Stable public int jvmAccMonitorMatch; @HotSpotVMConstant(name = "JVM_ACC_HAS_MONITOR_BYTECODES") @Stable public int jvmAccHasMonitorBytecodes; + @HotSpotVMField(name = "GraalEnv::_task", type = "CompileTask*", get = HotSpotVMField.Type.OFFSET) @Stable public int graalEnvTaskOffset; + @HotSpotVMField(name = "GraalEnv::_jvmti_can_hotswap_or_post_breakpoint", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int graalEnvJvmtiCanHotswapOrPostBreakpointOffset; @HotSpotVMField(name = "CompileTask::_num_inlined_bytecodes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int compileTaskNumInlinedBytecodesOffset; /** @@ -1344,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Sat Feb 21 19:55:33 2015 +0100 @@ -119,6 +119,10 @@ if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { instanceofSnippets.lower((InstanceOfDynamicNode) n, tool); } + } else if (n instanceof ClassIsAssignableFromNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool); + } } else if (n instanceof NewInstanceNode) { if (graph.getGuardsStage().areFrameStatesAtDeopts()) { newObjectSnippets.lower((NewInstanceNode) n, registers, tool); @@ -352,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Sat Feb 21 19:55:33 2015 +0100 @@ -239,12 +239,12 @@ return installedCode; } - public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long ctask, boolean isDefault) { + public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long graalEnv, boolean isDefault) { if (compResult.getId() == -1) { compResult.setId(method.allocateCompileId(compResult.getEntryBCI())); } HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault); - runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(method, compResult, ctask), installedCode, method.getSpeculationLog()); + runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(method, compResult, graalEnv), installedCode, method.getSpeculationLog()); return logOrDump(installedCode, compResult); } @@ -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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,253 @@ +/* + * 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.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.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.*; + +/** + * Provides HotSpot specific {@link InvocationPlugin}s. + */ +public class HotSpotGraphBuilderPlugins { + 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) { + ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp(); + ValueNode mirror; + if (objectStamp.isExactType() && objectStamp.nonNull()) { + mirror = builder.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), builder.getMetaAccess())); + } else { + StampProvider stampProvider = builder.getStampProvider(); + LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, nullCheckedValue(builder, rcvr))); + mirror = builder.append(new HubGetClassNode(builder.getMetaAccess(), hub)); + } + builder.push(Kind.Object, mirror); + return true; + } + }); + } + + 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()) { + ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); + if (type != null && !type.isPrimitive()) { + builder.push(Kind.Object, builder.append(CheckCastNode.create(type, object, null, false, builder.getAssumptions()))); + return true; + } + } + return false; + } + }); + r.register2("isInstance", Receiver.class, Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode rcvr, ValueNode object) { + if (rcvr.isConstant() && !rcvr.isNullConstant()) { + ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); + if (type != null && !type.isPrimitive()) { + LogicNode node = builder.append(InstanceOfNode.create(type, object, null)); + builder.push(Kind.Boolean.getStackKind(), builder.append(ConditionalNode.create(node))); + return true; + } + } + return false; + } + }); + } + + 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()) { + Object object = ((HotSpotObjectConstantImpl) rcvr.asConstant()).object(); + StableOptionValue option = (StableOptionValue) object; + ConstantNode value = builder.append(ConstantNode.forConstant(HotSpotObjectConstantImpl.forObject(option.getValue()), builder.getMetaAccess())); + builder.push(Kind.Object, value); + return true; + } + return false; + } + }); + } + + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMemoryAccessProviderImpl.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Sat Feb 21 19:55:33 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()); @@ -183,7 +175,7 @@ CallSite callSite = (CallSite) object; MethodHandle target = callSite.getTarget(); if (!(callSite instanceof ConstantCallSite)) { - if (assumptions == null || !assumptions.useOptimisticAssumptions()) { + if (assumptions == null) { return null; } assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target)); @@ -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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,45 +22,73 @@ */ 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.function.*; +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}. */ -public class HotSpotSuitesProvider implements SuitesProvider, Supplier { +public class HotSpotSuitesProvider implements SuitesProvider { protected final DerivedOptionValue defaultSuites; protected final PhaseSuite defaultGraphBuilderSuite; + private final DerivedOptionValue defaultLIRSuites; protected final HotSpotGraalRuntimeProvider runtime; - public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime) { + private class SuitesSupplier implements OptionSupplier { + + private static final long serialVersionUID = -3444304453553320390L; + + public Suites get() { + return createSuites(); + } + + } + + private class LIRSuitesSupplier implements OptionSupplier { + + private static final long serialVersionUID = -1558586374095874299L; + + public LIRSuites get() { + return createLIRSuites(); + } + + } + + public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { this.runtime = runtime; - this.defaultGraphBuilderSuite = createGraphBuilderSuite(); - this.defaultSuites = new DerivedOptionValue<>(this); + this.defaultGraphBuilderSuite = createGraphBuilderSuite(metaAccess, constantReflection, replacements); + this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); + this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); } public Suites getDefaultSuites() { return defaultSuites.getValue(); } - public Suites get() { - return createSuites(); - } - public PhaseSuite getDefaultGraphBuilderSuite() { return defaultGraphBuilderSuite; } @@ -84,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; } @@ -117,4 +225,12 @@ return gbs; } + public LIRSuites getDefaultLIRSuites() { + return defaultLIRSuites.getValue(); + } + + public LIRSuites createLIRSuites() { + return Suites.createDefaultLIRSuites(); + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Sat Feb 21 19:55:33 2015 +0100 @@ -37,6 +37,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -160,10 +161,11 @@ private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) { StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes); Suites suites = providers.getSuites().createSuites(); + LIRSuites lirSuites = providers.getSuites().createLIRSuites(); PhaseSuite phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false); CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL, - DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, new CompilationResult(), CompilationResultBuilderFactory.Default); + DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, lirSuites, new CompilationResult(), CompilationResultBuilderFactory.Default); InstalledCode installedCode; try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null, null); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.virtual.*; @@ -52,7 +53,7 @@ public static StructuredGraph getGraph(HotSpotProviders providers, RawNativeCallNodeFactory factory, long functionPointer, Class returnType, Class... argumentTypes) { try { ResolvedJavaMethod method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class)); - StructuredGraph g = new StructuredGraph(method); + StructuredGraph g = new StructuredGraph(method, AllowAssumptions.NO); ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object))); ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object))); ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object))); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Sat Feb 21 19:55:33 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.*; @@ -33,13 +34,15 @@ /** * {@link MacroNode Macro node} for {@link Class#cast(Object)}. * - * @see ClassSubstitutions#cast(Class, Object) + * @see HotSpotClassSubstitutions#cast(Class, Object) */ @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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,14 +34,16 @@ /** * {@link MacroNode Macro node} for {@link Class#getClassLoader0()}. * - * @see ClassSubstitutions#getClassLoader0(Class) + * @see HotSpotClassSubstitutions#getClassLoader0(Class) */ @SuppressWarnings("javadoc") @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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Sat Feb 21 19:55:33 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 @@ -34,13 +34,15 @@ /** * {@link MacroNode Macro node} for {@link Class#getComponentType()}. * - * @see ClassSubstitutions#getComponentType(Class) + * @see HotSpotClassSubstitutions#getComponentType(Class) */ @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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Sat Feb 21 19:55:33 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,13 +33,14 @@ /** * {@link MacroNode Macro node} for {@link Class#getModifiers()}. * - * @see ClassSubstitutions#getModifiers(Class) + * @see HotSpotClassSubstitutions#getModifiers(Class) */ @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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Sat Feb 21 19:55:33 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 @@ -34,13 +34,15 @@ /** * {@link MacroNode Macro node} for {@link Class#getSuperclass()}. * - * @see ClassSubstitutions#getSuperclass(Class) + * @see HotSpotClassSubstitutions#getSuperclass(Class) */ @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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Sat Feb 21 19:55:33 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,13 +33,15 @@ /** * {@link MacroNode Macro node} for {@link Class#isArray()}. * - * @see ClassSubstitutions#isArray(Class) + * @see HotSpotClassSubstitutions#isArray(Class) */ @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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +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.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.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isAssignableFrom(Class)}. - * - * @see ClassSubstitutions#isAssignableFrom(Class, Class) - */ -@NodeInfo -public final class ClassIsAssignableFromNode extends MacroStateSplitNode implements Canonicalizable { - public ClassIsAssignableFromNode(Invoke invoke) { - super(invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - private ValueNode getOtherClass() { - return arguments.get(1); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - ValueNode otherClass = getOtherClass(); - if (javaClass.isConstant() && otherClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType thisType = constantReflection.asJavaType(javaClass.asJavaConstant()); - ResolvedJavaType otherType = constantReflection.asJavaType(otherClass.asJavaConstant()); - if (thisType != null && otherType != null) { - return ConstantNode.forBoolean(thisType.isAssignableFrom(otherType)); - } - } - return this; - } -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -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.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isInstance(Object)}. - * - * @see ClassSubstitutions#isInstance(Class, Object) - */ -@NodeInfo -public final class ClassIsInstanceNode extends MacroNode implements Canonicalizable { - - public ClassIsInstanceNode(Invoke invoke) { - super(invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - private ValueNode getObject() { - return arguments.get(1); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ValueNode object = getObject(); - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - if (type.isPrimitive()) { - return ConstantNode.forBoolean(false); - } - if (object.isConstant()) { - JavaConstant c = object.asJavaConstant(); - return ConstantNode.forBoolean(c.isNonNull() && type.isInstance(c)); - } - InstanceOfNode instanceOf = new InstanceOfNode(type, object, null); - return new ConditionalNode(instanceOf, ConstantNode.forBoolean(true), ConstantNode.forBoolean(false)); - } - } - return this; - } -} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Sat Feb 21 19:55:33 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,13 +33,15 @@ /** * {@link MacroNode Macro node} for {@link Class#isInterface()}. * - * @see ClassSubstitutions#isInterface(Class) + * @see HotSpotClassSubstitutions#isInterface(Class) */ @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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Sat Feb 21 19:55:33 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,13 +33,15 @@ /** * {@link MacroNode Macro node} for {@link Class#isPrimitive()}. * - * @see ClassSubstitutions#isPrimitive(Class) + * @see HotSpotClassSubstitutions#isPrimitive(Class) */ @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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadIndexedPointerNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubStartNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.replacements; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -35,18 +34,20 @@ @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() { return arguments.get(0); } - private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccess, Assumptions assumptions) { + private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccess) { if (getCallSite().isConstant() && !getCallSite().isNullConstant()) { HotSpotObjectConstant c = (HotSpotObjectConstant) getCallSite().asConstant(); - JavaConstant target = c.getCallSiteTarget(assumptions); + JavaConstant target = c.getCallSiteTarget(graph().getAssumptions()); if (target != null) { return ConstantNode.forConstant(target, metaAccess); } @@ -56,7 +57,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - ConstantNode target = getConstantCallTarget(tool.getMetaAccess(), tool.assumptions()); + ConstantNode target = getConstantCallTarget(tool.getMetaAccess()); if (target != null) { return target; } @@ -66,7 +67,7 @@ @Override public void lower(LoweringTool tool) { - ConstantNode target = getConstantCallTarget(tool.getMetaAccess(), tool.assumptions()); + ConstantNode target = getConstantCallTarget(tool.getMetaAccess()); if (target != null) { graph().replaceFixedWithFloating(this, target); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableAddressNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CardTableShiftNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 java.lang.reflect.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.hotspot.word.*; -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.word.*; - -/** - * Substitutions for {@link java.lang.Class} methods. - */ -@ClassSubstitution(java.lang.Class.class) -public class ClassSubstitutions { - - @MacroSubstitution(macro = ClassGetModifiersNode.class, isStatic = false) - @MethodSubstitution(isStatic = false, forced = true) - public static int getModifiers(final Class thisObj) { - KlassPointer klass = ClassGetHubNode.readClass(thisObj); - if (klass.isNull()) { - // Class for primitive type - return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; - } else { - return klass.readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION); - } - } - - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsInterfaceNode.class, isStatic = false) - @MethodSubstitution(isStatic = false, forced = true) - public static boolean isInterface(final Class thisObj) { - KlassPointer klass = ClassGetHubNode.readClass(thisObj); - if (klass.isNull()) { - return false; - } else { - int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); - return (accessFlags & Modifier.INTERFACE) != 0; - } - } - - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsArrayNode.class, isStatic = false) - @MethodSubstitution(isStatic = false, forced = true) - public static boolean isArray(final Class thisObj) { - KlassPointer klass = ClassGetHubNode.readClass(thisObj); - if (klass.isNull()) { - return false; - } else { - return klassIsArray(klass); - } - } - - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsPrimitiveNode.class, isStatic = false) - @MethodSubstitution(isStatic = false, forced = true) - public static boolean isPrimitive(final Class thisObj) { - KlassPointer klass = ClassGetHubNode.readClass(thisObj); - return klass.isNull(); - } - - @MacroSubstitution(macro = ClassGetClassLoader0Node.class, isStatic = false) - public static native ClassLoader getClassLoader0(Class thisObj); - - @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) - public static Class getSuperclass(final Class thisObj) { - KlassPointer klass = ClassGetHubNode.readClass(thisObj); - if (!klass.isNull()) { - int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); - if ((accessFlags & Modifier.INTERFACE) == 0) { - if (klassIsArray(klass)) { - return Object.class; - } else { - Word superKlass = klass.readWord(klassSuperKlassOffset(), KLASS_SUPER_KLASS_LOCATION); - if (superKlass.equal(0)) { - return null; - } else { - return readJavaMirror(superKlass); - } - } - } - } - return null; - } - - public static Class readJavaMirror(Word klass) { - return piCastExactNonNull(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION), Class.class); - } - - @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) - public static Class getComponentType(final Class thisObj) { - KlassPointer klass = ClassGetHubNode.readClass(thisObj); - if (!klass.isNull()) { - if (klassIsArray(klass)) { - return piCastExactNonNull(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class); - } - } - return null; - } - - @MacroSubstitution(macro = ClassIsInstanceNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) - public static boolean isInstance(Class thisObj, Object obj) { - return ConditionalNode.materializeIsInstance(thisObj, obj); - } - - @MacroSubstitution(macro = ClassIsAssignableFromNode.class, isStatic = false) - @MethodSubstitution(isStatic = false) - public static boolean isAssignableFrom(Class thisClass, Class otherClass) { - if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, otherClass == null)) { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); - return false; - } - GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode); - KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode); - if (thisHub.isNull() || otherHub.isNull()) { - // primitive types, only true if equal. - return thisClass == otherClass; - } - if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) { - return false; - } - return true; - } - - @MacroSubstitution(macro = ClassCastNode.class, isStatic = false) - public static native Object cast(final Class thisObj, Object obj); -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompilerToVMImplSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompilerToVMImplSubstitutions.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompilerToVMImplSubstitutions.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,6 +34,6 @@ @MethodSubstitution(isStatic = false) public static Class getJavaMirror(@SuppressWarnings("unused") CompilerToVMImpl impl, long metaspaceklass) { - return ClassSubstitutions.readJavaMirror(Word.unsigned(metaspaceklass)); + return HotSpotClassSubstitutions.readJavaMirror(Word.unsigned(metaspaceklass)); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 java.lang.reflect.*; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.word.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@link java.lang.Class} methods. + */ +@ClassSubstitution(java.lang.Class.class) +public class HotSpotClassSubstitutions { + + @MacroSubstitution(macro = ClassGetModifiersNode.class, isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) + public static int getModifiers(final Class thisObj) { + KlassPointer klass = ClassGetHubNode.readClass(thisObj); + if (klass.isNull()) { + // Class for primitive type + return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; + } else { + return klass.readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION); + } + } + + // This MacroSubstitution should be removed once non-null klass pointers can be optimized + @MacroSubstitution(macro = ClassIsInterfaceNode.class, isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) + public static boolean isInterface(final Class thisObj) { + KlassPointer klass = ClassGetHubNode.readClass(thisObj); + if (klass.isNull()) { + return false; + } else { + int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); + return (accessFlags & Modifier.INTERFACE) != 0; + } + } + + // This MacroSubstitution should be removed once non-null klass pointers can be optimized + @MacroSubstitution(macro = ClassIsArrayNode.class, isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) + public static boolean isArray(final Class thisObj) { + KlassPointer klass = ClassGetHubNode.readClass(thisObj); + if (klass.isNull()) { + return false; + } else { + return klassIsArray(klass); + } + } + + // This MacroSubstitution should be removed once non-null klass pointers can be optimized + @MacroSubstitution(macro = ClassIsPrimitiveNode.class, isStatic = false) + @MethodSubstitution(isStatic = false, forced = true) + public static boolean isPrimitive(final Class thisObj) { + KlassPointer klass = ClassGetHubNode.readClass(thisObj); + return klass.isNull(); + } + + @MacroSubstitution(macro = ClassGetClassLoader0Node.class, isStatic = false) + public static native ClassLoader getClassLoader0(Class thisObj); + + @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false) + @MethodSubstitution(isStatic = false) + public static Class getSuperclass(final Class thisObj) { + KlassPointer klass = ClassGetHubNode.readClass(thisObj); + if (!klass.isNull()) { + int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION); + if ((accessFlags & Modifier.INTERFACE) == 0) { + if (klassIsArray(klass)) { + return Object.class; + } else { + Word superKlass = klass.readWord(klassSuperKlassOffset(), KLASS_SUPER_KLASS_LOCATION); + if (superKlass.equal(0)) { + return null; + } else { + return readJavaMirror(superKlass); + } + } + } + } + return null; + } + + public static Class readJavaMirror(Word klass) { + return piCastExactNonNull(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION), Class.class); + } + + @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false) + @MethodSubstitution(isStatic = false) + public static Class getComponentType(final Class thisObj) { + KlassPointer klass = ClassGetHubNode.readClass(thisObj); + if (!klass.isNull()) { + if (klassIsArray(klass)) { + return piCastExactNonNull(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class); + } + } + return null; + } + + @MacroSubstitution(macro = ClassCastNode.class, isStatic = false) + public static native Object cast(final Class thisObj, Object obj); +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +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.hotspot.replacements; - -import static com.oracle.graal.java.GraphBuilderContext.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.common.type.*; -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.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Provider of HotSpot specific {@link GraphBuilderPlugin}s. - */ -@ServiceProvider(GraphBuilderPluginsProvider.class) -public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { - public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - Registration r = new Registration(plugins, metaAccess, Object.class); - r.register1("getClass", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { - ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp(); - ValueNode mirror; - if (objectStamp.isExactType() && objectStamp.nonNull()) { - mirror = builder.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), metaAccess)); - } else { - StampProvider stampProvider = builder.getStampProvider(); - LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, nullCheckedValue(builder, rcvr))); - mirror = builder.append(new HubGetClassNode(builder.getMetaAccess(), hub)); - } - builder.push(Kind.Object, mirror); - return true; - } - }); - } -} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Sat Feb 21 19:55:33 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.*; @@ -60,12 +58,9 @@ replacements.registerSubstitutions(System.class, SystemSubstitutions.class); replacements.registerSubstitutions(Thread.class, ThreadSubstitutions.class); replacements.registerSubstitutions(Unsafe.class, UnsafeSubstitutions.class); - replacements.registerSubstitutions(Class.class, ClassSubstitutions.class); + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java Sat Feb 21 19:55:33 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; - protected HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { - super(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Class.class)), null); + public HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { + super(TYPE, StampFactory.declaredNonNull(metaAccess.lookupJavaType(Class.class)), null); this.hub = hub; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -60,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)); } /** @@ -194,6 +204,25 @@ return trueValue; } + @Snippet + public static Object isAssignableFrom(Class thisClass, Class otherClass, Object trueValue, Object falseValue) { + if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, otherClass == null)) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); + return false; + } + GuardingNode anchorNode = SnippetAnchorNode.anchor(); + KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode); + KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode); + if (thisHub.isNull() || otherHub.isNull()) { + // primitive types, only true if equal. + return thisClass == otherClass ? trueValue : falseValue; + } + if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) { + return falseValue; + } + return trueValue; + } + static class Options { // @formatter:off @@ -214,6 +243,7 @@ private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary"); private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary"); private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic"); + private final SnippetInfo isAssignableFrom = snippet(InstanceOfSnippets.class, "isAssignableFrom"); private final long compilationThreshold; public Templates(HotSpotProviders providers, TargetDescription target, long compilationThreshold) { @@ -226,7 +256,8 @@ if (replacer.instanceOf instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf; ValueNode object = instanceOf.getValue(); - TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue()); + Assumptions assumptions = instanceOf.graph().getAssumptions(); + TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), assumptions, TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue()); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), instanceOf.graph()); @@ -263,8 +294,7 @@ } return args; - } else { - assert replacer.instanceOf instanceof InstanceOfDynamicNode; + } else if (replacer.instanceOf instanceof InstanceOfDynamicNode) { InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; ValueNode object = instanceOf.object(); @@ -274,6 +304,16 @@ args.add("trueValue", replacer.trueValue); args.add("falseValue", replacer.falseValue); return args; + } else if (replacer.instanceOf instanceof ClassIsAssignableFromNode) { + ClassIsAssignableFromNode isAssignable = (ClassIsAssignableFromNode) replacer.instanceOf; + Arguments args = new Arguments(isAssignableFrom, isAssignable.graph().getGuardsStage(), tool.getLoweringStage()); + args.add("thisClass", isAssignable.getThisClass()); + args.add("otherClass", isAssignable.getOtherClass()); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + return args; + } else { + throw GraalInternalError.shouldNotReachHere(); } } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Sat Feb 21 19:55:33 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,21 +26,26 @@ import java.lang.reflect.*; +import com.oracle.graal.api.code.*; 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; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; 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 @@ -68,9 +73,10 @@ } assert false : "unhandled array type " + type.getComponentType().getKind(); } else { - type = getConcreteType(getObject().stamp(), tool.assumptions(), tool.getMetaAccess()); + Assumptions assumptions = graph().getAssumptions(); + type = getConcreteType(getObject().stamp(), assumptions, tool.getMetaAccess()); if (type != null) { - StructuredGraph newGraph = new StructuredGraph(); + StructuredGraph newGraph = new StructuredGraph(AllowAssumptions.from(assumptions != null)); ParameterNode param = newGraph.unique(new ParameterNode(0, getObject().stamp())); NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); newGraph.addAfterFixed(newGraph.start(), newInstance); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyCallNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Sat Feb 21 19:55:33 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) { @@ -73,7 +76,7 @@ } // the canonicalization before loop unrolling is needed to propagate the length into // additions, etc. - PhaseContext context = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getLowerer(), tool.getReplacements(), tool.assumptions(), tool.getStampProvider()); + PhaseContext context = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getLowerer(), tool.getReplacements(), tool.getStampProvider()); new CanonicalizerPhase(true).apply(snippetGraph, context); new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(snippetGraph, context); new CanonicalizerPhase(true).apply(snippetGraph, context); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Sat Feb 21 19:55:33 2015 +0100 @@ -36,6 +36,7 @@ import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; @@ -190,7 +191,8 @@ Class[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = linkage.getOutgoingCallingConvention().getReturn().getKind() == Kind.Object; - StructuredGraph graph = new StructuredGraph(toString(), null); + StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO); + graph.disableInlinedMethodRecording(); GraphKit kit = new HotSpotGraphKit(graph, providers); ParameterNode[] params = createParameters(kit, args); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Sat Feb 21 19:55:33 2015 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.stubs; import static com.oracle.graal.compiler.GraalCompiler.*; -import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.util.*; @@ -40,6 +39,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*; @@ -157,6 +157,12 @@ if (code == null) { try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { final StructuredGraph graph = getGraph(); + + // Stubs cannot be recompiled so they cannot be compiled with + // assumptions and there is no point in recording evol_method dependencies + assert graph.getAssumptions() == null; + assert !graph.isInlinedMethodRecordingEnabled() : graph; + if (!(graph.start() instanceof StubStartNode)) { StubStartNode newStart = graph.add(new StubStartNode(Stub.this)); newStart.setStateAfter(graph.start().stateAfter()); @@ -170,12 +176,12 @@ compResult = new CompilationResult(toString()); try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) { - Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); Suites defaultSuites = providers.getSuites().getDefaultSuites(); Suites suites = new Suites(new PhaseSuite<>(), defaultSuites.getMidTier(), defaultSuites.getLowTier()); - SchedulePhase schedule = emitFrontEnd(providers, target, graph, assumptions, null, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, - getProfilingInfo(graph), null, suites); - emitBackEnd(graph, Stub.this, incomingCc, getInstalledCodeOwner(), backend, target, compResult, CompilationResultBuilderFactory.Default, assumptions, schedule, getRegisterConfig()); + SchedulePhase schedule = emitFrontEnd(providers, target, graph, null, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), + null, suites); + LIRSuites lirSuites = providers.getSuites().getDefaultLIRSuites(); + emitBackEnd(graph, Stub.this, incomingCc, getInstalledCodeOwner(), backend, target, compResult, CompilationResultBuilderFactory.Default, schedule, getRegisterConfig(), lirSuites); } catch (Throwable e) { throw Debug.handle(e); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/PointerCastNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,6 +24,7 @@ package com.oracle.graal.java; import static com.oracle.graal.api.code.TypeCheckHints.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import java.util.*; @@ -36,6 +37,7 @@ 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.*; @@ -73,18 +75,25 @@ 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; } @@ -109,7 +118,7 @@ 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); } @@ -563,7 +572,7 @@ } 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()); @@ -604,9 +613,19 @@ protected abstract T createNewInstance(ResolvedJavaType type, boolean fillContents); + @SuppressWarnings("unchecked") void genNewInstance(int cpi) { JavaType type = lookupType(cpi, NEW); if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { + ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes(); + if (skippedExceptionTypes != null) { + for (ResolvedJavaType exceptionType : skippedExceptionTypes) { + if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) { + append((T) new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); + return; + } + } + } frameState.apush(append(createNewInstance((ResolvedJavaType) type, true))); } else { handleUnresolvedNewInstance(type); @@ -688,7 +707,7 @@ Kind kind = field.getKind(); T receiver = frameState.apop(); if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); + LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ValueNode) receiver, (ResolvedJavaField) field)) { appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field)); } @@ -707,7 +726,7 @@ protected void emitExplicitExceptions(T receiver, T outOfBoundsIndex) { assert receiver != null; - if (graphBuilderConfig.omitAllExceptionEdges() || + if (graphBuilderConfig.omitAllExceptionEdges() || profilingInfo == null || (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) { return; } @@ -737,7 +756,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)); } @@ -786,7 +805,7 @@ 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 { @@ -831,9 +850,9 @@ Map bciToBlockSuccessorIndex = new HashMap<>(); for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { - assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessors().get(i).startBci); - if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessors().get(i).startBci)) { - bciToBlockSuccessorIndex.put(currentBlock.getSuccessors().get(i).startBci, new SuccessorInfo(i)); + assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci); + if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) { + bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); } } @@ -842,12 +861,13 @@ int[] keySuccessors = new int[nofCases + 1]; int deoptSuccessorIndex = -1; int nextSuccessorIndex = 0; + boolean constantValue = ((ValueNode) 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); @@ -858,7 +878,7 @@ SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); if (info.actualIndex < 0) { info.actualIndex = nextSuccessorIndex++; - actualSuccessors.add(currentBlock.getSuccessors().get(info.blockIndex)); + actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex)); } keySuccessors[i] = info.actualIndex; } @@ -890,6 +910,10 @@ } protected double branchProbability() { + if (profilingInfo == null) { + return 0.5; + } + assert assertAtIfBytecode(); double probability = profilingInfo.getBranchTakenProbability(bci()); if (probability < 0) { assert probability == -1 : "invalid probability"; @@ -907,6 +931,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) { @@ -1137,10 +1186,11 @@ 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Sat Feb 21 19:55:33 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 @@ -31,10 +31,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.cfg.*; 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 @@ -75,25 +72,17 @@ */ public final class BciBlockMapping { - public static class BciBlock extends AbstractBlockBase implements Cloneable { + public static class BciBlock implements Cloneable { + protected int id; public int startBci; public int endBci; public boolean isExceptionEntry; public boolean isLoopHeader; public int loopId; public int loopEnd; - - /** - * XXX to be removed - currently only used by baseline compiler. - */ - public Loop loop; - public boolean isLoopEnd; - - private FixedWithNextNode firstInstruction; - private AbstractFrameStateBuilder entryState; - private FixedWithNextNode[] firstInstructionArray; - private AbstractFrameStateBuilder[] entryStateArray; + protected List successors; + private int predecessorCount; private boolean visited; private boolean active; @@ -128,6 +117,14 @@ return null; } + public int getId() { + return id; + } + + public int getPredecessorCount() { + return this.predecessorCount; + } + public int numNormalSuccessors() { if (exceptionDispatchBlock() != null) { return successors.size() - 1; @@ -165,14 +162,6 @@ return sb.toString(); } - public Loop getLoop() { - return loop; - } - - public void setLoop(Loop loop) { - this.loop = loop; - } - public int getLoopDepth() { return Long.bitCount(loops); } @@ -181,10 +170,6 @@ return isLoopHeader; } - public boolean isLoopEnd() { - return isLoopEnd; - } - public boolean isExceptionEntry() { return isExceptionEntry; } @@ -258,7 +243,7 @@ return jsrData; } - public void setEndsWithRet() { + void setEndsWithRet() { getOrCreateJSRData().endsWithRet = true; } @@ -278,7 +263,7 @@ } } - public void setRetSuccessor(BciBlock bciBlock) { + void setRetSuccessor(BciBlock bciBlock) { this.getOrCreateJSRData().retSuccessor = bciBlock; } @@ -321,76 +306,40 @@ } } - 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 int getSuccessorCount() { + return successors.size(); + } + + public List getSuccessors() { + return successors; } - 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; - } + void setId(int i) { + this.id = i; } - 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 addSuccessor(BciBlock sux) { + successors.add(sux); + sux.predecessorCount++; } - 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 void clearSucccessors() { + for (BciBlock sux : successors) { + sux.predecessorCount--; } + successors.clear(); } } @@ -408,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"); } } @@ -494,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) @@ -512,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; } @@ -528,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; } @@ -556,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: @@ -583,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: { @@ -600,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; } @@ -626,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); } } } @@ -638,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(); @@ -654,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; @@ -670,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++) { @@ -678,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()); @@ -739,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--) { @@ -767,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); } @@ -781,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 @@ -801,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]); @@ -813,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) { @@ -831,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; } @@ -858,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(" :"); @@ -976,7 +924,6 @@ loops |= computeBlockOrder(successor); if (successor.active) { // Reached block via backward branch. - block.isLoopEnd = true; loops |= (1L << successor.loopId); } } @@ -995,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) { @@ -1009,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; @@ -1024,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)")); } @@ -1266,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +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); - } - - @Override - public String toString() { - return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); - } -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,30 +22,48 @@ */ package com.oracle.graal.java; -import java.util.function.*; - +import com.oracle.graal.lir.phases.*; import com.oracle.graal.options.*; +import com.oracle.graal.options.DerivedOptionValue.OptionSupplier; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; -public class DefaultSuitesProvider implements SuitesProvider, Supplier { +public class DefaultSuitesProvider implements SuitesProvider { private final DerivedOptionValue defaultSuites; private final PhaseSuite defaultGraphBuilderSuite; + private final DerivedOptionValue defaultLIRSuites; + + private class SuitesSupplier implements OptionSupplier { + + private static final long serialVersionUID = 2677805381215454728L; + + public Suites get() { + return createSuites(); + } + + } + + private class LIRSuitesSupplier implements OptionSupplier { + + private static final long serialVersionUID = 312070237227476252L; + + public LIRSuites get() { + return createLIRSuites(); + } + + } public DefaultSuitesProvider() { this.defaultGraphBuilderSuite = createGraphBuilderSuite(); - this.defaultSuites = new DerivedOptionValue<>(this::createSuites); + this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); + this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); } public Suites getDefaultSuites() { return defaultSuites.getValue(); } - public Suites get() { - return createSuites(); - } - public Suites createSuites() { return Suites.createDefaultSuites(); } @@ -60,4 +78,12 @@ return suite; } + public LIRSuites getDefaultLIRSuites() { + return defaultLIRSuites.getValue(); + } + + public LIRSuites createLIRSuites() { + return Suites.createDefaultLIRSuites(); + } + } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,8 +24,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; /** @@ -41,6 +43,8 @@ T append(T value); + T append(T value); + StampProvider getStampProvider(); MetaAccessProvider getMetaAccess(); @@ -49,8 +53,17 @@ ConstantReflectionProvider getConstantReflection(); + SnippetReflectionProvider getSnippetReflection(); + 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) */ @@ -61,4 +74,8 @@ } return nonNullValue; } + + GuardingNode getCurrentBlockGuard(); + + BailoutException bailout(String string); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,27 +26,32 @@ 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.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.common.*; 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.*; @@ -64,31 +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(), context.getAssumptions(), 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,11 +92,10 @@ private ResolvedJavaMethod rootMethod; private final GraphBuilderConfiguration graphBuilderConfig; - private final GraphBuilderPlugins graphBuilderPlugins; private final OptimisticOptimizations optimisticOpts; private final StampProvider stampProvider; - private final Assumptions assumptions; private final ConstantReflectionProvider constantReflection; + private final SnippetReflectionProvider snippetReflectionProvider; /** * Gets the graph being processed by this builder. @@ -111,21 +104,20 @@ return currentGraph; } - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, - GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) { + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, ConstantReflectionProvider constantReflection, + GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; this.stampProvider = stampProvider; - this.assumptions = assumptions; - this.graphBuilderPlugins = graphBuilderPlugins; this.constantReflection = constantReflection; + this.snippetReflectionProvider = snippetReflectionProvider; assert metaAccess != null; } - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, - GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - this(metaAccess, stampProvider, assumptions, constantReflection, graphBuilderConfig, null, optimisticOpts); + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, + OptimisticOptimizations optimisticOpts) { + this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, optimisticOpts); } @Override @@ -135,17 +127,17 @@ 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)) { + for (ParameterNode param : currentGraph.getNodes(ParameterNode.TYPE)) { if (param.hasNoUsages()) { assert param.inputs().isEmpty(); param.safeDelete(); @@ -182,7 +174,7 @@ 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 +184,6 @@ private int currentLineNumber; private ValueNode methodSynchronizedObject; - private ExceptionDispatchBlock unwindBlock; - private BciBlock returnBlock; private ValueNode returnValue; private FixedWithNextNode beforeReturnNode; @@ -204,9 +194,21 @@ private final boolean explodeLoops; 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()) { @@ -240,7 +242,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,19 +250,31 @@ 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)); } else { - frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true); + frameState.clearNonLiveLocals(startBlock, liveness, true); assert bci() == 0; startNode.setStateAfter(frameState.create(bci())); } @@ -270,7 +284,7 @@ // 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())); } @@ -279,12 +293,12 @@ 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,11 +307,10 @@ BciBlock block = blocks[index]; index = iterateBlock(blocks, block); } - processBlock(this, returnBlock); - processBlock(this, unwindBlock); - Debug.dump(currentGraph, "After bytecode parsing"); - + if (Debug.isDumpEnabled() && this.beforeReturnNode != startInstruction) { + Debug.dump(currentGraph, "Bytecodes parsed: " + method.getDeclaringClass().getUnqualifiedName() + "." + method.getName()); + } } } @@ -332,12 +345,10 @@ if (context.targetPeelIteration != -1) { // We were reaching the backedge during explosion. Explode further. - Debug.dump(currentGraph, "Before loop explosion " + context.targetPeelIteration); context.peelIteration = context.targetPeelIteration; context.targetPeelIteration = -1; } else { // We did not reach the backedge. Exit. - Debug.dump(currentGraph, "after loop explosion " + context.peelIteration); break; } } @@ -345,27 +356,6 @@ 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; - } - /** * @param type the unresolved type of the constant */ @@ -472,7 +462,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(); /* @@ -481,7 +471,7 @@ * unwind immediately. */ if (bci != currentBlock.endBci || dispatchBlock == null) { - dispatchBlock = unwindBlock(); + dispatchBlock = blockMap.getUnwindBlock(); } HIRFrameStateBuilder dispatchState = frameState.copy(); @@ -499,6 +489,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); @@ -522,32 +513,32 @@ @Override protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) { - return new SubNode(x, y); + return SubNode.create(x, y); } @Override protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) { - return new MulNode(x, y); + return MulNode.create(x, y); } @Override protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new AddNode(x, y); + return AddNode.create(x, y); } @Override protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new SubNode(x, y); + return SubNode.create(x, y); } @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 @@ -587,62 +578,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); } @@ -664,12 +655,12 @@ @Override protected ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck) { - return new CheckCastNode(type, object, profileForTypeCheck, forStoreCheck); + return CheckCastNode.create(type, object, profileForTypeCheck, forStoreCheck, currentGraph.getAssumptions()); } @Override protected ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck) { - return new InstanceOfNode(type, object, profileForTypeCheck); + return InstanceOfNode.create(type, object, profileForTypeCheck); } @Override @@ -832,7 +823,7 @@ InvokeKind invokeKind = initialInvokeKind; if (initialInvokeKind.isIndirect()) { ResolvedJavaType contextType = this.frameState.method.getDeclaringClass(); - ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, assumptions, contextType); + ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, contextType); if (specialCallTarget != null) { invokeKind = InvokeKind.Special; targetMethod = specialCallTarget; @@ -852,22 +843,27 @@ } 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)) { - 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)) { - parseAndInlineCallee(targetMethod, args); + if (tryAnnotatedInvocationPlugin(args, targetMethod)) { + if (GraalOptions.TraceInlineDuringParsing.getValue()) { + TTY.println(format("%sUsed annotated invocation plugin for %s", nSpaces(currentDepth), targetMethod)); + } + return; + } + + if (tryInline(args, targetMethod, invokeKind, returnType)) { return; } @@ -875,7 +871,7 @@ // 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); @@ -885,16 +881,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"; @@ -903,6 +900,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) { @@ -915,10 +917,36 @@ 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()); } @@ -940,8 +968,22 @@ 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())); } + + // Record inlined method dependency in the graph + if (currentGraph.isInlinedMethodRecordingEnabled()) { + currentGraph.getInlinedMethods().add(targetMethod); + } } protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) { @@ -964,17 +1006,28 @@ @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)); } } @@ -985,7 +1038,7 @@ synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x); if (frameState.lockDepth() != 0) { - throw new BailoutException("unbalanced monitors"); + throw bailout("unbalanced monitors"); } } @@ -1002,7 +1055,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; @@ -1022,7 +1075,7 @@ } ConstantNode nextBciNode = getJsrConstant(nextBci); frameState.push(Kind.Int, nextBciNode); - appendGoto(createTarget(successor, frameState)); + appendGoto(successor); } @Override @@ -1038,7 +1091,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) { @@ -1050,10 +1103,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)); + } } } @@ -1063,8 +1129,13 @@ return ConstantNode.forConstant(constant, metaAccess, currentGraph); } + @SuppressWarnings("unchecked") @Override - protected ValueNode append(ValueNode v) { + public ValueNode append(ValueNode v) { + if (v.graph() != null) { + // This node was already appended to the graph. + return v; + } if (v instanceof ControlSinkNode) { return append((ControlSinkNode) v); } @@ -1108,6 +1179,9 @@ } public T append(T v) { + if (v.graph() != null) { + return v; + } T added = currentGraph.unique(v); return added; } @@ -1124,7 +1198,7 @@ do { long lMask = 1L << pos; if ((exits & lMask) != 0) { - exitLoops.add(loopHeaders[pos]); + exitLoops.add(blockMap.getLoopHeader(pos)); exits &= ~lMask; } pos++; @@ -1144,7 +1218,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); @@ -1153,8 +1227,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, (HIRFrameStateBuilder) getEntryState(loop, this.getCurrentDimension())); loopExit.setStateAfter(newState.create(bci)); } @@ -1165,6 +1239,98 @@ return new Target(target, state); } + private AbstractFrameStateBuilder getEntryState(BciBlock block, int dimension) { + int id = block.id; + if (dimension == 0) { + return entryStateArray[id]; + } else { + return getEntryStateMultiDimension(dimension, id); + } + } + + private AbstractFrameStateBuilder getEntryStateMultiDimension(int dimension, int id) { + if (entryStateMatrix != null && dimension - 1 < entryStateMatrix.length) { + AbstractFrameStateBuilder[] 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)) { @@ -1176,94 +1342,71 @@ } private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) { + return createTarget(block, state, false); + } + + private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state, boolean isGoto) { 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); - // 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 (isGoto && (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 ? 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 (!((HIRFrameStateBuilder) 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); + ((HIRFrameStateBuilder) 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 getFirstInstruction(block, operatingDimension).next() == null : "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. */ - AbstractBeginNode placeholder = (AbstractBeginNode) block.getFirstInstruction(operatingDimension); + AbstractBeginNode placeholder = (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(); @@ -1278,22 +1421,63 @@ 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); + ((HIRFrameStateBuilder) 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) { + if (this.explodeLoops && this.explodeLoopsContext != null && !this.explodeLoopsContext.isEmpty()) { + return findOperatingDimensionWithLoopExplosion(block); + } + return this.getCurrentDimension(); + } + + private int findOperatingDimensionWithLoopExplosion(BciBlock block) { + 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 > 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; + } 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. @@ -1317,33 +1501,37 @@ 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) { + if (block == null || getFirstInstruction(block, this.getCurrentDimension()) == 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, getFirstInstruction(block, this.getCurrentDimension()), block.isLoopHeader)) { - lastInstr = block.getFirstInstruction(this.getCurrentDimension()); - frameState = (HIRFrameStateBuilder) block.getEntryState(this.getCurrentDimension()); + lastInstr = getFirstInstruction(block, this.getCurrentDimension()); + frameState = (HIRFrameStateBuilder) getEntryState(block, this.getCurrentDimension()); parser.setCurrentFrameState(frameState); currentBlock = block; if (lastInstr instanceof AbstractMergeNode) { - int bci = block.startBci; - if (block instanceof ExceptionDispatchBlock) { - bci = ((ExceptionDispatchBlock) block).deoptBci; + + AbstractMergeNode abstractMergeNode = (AbstractMergeNode) lastInstr; + if (abstractMergeNode.stateAfter() == null) { + int bci = block.startBci; + if (block instanceof ExceptionDispatchBlock) { + bci = ((ExceptionDispatchBlock) block).deoptBci; + } + abstractMergeNode.setStateAfter(frameState.create(bci)); } - ((AbstractMergeNode) lastInstr).setStateAfter(frameState.create(bci)); } - if (block == returnBlock) { + if (block == blockMap.getReturnBlock()) { 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) { + } else if (block == blockMap.getUnwindBlock()) { if (currentDepth == 0) { frameState.setRethrowException(false); createUnwind(); @@ -1375,7 +1563,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); @@ -1407,7 +1595,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; } @@ -1420,7 +1608,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); @@ -1431,7 +1619,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(); @@ -1447,9 +1635,10 @@ } } - private void appendGoto(FixedNode target) { - if (lastInstr != null) { - lastInstr.setNext(target); + private void appendGoto(BciBlock successor) { + FixedNode targetInstr = createTarget(successor, frameState, true); + if (lastInstr != null && lastInstr != targetInstr) { + lastInstr.setNext(targetInstr); } } @@ -1462,7 +1651,8 @@ 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()); + controlFlowSplit = true; + EndNode preLoopEnd = currentGraph.add(new EndNode()); LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); lastInstr.setNext(preLoopEnd); // Add the single non-loop predecessor of the loop header. @@ -1478,12 +1668,12 @@ * 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); } @@ -1509,8 +1699,8 @@ // 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"); @@ -1547,7 +1737,7 @@ 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; } } @@ -1573,10 +1763,11 @@ } } - private void traceState() { + private boolean traceState() { if (Debug.isEnabled() && Options.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) { traceStateHelper(); } + return true; } private void traceStateHelper() { @@ -1593,18 +1784,14 @@ @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)); + appendGoto(trueBlock); return; } - double probability = branchProbability(); - // the mirroring and negation operations get the condition into canonical form boolean mirror = cond.canonicalMirror(); boolean negate = cond.canonicalNegate(); @@ -1612,7 +1799,7 @@ ValueNode a = mirror ? y : x; ValueNode b = mirror ? x : y; - ValueNode condition; + LogicNode condition; assert !a.getKind().isNumericFloat(); if (cond == Condition.EQ || cond == Condition.NE) { if (a.getKind() == Kind.Object) { @@ -1624,7 +1811,12 @@ assert a.getKind() != Kind.Object && !cond.isUnsigned(); condition = genIntegerLessThan(a, b); } - condition = genUnique(condition); + + if (condition instanceof LogicNegationNode) { + LogicNegationNode logicNegationNode = (LogicNegationNode) condition; + negate = !negate; + condition = logicNegationNode.getValue(); + } if (condition instanceof LogicConstantNode) { LogicConstantNode constantLogicNode = (LogicConstantNode) condition; @@ -1636,8 +1828,57 @@ if (value) { nextBlock = trueBlock; } - appendGoto(createTarget(nextBlock, frameState)); + appendGoto(nextBlock); } else { + + if (condition.graph() == null) { + condition = currentGraph.unique(condition); + } + + // Need to get probability based on current bci. + double probability = branchProbability(); + + int oldBci = stream.currentBCI(); + int trueBlockInt = checkPositiveIntConstantPushed(trueBlock); + if (trueBlockInt != -1) { + int falseBlockInt = checkPositiveIntConstantPushed(falseBlock); + if (falseBlockInt != -1) { + + boolean genReturn = false; + boolean genConditional = false; + if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) { + genConditional = true; + } else if (this.currentDepth != 0 && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) { + genReturn = true; + genConditional = true; + } + + if (genConditional) { + ConstantNode trueValue = currentGraph.unique(ConstantNode.forInt(trueBlockInt)); + ConstantNode falseValue = currentGraph.unique(ConstantNode.forInt(falseBlockInt)); + if (negate) { + ConstantNode tmp = falseValue; + falseValue = trueValue; + trueValue = tmp; + } + 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); + } + return; + } + } + } + + this.controlFlowSplit = true; + ValueNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState); ValueNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState); @@ -1646,6 +1887,32 @@ } } + 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; + } + + 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() { return stampProvider; } @@ -1655,7 +1922,7 @@ } public Assumptions getAssumptions() { - return assumptions; + return currentGraph.getAssumptions(); } public void push(Kind kind, ValueNode value) { @@ -1675,6 +1942,37 @@ return constantReflection; } + public SnippetReflectionProvider getSnippetReflection() { + 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 = this.frameState.create(bci()); + StackTraceElement[] elements = GraphUtil.approxSourceStackTraceElement(currentFrameState); + BailoutException bailout = new BailoutException(string); + throw GraphUtil.createBailoutException(string, bailout, elements); + } } } + + static String nSpaces(int n) { + return n == 0 ? "" : format("%" + n + "s", ""); + } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,14 +22,141 @@ */ 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 GraphBuilderPluginsProvider - * @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); + } + + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,299 +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); -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +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 com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; - -/** - * Interface for providers of {@link GraphBuilderPlugin}s. - */ -public interface GraphBuilderPluginsProvider extends Service { - /** - * Registers the plugins provided by this object. - */ - void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins); -} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Sat Feb 21 19:55:33 2015 +0100 @@ -31,8 +31,7 @@ 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.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -54,8 +53,8 @@ * @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) { + super(method, checkTypes); assert graph != null; @@ -70,14 +69,14 @@ 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++; } @@ -96,7 +95,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,7 +121,7 @@ if (param == null) { param = new ParameterNode(index, stamp); } - storeLocal(javaIndex, graph.unique(param)); + locals[javaIndex] = graph.unique(param); javaIndex += kind.getSlotCount(); index++; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +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.api.runtime.*; -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. - */ -@ServiceProvider(GraphBuilderPluginsProvider.class) -public class StandardGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { - public 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) { - builder.push(kind.getStackKind(), builder.append(new UnboxNode(nullCheckedValue(builder, value), kind))); - 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; /** * Base class for the JTT tests. @@ -56,8 +57,8 @@ } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m) { - StructuredGraph graph = super.parseEager(m); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + StructuredGraph graph = super.parseEager(m, allowAssumptions); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6753639.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/LongToSomethingArray01.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,7 +28,7 @@ /** * inspired by java.security.SecureRandom.longToByteArray(long). - * + * */ public class LongToSomethingArray01 extends JTTTest { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BreakpointOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64CCall.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Sat Feb 21 19:55:33 2015 +0100 @@ -36,7 +36,7 @@ * *
      *   Base       Contents
    - * 
    + *
      *            :                                :  -----
      *   caller   | incoming overflow argument n   |    ^
      *   frame    :     ...                        :    | positive
    diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -56,13 +56,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;
    @@ -78,7 +80,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;
    @@ -91,6 +94,7 @@
             }
     
             public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.result = result;
                 this.x = x;
    @@ -113,7 +117,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;
    @@ -126,6 +131,7 @@
             }
     
             public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, Value x, JavaConstant y, LIRFrameState state) {
    +            super(TYPE);
                 this.opcode = opcode;
                 this.result = result;
                 this.x = x;
    @@ -148,7 +154,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;
    @@ -159,6 +166,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;
    @@ -183,7 +191,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;
    @@ -191,6 +200,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;
    @@ -835,7 +845,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;
    @@ -844,6 +855,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java	Sat Feb 21 19:55:33 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
    @@ -46,7 +46,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;
    @@ -63,6 +64,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -41,7 +41,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,
    @@ -57,6 +58,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Sat Feb 21 19:55:33 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
    @@ -34,7 +34,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
    @@ -47,6 +48,7 @@
         @Use({REG, STACK}) protected Value[] parameters;
     
         public SPARCBreakpointOp(Value[] parameters) {
    +        super(TYPE);
             this.parameters = parameters;
         }
     
    diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Sat Feb 21 19:55:33 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
    @@ -41,13 +41,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;
    @@ -62,27 +64,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);
    @@ -122,12 +129,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;
             }
     
    @@ -144,11 +153,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;
             }
     
    @@ -159,10 +169,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
    @@ -172,10 +183,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -40,13 +40,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Sat Feb 21 19:55:33 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,11 +42,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;
             }
     
    @@ -62,7 +64,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;
    @@ -83,6 +86,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;
    @@ -348,7 +352,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);
             // TODO: Condition code/flag handling needs to be improved;
             protected final Condition condition;
             protected final ConditionFlag conditionFlag;
    @@ -358,6 +363,7 @@
             protected final boolean unorderedIsTrue;
     
             public BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind) {
    +            super(TYPE);
                 this.conditionFlag = condition;
                 this.trueDestination = trueDestination;
                 this.falseDestination = falseDestination;
    @@ -367,6 +373,7 @@
             }
     
             public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind) {
    +            super(TYPE);
                 this.condition = condition;
                 this.trueDestination = trueDestination;
                 this.falseDestination = falseDestination;
    @@ -376,6 +383,7 @@
             }
     
             public BranchOp(Condition finalCondition, LabelRef trueDestination, LabelRef falseDestination, Kind kind, boolean unorderedIsTrue) {
    +            super(TYPE);
                 this.trueDestination = trueDestination;
                 this.falseDestination = falseDestination;
                 this.kind = kind;
    @@ -517,7 +525,8 @@
             }
         }
     
    -    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;
    @@ -526,6 +535,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;
    @@ -583,7 +593,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;
    @@ -592,6 +603,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;
    @@ -655,7 +667,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;
     
    @@ -667,6 +680,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -35,7 +35,7 @@
      *
      * 
      *   Base       Contents
    - * 
    + *
      *            :                                :  -----
      *   caller   | incoming overflow argument n   |    ^
      *   frame    :     ...                        :    | positive
    diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java	Sat Feb 21 19:55:33 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
    @@ -29,12 +29,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Sat Feb 21 19:55:33 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.*;
     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,
    @@ -48,6 +49,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Sat Feb 21 19:55:33 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
    @@ -74,11 +74,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;
             }
    @@ -100,12 +102,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;
             }
    @@ -130,14 +134,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;
    @@ -224,13 +229,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;
             }
    @@ -277,12 +283,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;
    @@ -304,12 +312,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;
             }
     
    @@ -356,12 +365,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;
             }
    @@ -373,12 +384,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;
             }
    @@ -393,11 +406,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;
             }
     
    @@ -407,12 +422,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;
             }
    @@ -434,7 +451,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;
    @@ -442,6 +460,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;
    @@ -455,12 +474,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;
             }
    @@ -491,11 +512,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;
             }
     
    @@ -540,12 +562,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Sat Feb 21 19:55:33 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
    @@ -42,6 +42,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.
    @@ -66,6 +67,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Sat Feb 21 19:55:33 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,14 +30,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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest3.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -26,87 +26,98 @@
     
     import java.util.*;
     
    +import com.oracle.graal.api.code.*;
    +import com.oracle.graal.compiler.common.cfg.*;
     import com.oracle.graal.debug.*;
    -import com.oracle.graal.compiler.common.cfg.*;
    +import com.oracle.graal.lir.gen.*;
    +import com.oracle.graal.lir.phases.*;
     
     /**
      * This class performs basic optimizations on the control flow graph after LIR generation.
      */
    -public final class ControlFlowOptimizer {
    +public final class ControlFlowOptimizer extends PostAllocationOptimizationPhase {
     
         /**
          * Performs control flow optimizations on the given LIR graph.
          */
    -    public static > void optimize(LIR lir, List codeEmittingOrder) {
    -        ControlFlowOptimizer.deleteEmptyBlocks(lir, codeEmittingOrder);
    -    }
    -
    -    private ControlFlowOptimizer() {
    -    }
    -
    -    private static final DebugMetric BLOCKS_DELETED = Debug.metric("BlocksDeleted");
    -
    -    /**
    -     * Checks whether a block can be deleted. Only blocks with exactly one successor and an
    -     * unconditional branch to this successor are eligable.
    -     *
    -     * @param block the block checked for deletion
    -     * @return whether the block can be deleted
    -     */
    -    private static boolean canDeleteBlock(LIR lir, AbstractBlock block) {
    -        if (block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getSuccessors().iterator().next() == block) {
    -            return false;
    -        }
    -
    -        List instructions = lir.getLIRforBlock(block);
    -
    -        assert instructions.size() >= 2 : "block must have label and branch";
    -        assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label";
    -        assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch";
    -        assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.getLIRforBlock(block.getSuccessors().iterator().next()).get(0)).getLabel() : "branch target must be the successor";
    -
    -        // Block must have exactly one successor.
    -        return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState() && !block.isExceptionEntry();
    +    @Override
    +    protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) {
    +        LIR lir = lirGenRes.getLIR();
    +        new Optimizer(lir).deleteEmptyBlocks(codeEmittingOrder);
         }
     
    -    private static void alignBlock(LIR lir, AbstractBlock block) {
    -        if (!block.isAligned()) {
    -            block.setAlign(true);
    +    private static final class Optimizer> {
    +
    +        private final LIR lir;
    +
    +        private Optimizer(LIR lir) {
    +            this.lir = lir;
    +        }
    +
    +        private static final DebugMetric BLOCKS_DELETED = Debug.metric("BlocksDeleted");
    +
    +        /**
    +         * Checks whether a block can be deleted. Only blocks with exactly one successor and an
    +         * unconditional branch to this successor are eligable.
    +         *
    +         * @param block the block checked for deletion
    +         * @return whether the block can be deleted
    +         */
    +        private boolean canDeleteBlock(B block) {
    +            if (block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getSuccessors().iterator().next() == block) {
    +                return false;
    +            }
    +
                 List instructions = lir.getLIRforBlock(block);
    +
    +            assert instructions.size() >= 2 : "block must have label and branch";
                 assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label";
    -            StandardOp.LabelOp label = (StandardOp.LabelOp) instructions.get(0);
    -            instructions.set(0, new StandardOp.LabelOp(label.getLabel(), true));
    +            assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch";
    +            assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.getLIRforBlock(block.getSuccessors().iterator().next()).get(0)).getLabel() : "branch target must be the successor";
    +
    +            // Block must have exactly one successor.
    +            return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState() && !block.isExceptionEntry();
    +        }
    +
    +        private void alignBlock(B block) {
    +            if (!block.isAligned()) {
    +                block.setAlign(true);
    +                List instructions = lir.getLIRforBlock(block);
    +                assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label";
    +                StandardOp.LabelOp label = (StandardOp.LabelOp) instructions.get(0);
    +                instructions.set(0, new StandardOp.LabelOp(label.getLabel(), true));
    +            }
    +        }
    +
    +        private void deleteEmptyBlocks(List blocks) {
    +            assert verifyBlocks(lir, blocks);
    +            Iterator iterator = blocks.iterator();
    +            while (iterator.hasNext()) {
    +                B block = iterator.next();
    +                if (canDeleteBlock(block)) {
    +                    // adjust successor and predecessor lists
    +                    B other = block.getSuccessors().iterator().next();
    +                    for (AbstractBlock pred : block.getPredecessors()) {
    +                        Collections.replaceAll(pred.getSuccessors(), block, other);
    +                    }
    +                    for (int i = 0; i < other.getPredecessorCount(); i++) {
    +                        if (other.getPredecessors().get(i) == block) {
    +                            other.getPredecessors().remove(i);
    +                            other.getPredecessors().addAll(i, block.getPredecessors());
    +                        }
    +                    }
    +                    block.getSuccessors().clear();
    +                    block.getPredecessors().clear();
    +
    +                    if (block.isAligned()) {
    +                        alignBlock(other);
    +                    }
    +
    +                    BLOCKS_DELETED.increment();
    +                    iterator.remove();
    +                }
    +            }
    +            assert verifyBlocks(lir, blocks);
             }
         }
    -
    -    private static > void deleteEmptyBlocks(LIR lir, List blocks) {
    -        assert verifyBlocks(lir, blocks);
    -        Iterator iterator = blocks.iterator();
    -        while (iterator.hasNext()) {
    -            T block = iterator.next();
    -            if (canDeleteBlock(lir, block)) {
    -                // adjust successor and predecessor lists
    -                T other = block.getSuccessors().iterator().next();
    -                for (AbstractBlock pred : block.getPredecessors()) {
    -                    Collections.replaceAll(pred.getSuccessors(), block, other);
    -                }
    -                for (int i = 0; i < other.getPredecessorCount(); i++) {
    -                    if (other.getPredecessors().get(i) == block) {
    -                        other.getPredecessors().remove(i);
    -                        other.getPredecessors().addAll(i, block.getPredecessors());
    -                    }
    -                }
    -                block.getSuccessors().clear();
    -                block.getPredecessors().clear();
    -
    -                if (block.isAligned()) {
    -                    alignBlock(lir, other);
    -                }
    -
    -                BLOCKS_DELETED.increment();
    -                iterator.remove();
    -            }
    -        }
    -        assert verifyBlocks(lir, blocks);
    -    }
     }
    diff -r 82b5899f20cb -r db19eba20b9c 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	Sat Feb 21 19:47:33 2015 +0100
    +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Sat Feb 21 19:55:33 2015 +0100
    @@ -24,34 +24,36 @@
     
     import java.util.*;
     
    +import com.oracle.graal.api.code.*;
     import com.oracle.graal.compiler.common.cfg.*;
     import com.oracle.graal.lir.StandardOp.MoveOp;
    +import com.oracle.graal.lir.gen.*;
    +import com.oracle.graal.lir.phases.*;
     
     /**
      * This class optimizes moves, particularly those that result from eliminating SSA form.
    - *
    + * 

    * When a block has more than one predecessor, and all predecessors end with the - * {@linkplain #same(LIRInstruction, LIRInstruction) same} sequence of {@linkplain MoveOp move} - * instructions, then these sequences can be replaced with a single copy of the sequence at the - * beginning of the block. - * + * {@linkplain Optimizer#same(LIRInstruction, LIRInstruction) same} sequence of {@linkplain MoveOp + * move} instructions, then these sequences can be replaced with a single copy of the sequence at + * the beginning of the block. + *

    * Similarly, when a block has more than one successor, then same sequences of moves at the * beginning of the successors can be placed once at the end of the block. But because the moves * must be inserted before all branch instructions, this works only when there is exactly one * conditional branch at the end of the block (because the moves must be inserted before all * branches, but after all compares). - * + *

    * This optimization affects all kind of moves (reg->reg, reg->stack and stack->reg). * 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 { +public final class EdgeMoveOptimizer extends PostAllocationOptimizationPhase { - /** - * Optimizes moves on block edges. - */ - public static void optimize(LIR ir) { - EdgeMoveOptimizer optimizer = new EdgeMoveOptimizer(ir); + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + LIR ir = lirGenRes.getLIR(); + Optimizer optimizer = new Optimizer(ir); List> blockList = ir.linearScanOrder(); // ignore the first block in the list (index 0 is not processed) @@ -67,213 +69,216 @@ } } - private final List> edgeInstructionSeqences; - private LIR ir; - - public EdgeMoveOptimizer(LIR ir) { - this.ir = ir; - edgeInstructionSeqences = new ArrayList<>(4); - } - - /** - * Determines if two operations are both {@linkplain MoveOp moves} that have the same - * {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination} - * operands. - * - * @param op1 the first instruction to compare - * @param op2 the second instruction to compare - * @return {@code true} if {@code op1} and {@code op2} are the same by the above algorithm - */ - private static boolean same(LIRInstruction op1, LIRInstruction op2) { - assert op1 != null; - assert op2 != null; + private static final class Optimizer { + private final List> edgeInstructionSeqences; + private LIR ir; - if (op1 instanceof MoveOp && op2 instanceof MoveOp) { - MoveOp move1 = (MoveOp) op1; - MoveOp move2 = (MoveOp) op2; - if (move1.getInput().equals(move2.getInput()) && move1.getResult().equals(move2.getResult())) { - // these moves are exactly equal and can be optimized - return true; - } - } - return false; - } - - /** - * 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()) { - if (pred == block) { - // currently we can't handle this correctly. - return; - } + public Optimizer(LIR ir) { + this.ir = ir; + edgeInstructionSeqences = new ArrayList<>(4); } - // clear all internal data structures - edgeInstructionSeqences.clear(); - - int numPreds = block.getPredecessorCount(); - assert numPreds > 1 : "do not call otherwise"; - - // setup a list with the LIR instructions of all predecessors - for (AbstractBlock pred : block.getPredecessors()) { - assert pred != null; - assert ir.getLIRforBlock(pred) != null; - List predInstructions = ir.getLIRforBlock(pred); + /** + * Determines if two operations are both {@linkplain MoveOp moves} that have the same + * {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination} + * operands. + * + * @param op1 the first instruction to compare + * @param op2 the second instruction to compare + * @return {@code true} if {@code op1} and {@code op2} are the same by the above algorithm + */ + private static boolean same(LIRInstruction op1, LIRInstruction op2) { + assert op1 != null; + assert op2 != null; - if (pred.getSuccessorCount() != 1) { - // this can happen with switch-statements where multiple edges are between - // the same blocks. - return; + if (op1 instanceof MoveOp && op2 instanceof MoveOp) { + MoveOp move1 = (MoveOp) op1; + MoveOp move2 = (MoveOp) op2; + if (move1.getInput().equals(move2.getInput()) && move1.getResult().equals(move2.getResult())) { + // these moves are exactly equal and can be optimized + return true; + } } - - assert pred.getSuccessors().iterator().next() == block : "invalid control flow"; - assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; - - if (predInstructions.get(predInstructions.size() - 1).hasState()) { - // can not optimize instructions that have debug info - return; - } - - // ignore the unconditional branch at the end of the block - List seq = predInstructions.subList(0, predInstructions.size() - 1); - edgeInstructionSeqences.add(seq); + return false; } - // process lir-instructions while all predecessors end with the same instruction - while (true) { - List seq = edgeInstructionSeqences.get(0); - if (seq.isEmpty()) { - return; - } - - LIRInstruction op = last(seq); - for (int i = 1; i < numPreds; ++i) { - List otherSeq = edgeInstructionSeqences.get(i); - if (otherSeq.isEmpty() || !same(op, last(otherSeq))) { + /** + * 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()) { + if (pred == block) { + // currently we can't handle this correctly. return; } } - // insert the instruction at the beginning of the current block - ir.getLIRforBlock(block).add(1, op); + // clear all internal data structures + edgeInstructionSeqences.clear(); + + int numPreds = block.getPredecessorCount(); + assert numPreds > 1 : "do not call otherwise"; + + // setup a list with the LIR instructions of all predecessors + for (AbstractBlock pred : block.getPredecessors()) { + assert pred != null; + assert ir.getLIRforBlock(pred) != null; + List predInstructions = ir.getLIRforBlock(pred); - // delete the instruction at the end of all predecessors - for (int i = 0; i < numPreds; i++) { - seq = edgeInstructionSeqences.get(i); - removeLast(seq); - } - } - } + if (pred.getSuccessorCount() != 1) { + // this can happen with switch-statements where multiple edges are between + // the same blocks. + return; + } + + assert pred.getSuccessors().iterator().next() == block : "invalid control flow"; + assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; + + if (predInstructions.get(predInstructions.size() - 1).hasState()) { + // can not optimize instructions that have debug info + return; + } - /** - * Moves the longest {@linkplain #same common} subsequence at the start of all successors of - * {@code block} to the end of {@code block} just prior to the branch instruction ending - * {@code block}. - */ - private void optimizeMovesAtBlockBegin(AbstractBlock block) { + // ignore the unconditional branch at the end of the block + List seq = predInstructions.subList(0, predInstructions.size() - 1); + edgeInstructionSeqences.add(seq); + } + + // process lir-instructions while all predecessors end with the same instruction + while (true) { + List seq = edgeInstructionSeqences.get(0); + if (seq.isEmpty()) { + return; + } - edgeInstructionSeqences.clear(); - int numSux = block.getSuccessorCount(); - - List instructions = ir.getLIRforBlock(block); + LIRInstruction op = last(seq); + for (int i = 1; i < numPreds; ++i) { + List otherSeq = edgeInstructionSeqences.get(i); + if (otherSeq.isEmpty() || !same(op, last(otherSeq))) { + return; + } + } - assert numSux == 2 : "method should not be called otherwise"; + // insert the instruction at the beginning of the current block + ir.getLIRforBlock(block).add(1, op); - LIRInstruction lastInstruction = instructions.get(instructions.size() - 1); - if (lastInstruction.hasState()) { - // cannot optimize instructions when debug info is needed - return; + // delete the instruction at the end of all predecessors + for (int i = 0; i < numPreds; i++) { + seq = edgeInstructionSeqences.get(i); + removeLast(seq); + } + } } - LIRInstruction branch = lastInstruction; - if (!(branch instanceof StandardOp.BranchOp) || branch.hasOperands()) { - // Only blocks that end with a conditional branch are optimized. - // In addition, a conditional branch with operands (including state) cannot - // be optimized. Moving a successor instruction before such a branch may - // interfere with the operands of the branch. For example, a successive move - // instruction may redefine an input operand of the branch. - return; - } - - // Now it is guaranteed that the block ends with a conditional branch. - // The instructions are inserted at the end of the block before the branch. - int insertIdx = instructions.size() - 1; - - // setup a list with the lir-instructions of all successors - for (AbstractBlock sux : block.getSuccessors()) { - List suxInstructions = ir.getLIRforBlock(sux); + /** + * Moves the longest {@linkplain #same common} subsequence at the start of all successors of + * {@code block} to the end of {@code block} just prior to the branch instruction ending + * {@code block}. + */ + private void optimizeMovesAtBlockBegin(AbstractBlock block) { - assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; + edgeInstructionSeqences.clear(); + int numSux = block.getSuccessorCount(); - if (sux.getPredecessorCount() != 1) { - // this can happen with switch-statements where multiple edges are between - // the same blocks. - return; - } - assert sux.getPredecessors().iterator().next() == block : "invalid control flow"; + List instructions = ir.getLIRforBlock(block); - // ignore the label at the beginning of the block - List seq = suxInstructions.subList(1, suxInstructions.size()); - edgeInstructionSeqences.add(seq); - } + assert numSux == 2 : "method should not be called otherwise"; - // process LIR instructions while all successors begin with the same instruction - while (true) { - List seq = edgeInstructionSeqences.get(0); - if (seq.isEmpty()) { + LIRInstruction lastInstruction = instructions.get(instructions.size() - 1); + if (lastInstruction.hasState()) { + // cannot optimize instructions when debug info is needed return; } - LIRInstruction op = first(seq); - for (int i = 1; i < numSux; i++) { - List otherSeq = edgeInstructionSeqences.get(i); - if (otherSeq.isEmpty() || !same(op, first(otherSeq))) { - // these instructions are different and cannot be optimized . - // no further optimization possible + LIRInstruction branch = lastInstruction; + if (!(branch instanceof StandardOp.BranchOp) || branch.hasOperands()) { + // Only blocks that end with a conditional branch are optimized. + // In addition, a conditional branch with operands (including state) cannot + // be optimized. Moving a successor instruction before such a branch may + // interfere with the operands of the branch. For example, a successive move + // instruction may redefine an input operand of the branch. + return; + } + + // Now it is guaranteed that the block ends with a conditional branch. + // The instructions are inserted at the end of the block before the branch. + int insertIdx = instructions.size() - 1; + + // setup a list with the lir-instructions of all successors + for (AbstractBlock sux : block.getSuccessors()) { + List suxInstructions = ir.getLIRforBlock(sux); + + assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; + + if (sux.getPredecessorCount() != 1) { + // this can happen with switch-statements where multiple edges are between + // the same blocks. return; } + assert sux.getPredecessors().iterator().next() == block : "invalid control flow"; + + // ignore the label at the beginning of the block + List seq = suxInstructions.subList(1, suxInstructions.size()); + edgeInstructionSeqences.add(seq); } - // insert instruction at end of current block - ir.getLIRforBlock(block).add(insertIdx, op); - insertIdx++; + // process LIR instructions while all successors begin with the same instruction + while (true) { + List seq = edgeInstructionSeqences.get(0); + if (seq.isEmpty()) { + return; + } - // delete the instructions at the beginning of all successors - for (int i = 0; i < numSux; i++) { - seq = edgeInstructionSeqences.get(i); - removeFirst(seq); + LIRInstruction op = first(seq); + for (int i = 1; i < numSux; i++) { + List otherSeq = edgeInstructionSeqences.get(i); + if (otherSeq.isEmpty() || !same(op, first(otherSeq))) { + // these instructions are different and cannot be optimized . + // no further optimization possible + return; + } + } + + // insert instruction at end of current block + ir.getLIRforBlock(block).add(insertIdx, op); + insertIdx++; + + // delete the instructions at the beginning of all successors + for (int i = 0; i < numSux; i++) { + seq = edgeInstructionSeqences.get(i); + removeFirst(seq); + } } } - } - /** - * Gets the first element from a LIR instruction sequence. - */ - private static LIRInstruction first(List seq) { - return seq.get(0); - } + /** + * Gets the first element from a LIR instruction sequence. + */ + private static LIRInstruction first(List seq) { + return seq.get(0); + } + + /** + * Gets the last element from a LIR instruction sequence. + */ + private static LIRInstruction last(List seq) { + return seq.get(seq.size() - 1); + } - /** - * Gets the last element from a LIR instruction sequence. - */ - private static LIRInstruction last(List seq) { - return seq.get(seq.size() - 1); - } + /** + * Removes the first element from a LIR instruction sequence. + */ + private static void removeFirst(List seq) { + seq.remove(0); + } - /** - * Removes the first element from a LIR instruction sequence. - */ - private static void removeFirst(List seq) { - seq.remove(0); - } + /** + * Removes the last element from a LIR instruction sequence. + */ + private static void removeLast(List seq) { + seq.remove(seq.size() - 1); + } - /** - * Removes the last element from a LIR instruction sequence. - */ - private static void removeLast(List seq) { - seq.remove(seq.size() - 1); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FullInfopointOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,18 +24,20 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; import com.oracle.graal.lir.StandardOp.NullCheck; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; -public final class NullCheckOptimizer { +public final class NullCheckOptimizer extends PostAllocationOptimizationPhase { - public static void optimize(LIR ir, int implicitNullCheckLimit) { + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + LIR ir = lirGenRes.getLIR(); List> blocks = ir.codeEmittingOrder(); - NullCheckOptimizer.foldNullChecks(ir, blocks, implicitNullCheckLimit); - } - - private NullCheckOptimizer() { + NullCheckOptimizer.foldNullChecks(ir, blocks, target.implicitNullCheckLimit); } private static void foldNullChecks(LIR ir, List> blocks, int implicitNullCheckLimit) { @@ -63,4 +65,5 @@ } } } + } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Sat Feb 21 19:55:33 2015 +0100 @@ -35,15 +35,18 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.framemap.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; /** * Removes move instructions, where the destination value is already in place. */ -public final class RedundantMoveElimination { +public final class RedundantMoveElimination extends PostAllocationOptimizationPhase { - public static void optimize(LIR lir, FrameMapBuilder frameMapBuilder) { - RedundantMoveElimination redundantMoveElimination = new RedundantMoveElimination(); - redundantMoveElimination.doOptimize(lir, frameMapBuilder); + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + Optimization redundantMoveElimination = new Optimization(); + redundantMoveElimination.doOptimize(lirGenRes.getLIR(), lirGenRes.getFrameMap()); } /** @@ -57,7 +60,7 @@ * The value numbers also contain information if it is an object kind value or not: if the * number is negative it is an object kind value. */ - private static class BlockData { + private static final class BlockData { BlockData(int stateSize) { entryState = new int[stateSize]; @@ -82,436 +85,440 @@ int entryValueNum; } - Map, BlockData> blockData = CollectionsFactory.newMap(); + private static final class Optimization { - Register[] callerSaveRegs; + Map, BlockData> blockData = CollectionsFactory.newMap(); + + Register[] callerSaveRegs; - /** - * Contains the register number for registers which can be optimized and -1 for the others. - */ - int[] eligibleRegs; + /** + * Contains the register number for registers which can be optimized and -1 for the others. + */ + int[] eligibleRegs; + + Map stackIndices = CollectionsFactory.newMap(); + + int numRegs; + + /* + * Pseudo value for a not yet assigned location. + */ + static final int INIT_VALUE = 0; - Map stackIndices = CollectionsFactory.newMap(); + /** + * The main method doing the elimination of redundant moves. + */ + private void doOptimize(LIR lir, FrameMap frameMap) { - int numRegs; + try (Indent indent = Debug.logAndIndent("eliminate redundant moves")) { + + callerSaveRegs = frameMap.getRegisterConfig().getCallerSaveRegisters(); - /* - * Pseudo value for a not yet assigned location. - */ - static final int INIT_VALUE = 0; + initBlockData(lir); + + // Compute a table of the registers which are eligible for move optimization. + // Unallocatable registers should never be optimized. + eligibleRegs = new int[numRegs]; + Arrays.fill(eligibleRegs, -1); + for (Register reg : frameMap.getRegisterConfig().getAllocatableRegisters()) { + if (reg.number < numRegs) { + eligibleRegs[reg.number] = reg.number; + } + } - /** - * The main method doing the elimination of redundant moves. - */ - private void doOptimize(LIR lir, FrameMapBuilder frameMapBuilder) { + if (!solveDataFlow(lir)) { + return; + } + + eliminateMoves(lir); + } + } - try (Indent indent = Debug.logAndIndent("eliminate redundant moves")) { + /** + * The maximum number of locations * blocks. This is a complexity limit for the inner loop + * in {@link #mergeState} (assuming a small number of iterations in {@link #solveDataFlow}. + */ + private static final int COMPLEXITY_LIMIT = 30000; - callerSaveRegs = frameMapBuilder.getRegisterConfig().getCallerSaveRegisters(); + private void initBlockData(LIR lir) { + + List> blocks = lir.linearScanOrder(); + numRegs = 0; + + int maxStackLocations = COMPLEXITY_LIMIT / blocks.size(); - initBlockData(lir); - - // Compute a table of the registers which are eligible for move optimization. - // Unallocatable registers should never be optimized. - eligibleRegs = new int[numRegs]; - Arrays.fill(eligibleRegs, -1); - for (Register reg : frameMapBuilder.getRegisterConfig().getAllocatableRegisters()) { - if (reg.number < numRegs) { - eligibleRegs[reg.number] = reg.number; + /* + * 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) { + List instructions = lir.getLIRforBlock(block); + for (LIRInstruction op : instructions) { + if (isEligibleMove(op)) { + Value dest = ((MoveOp) op).getResult(); + if (isRegister(dest)) { + int regNum = ((RegisterValue) dest).getRegister().number; + if (regNum >= numRegs) { + numRegs = regNum + 1; + } + } else if (isStackSlot(dest)) { + StackSlot stackSlot = (StackSlot) dest; + if (!stackIndices.containsKey(stackSlot) && stackIndices.size() < maxStackLocations) { + stackIndices.put(stackSlot, stackIndices.size()); + } + } + } } } - if (!solveDataFlow(lir)) { - return; + /* + * Now we know the number of locations to optimize, so we can allocate the block states. + */ + int numLocations = numRegs + stackIndices.size(); + Debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size()); + for (AbstractBlock block : blocks) { + BlockData data = new BlockData(numLocations); + blockData.put(block, data); + } + } + + /** + * Calculates the entry and exit states for all basic blocks. + * + * @return Returns true on success and false if the the control flow is too complex. + */ + private boolean solveDataFlow(LIR lir) { + + try (Indent indent = Debug.logAndIndent("solve data flow")) { + + List> blocks = lir.linearScanOrder(); + + int numIter = 0; + + /* + * Iterate until there are no more changes. + */ + int currentValueNum = 1; + boolean firstRound = true; + boolean changed; + do { + changed = false; + try (Indent indent2 = Debug.logAndIndent("new iteration")) { + + for (AbstractBlock block : blocks) { + + BlockData data = blockData.get(block); + /* + * Initialize the number for global value numbering for this block. It + * is essential that the starting number for a block is consistent at + * all iterations and also in eliminateMoves(). + */ + if (firstRound) { + data.entryValueNum = currentValueNum; + } + int valueNum = data.entryValueNum; + assert valueNum > 0; + boolean newState = false; + + if (block == blocks.get(0) || block.isExceptionEntry()) { + /* + * The entry block has undefined values. And also exception handler + * blocks: the LinearScan can insert moves at the end of an + * exception handler predecessor block (after the invoke, which + * throws the exception), and in reality such moves are not in the + * control flow in case of an exception. So we assume a save default + * for exception handler blocks. + */ + Debug.log("kill all values at entry of block %d", block.getId()); + clearValues(data.entryState, valueNum); + } else { + /* + * Merge the states of predecessor blocks + */ + for (AbstractBlock predecessor : block.getPredecessors()) { + BlockData predData = blockData.get(predecessor); + newState |= mergeState(data.entryState, predData.exitState, valueNum); + } + } + // Advance by the value numbers which are "consumed" by + // clearValues and mergeState + valueNum += data.entryState.length; + + if (newState || firstRound) { + try (Indent indent3 = Debug.logAndIndent("update block %d", block.getId())) { + + /* + * Derive the exit state from the entry state by iterating + * through all instructions of the block. + */ + int[] iterState = data.exitState; + copyState(iterState, data.entryState); + List instructions = lir.getLIRforBlock(block); + + for (LIRInstruction op : instructions) { + valueNum = updateState(iterState, op, valueNum); + } + changed = true; + } + } + if (firstRound) { + currentValueNum = valueNum; + } + } + firstRound = false; + } + numIter++; + + if (numIter > 5) { + /* + * This is _very_ seldom. + */ + return false; + } + + } while (changed); + } - eliminateMoves(lir); + return true; } - } + + /** + * Deletes all move instructions where the target location already contains the source + * value. + */ + private void eliminateMoves(LIR lir) { + + try (Indent indent = Debug.logAndIndent("eliminate moves")) { - /** - * The maximum number of locations * blocks. This is a complexity limit for the inner loop in - * {@link #mergeState} (assuming a small number of iterations in {@link #solveDataFlow}. - */ - private static final int COMPLEXITY_LIMIT = 30000; + List> blocks = lir.linearScanOrder(); + + for (AbstractBlock block : blocks) { + + try (Indent indent2 = Debug.logAndIndent("eliminate moves in block %d", block.getId())) { - private void initBlockData(LIR lir) { + List instructions = lir.getLIRforBlock(block); + BlockData data = blockData.get(block); + boolean hasDead = false; - List> blocks = lir.linearScanOrder(); - numRegs = 0; - - int maxStackLocations = COMPLEXITY_LIMIT / blocks.size(); + // Reuse the entry state for iteration, we don't need it later. + int[] iterState = data.entryState; - /* - * 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) { - List instructions = lir.getLIRforBlock(block); - for (LIRInstruction op : instructions) { - if (isEligibleMove(op)) { - Value dest = ((MoveOp) op).getResult(); - if (isRegister(dest)) { - int regNum = ((RegisterValue) dest).getRegister().number; - if (regNum >= numRegs) { - numRegs = regNum + 1; + // Add the values which are "consumed" by clearValues and + // mergeState in solveDataFlow + int valueNum = data.entryValueNum + data.entryState.length; + + int numInsts = instructions.size(); + for (int idx = 0; idx < numInsts; idx++) { + LIRInstruction op = instructions.get(idx); + if (isEligibleMove(op)) { + MoveOp moveOp = (MoveOp) op; + int sourceIdx = getStateIdx(moveOp.getInput()); + int destIdx = getStateIdx(moveOp.getResult()); + if (sourceIdx >= 0 && destIdx >= 0 && iterState[sourceIdx] == iterState[destIdx]) { + assert iterState[sourceIdx] != INIT_VALUE; + Debug.log("delete move %s", op); + instructions.set(idx, null); + hasDead = true; + } + } + // It doesn't harm if updateState is also called for a deleted move + valueNum = updateState(iterState, op, valueNum); } - } else if (isStackSlot(dest)) { - StackSlot stackSlot = (StackSlot) dest; - if (!stackIndices.containsKey(stackSlot) && stackIndices.size() < maxStackLocations) { - stackIndices.put(stackSlot, stackIndices.size()); + if (hasDead) { + instructions.removeAll(Collections.singleton(null)); } } } } } - /* - * Now we know the number of locations to optimize, so we can allocate the block states. + /** + * Updates the state for one instruction. */ - int numLocations = numRegs + stackIndices.size(); - Debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size()); - for (AbstractBlock block : blocks) { - BlockData data = new BlockData(numLocations); - blockData.put(block, data); - } - } - - /** - * Calculates the entry and exit states for all basic blocks. - * - * @return Returns true on success and false if the the control flow is too complex. - */ - private boolean solveDataFlow(LIR lir) { - - try (Indent indent = Debug.logAndIndent("solve data flow")) { - - List> blocks = lir.linearScanOrder(); + private int updateState(final int[] state, LIRInstruction op, int initValueNum) { - int numIter = 0; + try (final Indent indent = Debug.logAndIndent("update state for op %s, initial value num = %d", op, initValueNum)) { + if (isEligibleMove(op)) { + /* + * Handle the special case of a move instruction + */ + MoveOp moveOp = (MoveOp) op; + int sourceIdx = getStateIdx(moveOp.getInput()); + int destIdx = getStateIdx(moveOp.getResult()); + if (sourceIdx >= 0 && destIdx >= 0) { + assert isObjectValue(state[sourceIdx]) || moveOp.getInput().getLIRKind().isValue() : "move op moves object but input is not defined as object"; + state[destIdx] = state[sourceIdx]; + Debug.log("move value %d from %d to %d", state[sourceIdx], sourceIdx, destIdx); + return initValueNum; + } + } - /* - * Iterate until there are no more changes. - */ - int currentValueNum = 1; - boolean firstRound = true; - boolean changed; - do { - changed = false; - try (Indent indent2 = Debug.logAndIndent("new iteration")) { + int valueNum = initValueNum; + + if (op.destroysCallerSavedRegisters()) { + Debug.log("kill all caller save regs"); - for (AbstractBlock block : blocks) { - - BlockData data = blockData.get(block); - /* - * Initialize the number for global value numbering for this block. It is - * essential that the starting number for a block is consistent at all - * iterations and also in eliminateMoves(). - */ - if (firstRound) { - data.entryValueNum = currentValueNum; + for (Register reg : callerSaveRegs) { + if (reg.number < numRegs) { + // Kind.Object is the save default + state[reg.number] = encodeValueNum(valueNum++, true); } - int valueNum = data.entryValueNum; - assert valueNum > 0; - boolean newState = false; + } + } + + /* + * Value procedure for the instruction's output and temp values + */ + class OutputValueConsumer implements ValueConsumer { - if (block == blocks.get(0) || block.isExceptionEntry()) { + int opValueNum; + + OutputValueConsumer(int opValueNum) { + this.opValueNum = opValueNum; + } + + @Override + public void visitValue(Value operand, OperandMode mode, EnumSet flags) { + int stateIdx = getStateIdx(operand); + if (stateIdx >= 0) { /* - * The entry block has undefined values. And also exception handler - * blocks: the LinearScan can insert moves at the end of an exception - * handler predecessor block (after the invoke, which throws the - * exception), and in reality such moves are not in the control flow in - * case of an exception. So we assume a save default for exception - * handler blocks. - */ - Debug.log("kill all values at entry of block %d", block.getId()); - clearValues(data.entryState, valueNum); - } else { - /* - * Merge the states of predecessor blocks + * Assign a unique number to the output or temp location. */ - for (AbstractBlock predecessor : block.getPredecessors()) { - BlockData predData = blockData.get(predecessor); - newState |= mergeState(data.entryState, predData.exitState, valueNum); - } - } - // Advance by the value numbers which are "consumed" by - // clearValues and mergeState - valueNum += data.entryState.length; - - if (newState || firstRound) { - try (Indent indent3 = Debug.logAndIndent("update block %d", block.getId())) { - - /* - * Derive the exit state from the entry state by iterating through - * all instructions of the block. - */ - int[] iterState = data.exitState; - copyState(iterState, data.entryState); - List instructions = lir.getLIRforBlock(block); - - for (LIRInstruction op : instructions) { - valueNum = updateState(iterState, op, valueNum); - } - changed = true; - } - } - if (firstRound) { - currentValueNum = valueNum; + state[stateIdx] = encodeValueNum(opValueNum++, !operand.getLIRKind().isValue()); + Debug.log("set def %d for register %s(%d): %d", opValueNum, operand, stateIdx, state[stateIdx]); } } - firstRound = false; - } - numIter++; - - if (numIter > 5) { - /* - * This is _very_ seldom. - */ - return false; } - } while (changed); + OutputValueConsumer outputValueConsumer = new OutputValueConsumer(valueNum); + + op.visitEachTemp(outputValueConsumer); + /* + * Semantically the output values are written _after_ the temp values + */ + op.visitEachOutput(outputValueConsumer); + + valueNum = outputValueConsumer.opValueNum; + if (op.hasState()) { + /* + * All instructions with framestates (mostly method calls), may do garbage + * collection. GC will rewrite all object references which are live at this + * point. So we can't rely on their values. It would be sufficient to just kill + * all values which are referenced in the state (or all values which are not), + * but for simplicity we kill all values. + */ + Debug.log("kill all object values"); + clearValuesOfKindObject(state, valueNum); + valueNum += state.length; + } + + return valueNum; + } } - return true; - } - - /** - * Deletes all move instructions where the target location already contains the source value. - */ - private void eliminateMoves(LIR lir) { - - try (Indent indent = Debug.logAndIndent("eliminate moves")) { - - List> blocks = lir.linearScanOrder(); - - for (AbstractBlock block : blocks) { - - try (Indent indent2 = Debug.logAndIndent("eliminate moves in block %d", block.getId())) { - - List instructions = lir.getLIRforBlock(block); - BlockData data = blockData.get(block); - boolean hasDead = false; - - // Reuse the entry state for iteration, we don't need it later. - int[] iterState = data.entryState; + /** + * The state merge function for dataflow joins. + */ + private static boolean mergeState(int[] dest, int[] source, int defNum) { + assert dest.length == source.length; + boolean changed = false; + for (int idx = 0; idx < source.length; idx++) { + int phiNum = defNum + idx; + int dst = dest[idx]; + int src = source[idx]; + if (dst != src && src != INIT_VALUE && dst != encodeValueNum(phiNum, isObjectValue(dst))) { + if (dst != INIT_VALUE) { + dst = encodeValueNum(phiNum, isObjectValue(dst) || isObjectValue(src)); + } else { + dst = src; + } + dest[idx] = dst; + changed = true; + } + } + return changed; + } - // Add the values which are "consumed" by clearValues and - // mergeState in solveDataFlow - int valueNum = data.entryValueNum + data.entryState.length; + private static void copyState(int[] dest, int[] source) { + assert dest.length == source.length; + for (int idx = 0; idx < source.length; idx++) { + dest[idx] = source[idx]; + } + } - int numInsts = instructions.size(); - for (int idx = 0; idx < numInsts; idx++) { - LIRInstruction op = instructions.get(idx); - if (isEligibleMove(op)) { - MoveOp moveOp = (MoveOp) op; - int sourceIdx = getStateIdx(moveOp.getInput()); - int destIdx = getStateIdx(moveOp.getResult()); - if (sourceIdx >= 0 && destIdx >= 0 && iterState[sourceIdx] == iterState[destIdx]) { - assert iterState[sourceIdx] != INIT_VALUE; - Debug.log("delete move %s", op); - instructions.set(idx, null); - hasDead = true; - } - } - // It doesn't harm if updateState is also called for a deleted move - valueNum = updateState(iterState, op, valueNum); - } - if (hasDead) { - instructions.removeAll(Collections.singleton(null)); - } + private static void clearValues(int[] state, int defNum) { + for (int idx = 0; idx < state.length; idx++) { + int phiNum = defNum + idx; + // Let the killed values assume to be object references: it's the save default. + state[idx] = encodeValueNum(phiNum, true); + } + } + + private static void clearValuesOfKindObject(int[] state, int defNum) { + for (int idx = 0; idx < state.length; idx++) { + int phiNum = defNum + idx; + if (isObjectValue(state[idx])) { + state[idx] = encodeValueNum(phiNum, true); } } } - } - /** - * Updates the state for one instruction. - */ - private int updateState(final int[] state, LIRInstruction op, int initValueNum) { - - try (final Indent indent = Debug.logAndIndent("update state for op %s, initial value num = %d", op, initValueNum)) { - if (isEligibleMove(op)) { - /* - * Handle the special case of a move instruction - */ - MoveOp moveOp = (MoveOp) op; - int sourceIdx = getStateIdx(moveOp.getInput()); - int destIdx = getStateIdx(moveOp.getResult()); - if (sourceIdx >= 0 && destIdx >= 0) { - assert isObjectValue(state[sourceIdx]) || moveOp.getInput().getLIRKind().isValue() : "move op moves object but input is not defined as object"; - state[destIdx] = state[sourceIdx]; - Debug.log("move value %d from %d to %d", state[sourceIdx], sourceIdx, destIdx); - return initValueNum; + /** + * Returns the index to the state arrays in BlockData for a specific location. + */ + private int getStateIdx(Value location) { + if (isRegister(location)) { + int regNum = ((RegisterValue) location).getRegister().number; + if (regNum < numRegs) { + return eligibleRegs[regNum]; } - } - - int valueNum = initValueNum; - - if (op.destroysCallerSavedRegisters()) { - Debug.log("kill all caller save regs"); - - for (Register reg : callerSaveRegs) { - if (reg.number < numRegs) { - // Kind.Object is the save default - state[reg.number] = encodeValueNum(valueNum++, true); - } - } - } - - /* - * Value procedure for the instruction's output and temp values - */ - class OutputValueConsumer implements ValueConsumer { - - int opValueNum; - - OutputValueConsumer(int opValueNum) { - this.opValueNum = opValueNum; - } - - @Override - public void visitValue(Value operand, OperandMode mode, EnumSet flags) { - int stateIdx = getStateIdx(operand); - if (stateIdx >= 0) { - /* - * Assign a unique number to the output or temp location. - */ - state[stateIdx] = encodeValueNum(opValueNum++, !operand.getLIRKind().isValue()); - Debug.log("set def %d for register %s(%d): %d", opValueNum, operand, stateIdx, state[stateIdx]); - } - } + return -1; } - - OutputValueConsumer outputValueConsumer = new OutputValueConsumer(valueNum); - - op.visitEachTemp(outputValueConsumer); - /* - * Semantically the output values are written _after_ the temp values - */ - op.visitEachOutput(outputValueConsumer); - - valueNum = outputValueConsumer.opValueNum; - - if (op.hasState()) { - /* - * All instructions with framestates (mostly method calls), may do garbage - * collection. GC will rewrite all object references which are live at this point. - * So we can't rely on their values. It would be sufficient to just kill all values - * which are referenced in the state (or all values which are not), but for - * simplicity we kill all values. - */ - Debug.log("kill all object values"); - clearValuesOfKindObject(state, valueNum); - valueNum += state.length; - } - - return valueNum; - } - } - - /** - * The state merge function for dataflow joins. - */ - private static boolean mergeState(int[] dest, int[] source, int defNum) { - assert dest.length == source.length; - boolean changed = false; - for (int idx = 0; idx < source.length; idx++) { - int phiNum = defNum + idx; - int dst = dest[idx]; - int src = source[idx]; - if (dst != src && src != INIT_VALUE && dst != encodeValueNum(phiNum, isObjectValue(dst))) { - if (dst != INIT_VALUE) { - dst = encodeValueNum(phiNum, isObjectValue(dst) || isObjectValue(src)); - } else { - dst = src; + if (isStackSlot(location)) { + StackSlot slot = (StackSlot) location; + Integer index = stackIndices.get(slot); + if (index != null) { + return index.intValue() + numRegs; } - dest[idx] = dst; - changed = true; - } - } - return changed; - } - - private static void copyState(int[] dest, int[] source) { - assert dest.length == source.length; - for (int idx = 0; idx < source.length; idx++) { - dest[idx] = source[idx]; - } - } - - private static void clearValues(int[] state, int defNum) { - for (int idx = 0; idx < state.length; idx++) { - int phiNum = defNum + idx; - // Let the killed values assume to be object references: it's the save default. - state[idx] = encodeValueNum(phiNum, true); - } - } - - private static void clearValuesOfKindObject(int[] state, int defNum) { - for (int idx = 0; idx < state.length; idx++) { - int phiNum = defNum + idx; - if (isObjectValue(state[idx])) { - state[idx] = encodeValueNum(phiNum, true); - } - } - } - - /** - * Returns the index to the state arrays in BlockData for a specific location. - */ - private int getStateIdx(Value location) { - if (isRegister(location)) { - int regNum = ((RegisterValue) location).getRegister().number; - if (regNum < numRegs) { - return eligibleRegs[regNum]; } return -1; } - if (isStackSlot(location)) { - StackSlot slot = (StackSlot) location; - Integer index = stackIndices.get(slot); - if (index != null) { - return index.intValue() + numRegs; + + /** + * Encodes a value number + the is-object information to a number to be stored in a state. + */ + private static int encodeValueNum(int valueNum, boolean isObjectKind) { + assert valueNum > 0; + if (isObjectKind) { + return -valueNum; } + return valueNum; } - return -1; - } - - /** - * Encodes a value number + the is-object information to a number to be stored in a state. - */ - private static int encodeValueNum(int valueNum, boolean isObjectKind) { - assert valueNum > 0; - if (isObjectKind) { - return -valueNum; - } - return valueNum; - } - /** - * Returns true if an encoded value number (which is stored in a state) refers to an object - * reference. - */ - private static boolean isObjectValue(int encodedValueNum) { - return encodedValueNum < 0; - } + /** + * Returns true if an encoded value number (which is stored in a state) refers to an object + * reference. + */ + private static boolean isObjectValue(int encodedValueNum) { + return encodedValueNum < 0; + } - /** - * Returns true for a move instruction which is a candidate for elimination. - */ - private static boolean isEligibleMove(LIRInstruction op) { - if (op instanceof MoveOp) { - MoveOp moveOp = (MoveOp) op; - Value source = moveOp.getInput(); - Value dest = moveOp.getResult(); - /* - * Moves with mismatching kinds are not moves, but memory loads/stores! - */ - return source.getLIRKind().equals(dest.getLIRKind()); + /** + * Returns true for a move instruction which is a candidate for elimination. + */ + private static boolean isEligibleMove(LIRInstruction op) { + if (op instanceof MoveOp) { + MoveOp moveOp = (MoveOp) op; + Value source = moveOp.getInput(); + Value dest = moveOp.getResult(); + /* + * Moves with mismatching kinds are not moves, but memory loads/stores! + */ + return source.getLIRKind().equals(dest.getLIRKind()); + } + return false; } - return false; } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Sat Feb 21 19:55:33 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,7 +186,8 @@ * 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. @@ -191,6 +200,7 @@ final int index; public NoOp(AbstractBlock 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java Sat Feb 21 19:55:33 2015 +0100 @@ -56,7 +56,7 @@ * >"Optimized Interval Splitting in a Linear Scan Register Allocator" by Christian Wimmer and * Hanspeter Moessenboeck. */ -public final class LinearScan { +final class LinearScan { final TargetDescription target; final LIRGenerationResult res; @@ -109,7 +109,7 @@ public BitSet liveKill; } - public final BlockMap blockData; + final BlockMap blockData; /** * List of blocks in linear-scan order. This is only correct as long as the CFG does not change. @@ -161,7 +161,7 @@ */ private final int firstVariableNumber; - public LinearScan(TargetDescription target, LIRGenerationResult res) { + LinearScan(TargetDescription target, LIRGenerationResult res) { this.target = target; this.res = res; this.ir = res.getLIR(); @@ -178,13 +178,13 @@ this.callKillsRegisters = this.frameMapBuilder.getRegisterConfig().areAllAllocatableRegistersCallerSaved(); } - public int getFirstLirInstructionId(AbstractBlock block) { + int getFirstLirInstructionId(AbstractBlock block) { int result = ir.getLIRforBlock(block).get(0).id(); assert result >= 0; return result; } - public int getLastLirInstructionId(AbstractBlock block) { + int getLastLirInstructionId(AbstractBlock block) { List instructions = ir.getLIRforBlock(block); int result = instructions.get(instructions.size() - 1).id(); assert result >= 0; @@ -220,7 +220,7 @@ /** * Gets the highest operand number for a register operand. This value will never change. */ - public int maxRegisterNumber() { + int maxRegisterNumber() { return firstVariableNumber - 1; } @@ -1374,7 +1374,7 @@ sortedIntervals = combinedList; } - public void allocateRegisters() { + void allocateRegisters() { try (Indent indent = Debug.logAndIndent("allocate registers")) { Interval precoloredIntervals; Interval notPrecoloredIntervals; @@ -1731,11 +1731,7 @@ } } - public static void allocate(TargetDescription target, LIRGenerationResult res) { - new LinearScan(target, res).allocate(); - } - - private void allocate() { + void allocate() { /* * This is the point to enable debug logging for the whole register allocation. diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,39 @@ +/* + * 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.alloc.lsra; + +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.phases.*; + +public final class LinearScanPhase extends AllocationPhase { + + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + new LinearScan(target, lirGenRes).allocate(); + } + +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,9 +34,15 @@ import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.framemap.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.options.*; -public final class LocationMarker { +/** + * Mark all live references for a frame state. The frame state use this information to build the OOP + * maps. + */ +public final class LocationMarker extends AllocationPhase { public static class Options { // @formatter:off @@ -45,177 +51,177 @@ // @formatter:on } - /** - * Mark all live references for a frame state. The frame state use this information to build the - * OOP maps. - */ - public static void markLocations(LIR lir, FrameMap frameMap) { - new LocationMarker(lir, frameMap).build(); - } - - private final LIR lir; - private final FrameMap frameMap; - private final RegisterAttributes[] registerAttributes; - private final BlockMap liveInMap; - private final BlockMap liveOutMap; - - private LocationMarker(LIR lir, FrameMap frameMap) { - this.lir = lir; - this.frameMap = frameMap; - this.registerAttributes = frameMap.getRegisterConfig().getAttributesMap(); - liveInMap = new BlockMap<>(lir.getControlFlowGraph()); - liveOutMap = new BlockMap<>(lir.getControlFlowGraph()); + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build(); } - private void build() { - 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()) { - liveInMap.put(block, frameMap.initReferenceMap(true)); - } - while (!worklist.isEmpty()) { - AbstractBlock block = worklist.poll(); - processBlock(block, worklist); - } - // finish states - for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { - List instructions = lir.getLIRforBlock(block); - for (int i = instructions.size() - 1; i >= 0; i--) { - LIRInstruction inst = instructions.get(i); - inst.forEachState((op, info) -> info.finish(op, frameMap)); - } + private static final class Marker { + private final LIR lir; + private final FrameMap frameMap; + private final RegisterAttributes[] registerAttributes; + private final BlockMap liveInMap; + private final BlockMap liveOutMap; + private Marker(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + this.registerAttributes = frameMap.getRegisterConfig().getAttributesMap(); + liveInMap = new BlockMap<>(lir.getControlFlowGraph()); + liveOutMap = new BlockMap<>(lir.getControlFlowGraph()); } - } - /** - * Merge outSet with in-set of successors. - */ - private boolean updateOutBlock(AbstractBlock block) { - ReferenceMap union = frameMap.initReferenceMap(true); - block.getSuccessors().forEach(succ -> union.updateUnion(liveInMap.get(succ))); - ReferenceMap outSet = liveOutMap.get(block); - // check if changed - if (outSet == null || !union.equals(outSet)) { - liveOutMap.put(block, union); - return true; - } - return false; - } - - private void processBlock(AbstractBlock block, Deque> worklist) { - if (updateOutBlock(block)) { - try (Indent indent = Debug.logAndIndent("handle block %s", block)) { - BlockClosure closure = new BlockClosure(liveOutMap.get(block).clone()); + private void build() { + 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()) { + liveInMap.put(block, frameMap.initReferenceMap(true)); + } + while (!worklist.isEmpty()) { + AbstractBlock block = worklist.poll(); + processBlock(block, worklist); + } + // finish states + for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { List instructions = lir.getLIRforBlock(block); for (int i = instructions.size() - 1; i >= 0; i--) { LIRInstruction inst = instructions.get(i); - closure.processInstructionBottomUp(inst); + inst.forEachState((op, info) -> info.finish(op, frameMap)); } - liveInMap.put(block, closure.getCurrentSet()); - worklist.addAll(block.getPredecessors()); - } - } - } - - private static final EnumSet REGISTER_FLAG_SET = EnumSet.of(OperandFlag.REG); - private static final LIRKind REFERENCE_KIND = LIRKind.reference(Kind.Object); - - private void forEachDestroyedCallerSavedRegister(LIRInstruction op, ValueConsumer consumer) { - if (op.destroysCallerSavedRegisters()) { - for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { - consumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); - } - } - } - - private final class BlockClosure { - private final ReferenceMap currentSet; - private BlockClosure(ReferenceMap set) { - currentSet = set; - } - - private ReferenceMap getCurrentSet() { - return currentSet; - } - - /** - * Process all values of an instruction bottom-up, i.e. definitions before usages. Values - * that start or end at the current operation are not included. - */ - private void processInstructionBottomUp(LIRInstruction op) { - try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) { - // kills - op.visitEachTemp(this::defConsumer); - op.visitEachOutput(this::defConsumer); - forEachDestroyedCallerSavedRegister(op, this::defConsumer); - - // gen - values that are considered alive for this state - op.visitEachAlive(this::useConsumer); - op.visitEachState(this::useConsumer); - // mark locations - op.forEachState((inst, info) -> markLocation(inst, info, this.getCurrentSet())); - // gen - op.visitEachInput(this::useConsumer); } } /** - * @see InstructionValueConsumer - * @param operand - * @param mode - * @param flags + * Merge outSet with in-set of successors. */ - private void useConsumer(Value operand, OperandMode mode, EnumSet flags) { - LIRKind kind = operand.getLIRKind(); - if (shouldProcessValue(operand) && !kind.isValue() && !kind.isDerivedReference()) { - // no need to insert values and derived reference - Debug.log("set operand: %s", operand); - frameMap.setReference(operand, currentSet); + private boolean updateOutBlock(AbstractBlock block) { + ReferenceMap union = frameMap.initReferenceMap(true); + block.getSuccessors().forEach(succ -> union.updateUnion(liveInMap.get(succ))); + ReferenceMap outSet = liveOutMap.get(block); + // check if changed + if (outSet == null || !union.equals(outSet)) { + liveOutMap.put(block, union); + return true; + } + return false; + } + + private void processBlock(AbstractBlock block, Deque> worklist) { + if (updateOutBlock(block)) { + try (Indent indent = Debug.logAndIndent("handle block %s", block)) { + BlockClosure closure = new BlockClosure(liveOutMap.get(block).clone()); + List instructions = lir.getLIRforBlock(block); + for (int i = instructions.size() - 1; i >= 0; i--) { + LIRInstruction inst = instructions.get(i); + closure.processInstructionBottomUp(inst); + } + liveInMap.put(block, closure.getCurrentSet()); + worklist.addAll(block.getPredecessors()); + } + } + } + + private static final EnumSet REGISTER_FLAG_SET = EnumSet.of(OperandFlag.REG); + private static final LIRKind REFERENCE_KIND = LIRKind.reference(Kind.Object); + + private void forEachDestroyedCallerSavedRegister(LIRInstruction op, ValueConsumer consumer) { + if (op.destroysCallerSavedRegisters()) { + for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { + consumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); + } + } + } + + private final class BlockClosure { + private final ReferenceMap currentSet; + + private BlockClosure(ReferenceMap set) { + currentSet = set; + } + + private ReferenceMap getCurrentSet() { + return currentSet; + } + + /** + * Process all values of an instruction bottom-up, i.e. definitions before usages. + * Values that start or end at the current operation are not included. + */ + private void processInstructionBottomUp(LIRInstruction op) { + try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) { + // kills + op.visitEachTemp(this::defConsumer); + op.visitEachOutput(this::defConsumer); + forEachDestroyedCallerSavedRegister(op, this::defConsumer); + + // gen - values that are considered alive for this state + op.visitEachAlive(this::useConsumer); + op.visitEachState(this::useConsumer); + // mark locations + op.forEachState((inst, info) -> markLocation(inst, info, this.getCurrentSet())); + // gen + op.visitEachInput(this::useConsumer); + } + } + + /** + * @see InstructionValueConsumer + * @param operand + * @param mode + * @param flags + */ + private void useConsumer(Value operand, OperandMode mode, EnumSet flags) { + LIRKind kind = operand.getLIRKind(); + if (shouldProcessValue(operand) && !kind.isValue() && !kind.isDerivedReference()) { + // no need to insert values and derived reference + Debug.log("set operand: %s", operand); + frameMap.setReference(operand, currentSet); + } + } + + /** + * @see InstructionValueConsumer + * @param operand + * @param mode + * @param flags + */ + private void defConsumer(Value operand, OperandMode mode, EnumSet flags) { + if (shouldProcessValue(operand)) { + Debug.log("clear operand: %s", operand); + frameMap.clearReference(operand, currentSet); + } else { + assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s", + operand, mode); + } + } + + protected boolean shouldProcessValue(Value operand) { + return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal; } } /** - * @see InstructionValueConsumer - * @param operand - * @param mode - * @param flags + * This method does the actual marking. */ - private void defConsumer(Value operand, OperandMode mode, EnumSet flags) { - if (shouldProcessValue(operand)) { - Debug.log("clear operand: %s", operand); - frameMap.clearReference(operand, currentSet); - } else { - assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s", - operand, mode); + private void markLocation(LIRInstruction op, LIRFrameState info, ReferenceMap refMap) { + if (!info.hasDebugInfo()) { + info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !frameMap.getRegisterConfig().areAllAllocatableRegistersCallerSaved()); } + info.updateUnion(refMap); } - protected boolean shouldProcessValue(Value operand) { - return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal; - } - } - - /** - * This method does the actual marking. - */ - private void markLocation(LIRInstruction op, LIRFrameState info, ReferenceMap refMap) { - if (!info.hasDebugInfo()) { - info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !frameMap.getRegisterConfig().areAllAllocatableRegistersCallerSaved()); + /** + * Gets an object describing the attributes of a given register according to this register + * configuration. + * + * @see LinearScan#attributes + */ + private RegisterAttributes attributes(Register reg) { + return registerAttributes[reg.number]; } - info.updateUnion(refMap); - } - /** - * Gets an object describing the attributes of a given register according to this register - * configuration. - * - * @see LinearScan#attributes - */ - private RegisterAttributes attributes(Register reg) { - return registerAttributes[reg.number]; } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/Range.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java Sat Feb 21 19:55:33 2015 +0100 @@ -27,6 +27,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; @@ -38,6 +39,7 @@ import com.oracle.graal.lir.constopt.ConstantTree.Flags; import com.oracle.graal.lir.constopt.ConstantTree.NodeCost; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.options.*; /** @@ -45,27 +47,20 @@ * 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 { +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 ConstantLoadOptimization = new OptionValue<>(true); + public static final OptionValue LIROptConstantLoadOptimization = new OptionValue<>(true); // @formatter:on } - public static void optimize(LIR lir, LIRGeneratorTool lirGen) { - new ConstantLoadOptimization(lir, lirGen).apply(); + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRGeneratorTool lirGen) { + new Optimization(lirGenRes.getLIR(), lirGen).apply(); } - private LIR lir; - private LIRGeneratorTool lirGen; - private VariableMap map; - private BitSet phiConstants; - private BitSet defined; - private BlockMap> blockMap; - private BlockMap insertionBuffers; - private static final DebugMetric constantsTotal = Debug.metric("ConstantLoadOptimization[total]"); private static final DebugMetric phiConstantsSkipped = Debug.metric("ConstantLoadOptimization[PhisSkipped]"); private static final DebugMetric singleUsageConstantsSkipped = Debug.metric("ConstantLoadOptimization[SingleUsageSkipped]"); @@ -73,275 +68,285 @@ private static final DebugMetric materializeAtDefinitionSkipped = Debug.metric("ConstantLoadOptimization[MaterializeAtDefinitionSkipped]"); private static final DebugMetric constantsOptimized = Debug.metric("ConstantLoadOptimization[optimized]"); - private ConstantLoadOptimization(LIR lir, LIRGeneratorTool lirGen) { - this.lir = lir; - this.lirGen = lirGen; - this.map = new VariableMap<>(); - this.phiConstants = new BitSet(); - this.defined = new BitSet(); - this.insertionBuffers = new BlockMap<>(lir.getControlFlowGraph()); - this.blockMap = new BlockMap<>(lir.getControlFlowGraph()); - } + private static final class Optimization { + private final LIR lir; + private final LIRGeneratorTool lirGen; + private final VariableMap map; + private final BitSet phiConstants; + private final BitSet defined; + private final BlockMap> blockMap; + private final BlockMap insertionBuffers; + + private Optimization(LIR lir, LIRGeneratorTool lirGen) { + this.lir = lir; + this.lirGen = lirGen; + this.map = new VariableMap<>(); + this.phiConstants = new BitSet(); + this.defined = new BitSet(); + this.insertionBuffers = new BlockMap<>(lir.getControlFlowGraph()); + this.blockMap = new BlockMap<>(lir.getControlFlowGraph()); + } - private void apply() { - try (Indent indent = Debug.logAndIndent("ConstantLoadOptimization")) { - try (Scope s = Debug.scope("BuildDefUseTree")) { - // build DefUseTree - lir.getControlFlowGraph().getBlocks().forEach(this::analyzeBlock); - // remove all with only one use - map.filter(t -> { - if (t.usageCount() > 1) { - return true; - } else { - singleUsageConstantsSkipped.increment(); - return false; - } - }); - // collect block map - map.forEach(tree -> tree.forEach(this::addUsageToBlockMap)); - } catch (Throwable e) { - throw Debug.handle(e); - } + private void apply() { + try (Indent indent = Debug.logAndIndent("ConstantLoadOptimization")) { + try (Scope s = Debug.scope("BuildDefUseTree")) { + // build DefUseTree + lir.getControlFlowGraph().getBlocks().forEach(this::analyzeBlock); + // remove all with only one use + map.filter(t -> { + if (t.usageCount() > 1) { + return true; + } else { + singleUsageConstantsSkipped.increment(); + return false; + } + }); + // collect block map + map.forEach(tree -> tree.forEach(this::addUsageToBlockMap)); + } catch (Throwable e) { + throw Debug.handle(e); + } - try (Scope s = Debug.scope("BuildConstantTree")) { - // create ConstantTree - map.forEach(this::createConstantTree); + try (Scope s = Debug.scope("BuildConstantTree")) { + // create ConstantTree + map.forEach(this::createConstantTree); - // insert moves, delete null instructions and reset instruction ids - lir.getControlFlowGraph().getBlocks().forEach(this::rewriteBlock); + // insert moves, delete null instructions and reset instruction ids + lir.getControlFlowGraph().getBlocks().forEach(this::rewriteBlock); - assert verifyStates(); - } catch (Throwable e) { - throw Debug.handle(e); + assert verifyStates(); + } catch (Throwable e) { + throw Debug.handle(e); + } } } - } - private boolean verifyStates() { - map.forEach(this::verifyStateUsage); - return true; - } + private boolean verifyStates() { + map.forEach(this::verifyStateUsage); + return true; + } + + private void verifyStateUsage(DefUseTree tree) { + Variable var = tree.getVariable(); + ValueConsumer stateConsumer = new ValueConsumer() { - private void verifyStateUsage(DefUseTree tree) { - Variable var = tree.getVariable(); - ValueConsumer stateConsumer = new ValueConsumer() { - - @Override - public void visitValue(Value operand, OperandMode mode, EnumSet flags) { - assert !operand.equals(var) : "constant usage through variable in frame state " + var; - } - }; - for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { - for (LIRInstruction inst : lir.getLIRforBlock(block)) { - // set instruction id to the index in the lir instruction list - inst.visitEachState(stateConsumer); + @Override + public void visitValue(Value operand, OperandMode mode, EnumSet flags) { + assert !operand.equals(var) : "constant usage through variable in frame state " + var; + } + }; + for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + for (LIRInstruction inst : lir.getLIRforBlock(block)) { + // set instruction id to the index in the lir instruction list + inst.visitEachState(stateConsumer); + } } } - } - private static boolean isConstantLoad(LIRInstruction inst) { - if (!(inst instanceof MoveOp)) { - return false; + private static boolean isConstantLoad(LIRInstruction inst) { + if (!(inst instanceof MoveOp)) { + return false; + } + MoveOp move = (MoveOp) inst; + return isConstant(move.getInput()) && isVariable(move.getResult()); } - MoveOp move = (MoveOp) inst; - return isConstant(move.getInput()) && isVariable(move.getResult()); - } - private void addUsageToBlockMap(UseEntry entry) { - AbstractBlock block = entry.getBlock(); - List list = blockMap.get(block); - if (list == null) { - list = new ArrayList<>(); - blockMap.put(block, list); + private void addUsageToBlockMap(UseEntry entry) { + AbstractBlock block = entry.getBlock(); + List list = blockMap.get(block); + if (list == null) { + list = new ArrayList<>(); + blockMap.put(block, list); + } + list.add(entry); } - list.add(entry); - } - /** - * Collects def-use information for a {@code block}. - */ - private void analyzeBlock(AbstractBlock block) { - try (Indent indent = Debug.logAndIndent("Block: %s", block)) { + /** + * Collects def-use information for a {@code block}. + */ + private void analyzeBlock(AbstractBlock block) { + try (Indent indent = Debug.logAndIndent("Block: %s", block)) { + + InstructionValueConsumer loadConsumer = (instruction, value, mode, flags) -> { + if (isVariable(value)) { + Variable var = (Variable) value; - InstructionValueConsumer loadConsumer = (instruction, value, mode, flags) -> { - if (isVariable(value)) { - Variable var = (Variable) value; - - if (!phiConstants.get(var.index)) { - if (!defined.get(var.index)) { - defined.set(var.index); - if (isConstantLoad(instruction)) { - Debug.log("constant load: %s", instruction); - map.put(var, new DefUseTree(instruction, block)); - constantsTotal.increment(); + if (!phiConstants.get(var.index)) { + if (!defined.get(var.index)) { + defined.set(var.index); + if (isConstantLoad(instruction)) { + Debug.log("constant load: %s", instruction); + map.put(var, new DefUseTree(instruction, block)); + constantsTotal.increment(); + } + } else { + // Variable is redefined, this only happens for constant loads + // introduced by phi resolution -> ignore. + DefUseTree removed = map.remove(var); + if (removed != null) { + phiConstantsSkipped.increment(); + } + phiConstants.set(var.index); + Debug.log(3, "Removing phi variable: %s", var); } } else { - // Variable is redefined, this only happens for constant loads - // introduced by phi resolution -> ignore. - DefUseTree removed = map.remove(var); - if (removed != null) { - phiConstantsSkipped.increment(); - } - phiConstants.set(var.index); - Debug.log(3, "Removing phi variable: %s", var); + assert defined.get(var.index) : "phi but not defined? " + var; } - } else { - assert defined.get(var.index) : "phi but not defined? " + var; } - } - }; + }; - ValuePositionProcedure useProcedure = (instruction, position) -> { - Value value = position.get(instruction); - 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); - Debug.log("usage of %s : %s", var, instruction); + ValuePositionProcedure useProcedure = (instruction, position) -> { + Value value = position.get(instruction); + 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); + Debug.log("usage of %s : %s", var, instruction); + } } } - } - }; + }; - int opId = 0; - for (LIRInstruction inst : lir.getLIRforBlock(block)) { - // set instruction id to the index in the lir instruction list - inst.setId(opId++); - inst.visitEachOutput(loadConsumer); - inst.forEachInputPos(useProcedure); - inst.forEachAlivePos(useProcedure); + int opId = 0; + for (LIRInstruction inst : lir.getLIRforBlock(block)) { + // set instruction id to the index in the lir instruction list + inst.setId(opId++); + inst.visitEachOutput(loadConsumer); + inst.forEachInputPos(useProcedure); + inst.forEachAlivePos(useProcedure); + } } } - } - - /** - * Creates the dominator tree and searches for an solution. - */ - private void createConstantTree(DefUseTree tree) { - ConstantTree constTree = new ConstantTree(lir.getControlFlowGraph(), tree); - constTree.set(Flags.SUBTREE, tree.getBlock()); - tree.forEach(u -> constTree.set(Flags.USAGE, u.getBlock())); - - if (constTree.get(Flags.USAGE, tree.getBlock())) { - // usage in the definition block -> no optimization - usageAtDefinitionSkipped.increment(); - return; - } - constTree.markBlocks(); + /** + * Creates the dominator tree and searches for an solution. + */ + private void createConstantTree(DefUseTree tree) { + ConstantTree constTree = new ConstantTree(lir.getControlFlowGraph(), tree); + constTree.set(Flags.SUBTREE, tree.getBlock()); + tree.forEach(u -> constTree.set(Flags.USAGE, u.getBlock())); - NodeCost cost = ConstantTreeAnalyzer.analyze(constTree, tree.getBlock()); - int usageCount = cost.getUsages().size(); - assert usageCount == tree.usageCount() : "Usage count differs: " + usageCount + " vs. " + tree.usageCount(); - - if (Debug.isLogEnabled()) { - try (Indent i = Debug.logAndIndent("Variable: %s, Block: %s, prob.: %f", tree.getVariable(), tree.getBlock(), tree.getBlock().probability())) { - Debug.log("Usages result: %s", cost); + if (constTree.get(Flags.USAGE, tree.getBlock())) { + // usage in the definition block -> no optimization + usageAtDefinitionSkipped.increment(); + return; } + constTree.markBlocks(); + + NodeCost cost = ConstantTreeAnalyzer.analyze(constTree, tree.getBlock()); + int usageCount = cost.getUsages().size(); + assert usageCount == tree.usageCount() : "Usage count differs: " + usageCount + " vs. " + tree.usageCount(); + + if (Debug.isLogEnabled()) { + try (Indent i = Debug.logAndIndent("Variable: %s, Block: %s, prob.: %f", tree.getVariable(), tree.getBlock(), tree.getBlock().probability())) { + Debug.log("Usages result: %s", cost); + } + + } + + if (cost.getNumMaterializations() > 1 || cost.getBestCost() < tree.getBlock().probability()) { + try (Scope s = Debug.scope("CLOmodify", constTree); Indent i = Debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) { + // mark original load for removal + deleteInstruction(tree); + constantsOptimized.increment(); + + // collect result + createLoads(tree, constTree, tree.getBlock()); + + } catch (Throwable e) { + throw Debug.handle(e); + } + } else { + // no better solution found + materializeAtDefinitionSkipped.increment(); + } + Debug.dump(constTree, "ConstantTree for " + tree.getVariable()); } - if (cost.getNumMaterializations() > 1 || cost.getBestCost() < tree.getBlock().probability()) { - try (Scope s = Debug.scope("CLOmodify", constTree); Indent i = Debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) { - // mark original load for removal - deleteInstruction(tree); - constantsOptimized.increment(); - - // collect result - createLoads(tree, constTree, tree.getBlock()); - - } catch (Throwable e) { - throw Debug.handle(e); - } - } else { - // no better solution found - materializeAtDefinitionSkipped.increment(); - } - Debug.dump(constTree, "ConstantTree for " + tree.getVariable()); - } - - private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlock startBlock) { - Deque> worklist = new ArrayDeque<>(); - worklist.add(startBlock); - while (!worklist.isEmpty()) { - AbstractBlock 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()) { - if (constTree.isMarked(dominated)) { - worklist.addLast(dominated); + private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlock startBlock) { + Deque> worklist = new ArrayDeque<>(); + worklist.add(startBlock); + while (!worklist.isEmpty()) { + AbstractBlock 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()) { + if (constTree.isMarked(dominated)) { + worklist.addLast(dominated); + } } } } } - } - private void insertLoad(JavaConstant constant, LIRKind kind, AbstractBlock 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); - // 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); - Debug.log("patched instruction %s", u.getInstruction()); - } - } - - /** - * Inserts the constant loads created in {@link #createConstantTree} and deletes the original - * definition. - */ - private void rewriteBlock(AbstractBlock block) { - // insert moves - LIRInsertionBuffer buffer = insertionBuffers.get(block); - if (buffer != null) { - assert buffer.initialized() : "not initialized?"; - buffer.finish(); + private void insertLoad(JavaConstant constant, LIRKind kind, AbstractBlock 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); + // 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); + Debug.log("patched instruction %s", u.getInstruction()); + } } - // delete instructions - List instructions = lir.getLIRforBlock(block); - boolean hasDead = false; - for (LIRInstruction inst : instructions) { - if (inst == null) { - hasDead = true; - } else { - inst.setId(-1); + /** + * Inserts the constant loads created in {@link #createConstantTree} and deletes the + * original definition. + */ + private void rewriteBlock(AbstractBlock block) { + // insert moves + LIRInsertionBuffer buffer = insertionBuffers.get(block); + if (buffer != null) { + assert buffer.initialized() : "not initialized?"; + buffer.finish(); + } + + // delete instructions + List instructions = lir.getLIRforBlock(block); + boolean hasDead = false; + for (LIRInstruction inst : instructions) { + if (inst == null) { + hasDead = true; + } else { + inst.setId(-1); + } + } + if (hasDead) { + // Remove null values from the list. + instructions.removeAll(Collections.singleton(null)); } } - if (hasDead) { - // Remove null values from the list. - instructions.removeAll(Collections.singleton(null)); + + private void deleteInstruction(DefUseTree tree) { + AbstractBlock 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) { + LIRInsertionBuffer insertionBuffer = insertionBuffers.get(block); + if (insertionBuffer == null) { + insertionBuffer = new LIRInsertionBuffer(); + insertionBuffers.put(block, insertionBuffer); + assert !insertionBuffer.initialized() : "already initialized?"; + List instructions = lir.getLIRforBlock(block); + insertionBuffer.init(instructions); + } + return insertionBuffer; } } - - private void deleteInstruction(DefUseTree tree) { - AbstractBlock 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) { - LIRInsertionBuffer insertionBuffer = insertionBuffers.get(block); - if (insertionBuffer == null) { - insertionBuffer = new LIRInsertionBuffer(); - insertionBuffers.put(block, insertionBuffer); - assert !insertionBuffer.initialized() : "already initialized?"; - List instructions = lir.getLIRforBlock(block); - insertionBuffer.init(instructions); - } - return insertionBuffer; - } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Sat Feb 21 19:55:33 2015 +0100 @@ -71,14 +71,6 @@ this.cc = cc; } - /** - * Returns true if the redundant move elimination optimization should be done after register - * allocation. - */ - public boolean canEliminateRedundantMoves() { - return true; - } - @Override public TargetDescription target() { return getCodeCache().getTarget(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java Sat Feb 21 19:55:33 2015 +0100 @@ -139,12 +139,6 @@ Value loadNonConst(Value value); /** - * Returns true if the redundant move elimination optimization should be done after register - * allocation. - */ - boolean canEliminateRedundantMoves(); - - /** * Determines if only oop maps are required for the code generated from the LIR. */ boolean needOnlyOopMaps(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,43 @@ +/* + * 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 AllocationPhase extends LIRPhase { + + public static final class AllocationContext { + } + + @Override + protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, AllocationContext context) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder); + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); + +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,109 @@ +/* + * 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 java.util.regex.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.debug.DebugMemUseTracker.Closeable; +import com.oracle.graal.debug.internal.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; + +/** + * Base class for all {@link LIR low-level} phases. Subclasses should be stateless. There will be + * one global instance for each phase that is shared for all compilations. + */ +public abstract class LIRPhase { + + private static final int PHASE_DUMP_LEVEL = 2; + + private CharSequence name; + + /** + * Records time spent within {@link #apply}. + */ + private final DebugTimer timer; + + /** + * Records memory usage within {@link #apply}. + */ + private final DebugMemUseTracker memUseTracker; + + private static final Pattern NAME_PATTERN = Pattern.compile("[A-Z][A-Za-z0-9]+"); + + private static boolean checkName(String name) { + assert name == null || NAME_PATTERN.matcher(name).matches() : "illegal phase name: " + name; + return true; + } + + public LIRPhase() { + timer = Debug.timer("LIRPhaseTime_%s", getClass()); + memUseTracker = Debug.memUseTracker("LIRPhaseMemUse_%s", getClass()); + } + + protected LIRPhase(String name) { + assert checkName(name); + this.name = name; + timer = Debug.timer("LIRPhaseTime_%s", getClass()); + memUseTracker = Debug.memUseTracker("LIRPhaseMemUse_%s", getClass()); + } + + 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()); + } + } catch (Throwable e) { + throw Debug.handle(e); + } + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, C context); + + protected CharSequence createName() { + String className = LIRPhase.this.getClass().getName(); + String s = className.substring(className.lastIndexOf(".") + 1); // strip the package name + if (s.endsWith("Phase")) { + s = s.substring(0, s.length() - "Phase".length()); + } + return s; + } + + public final CharSequence getName() { + if (name == null) { + name = createName(); + } + return name; + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,78 @@ +/* + * 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 LIRPhaseSuite extends LIRPhase { + private final List> phases; + + public LIRPhaseSuite() { + phases = new ArrayList<>(); + } + + /** + * Add a new phase at the beginning of this suite. + */ + public final void prependPhase(LIRPhase phase) { + phases.add(0, phase); + } + + /** + * Add a new phase at the end of this suite. + */ + public final void appendPhase(LIRPhase phase) { + phases.add(phase); + } + + public final ListIterator> findPhase(Class> phaseClass) { + ListIterator> it = phases.listIterator(); + if (findNextPhase(it, phaseClass)) { + return it; + } else { + return null; + } + } + + public static boolean findNextPhase(ListIterator> it, Class> phaseClass) { + while (it.hasNext()) { + LIRPhase phase = it.next(); + if (phaseClass.isInstance(phase)) { + return true; + } + } + return false; + } + + @Override + 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,78 @@ +/* + * 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.api.code.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; +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 preAllocOptStage; + private final LIRPhaseSuite allocStage; + private final LIRPhaseSuite postAllocStage; + + public LIRSuites(LIRPhaseSuite preAllocOptStage, LIRPhaseSuite allocStage, LIRPhaseSuite postAllocStage) { + this.preAllocOptStage = preAllocOptStage; + this.allocStage = allocStage; + this.postAllocStage = postAllocStage; + } + + /** + * {@link PreAllocationOptimizationPhase}s are executed between {@link LIR} generation and + * register allocation. + *

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

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

    + * A {@link PostAllocationOptimizationPhase} must not introduce new {@link Variable}s, + * {@link VirtualStackSlot}s or {@link StackSlot}s. + */ + public LIRPhaseSuite getPostAllocationOptimizationStage() { + return postAllocStage; + } + +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,57 @@ +/* + * 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.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 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 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Sat Feb 21 19:55:33 2015 +0100 @@ -38,6 +38,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.phases.*; import com.oracle.graal.options.*; /** @@ -50,12 +51,12 @@ * {@link OperandFlag#UNINITIALIZED}. Otherwise the stack slot might be reused and its content * destroyed. */ -public final class LSStackSlotAllocator 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 LSStackSlotAllocation = new OptionValue<>(true); + public static final OptionValue LIROptLSStackSlotAllocator = new OptionValue<>(true); // @formatter:on } @@ -66,6 +67,11 @@ private static final DebugTimer AllocateSlotsTimer = Debug.timer("LSStackSlotAllocator[AllocateSlots]"); private static final DebugTimer AssignSlotsTimer = Debug.timer("LSStackSlotAllocator[AssignSlots]"); + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + lirGenRes.buildFrameMap(this); + } + public void allocateStackSlots(FrameMapBuilderTool builder, LIRGenerationResult res) { try (TimerCloseable t = MainTimer.start()) { new Allocator(res.getLIR(), builder).allocate(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,16 +24,24 @@ import static com.oracle.graal.api.code.ValueUtil.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.*; +import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.*; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; -public class SimpleStackSlotAllocator implements StackSlotAllocator { +public class SimpleStackSlotAllocator extends AllocationPhase implements StackSlotAllocator { + + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + lirGenRes.buildFrameMap(this); + } public void allocateStackSlots(FrameMapBuilderTool builder, LIRGenerationResult res) { StackSlot[] mapping = new StackSlot[builder.getNumberOfStackSlots()]; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Sat Feb 21 19:55:33 2015 +0100 @@ -233,26 +233,23 @@ return data; } - public NodeBitMap nodesInLoopFrom(AbstractBeginNode point, AbstractBeginNode until) { + public NodeBitMap nodesInLoopBranch(AbstractBeginNode branch) { Collection blocks = new LinkedList<>(); Collection exits = new LinkedList<>(); Queue work = new LinkedList<>(); ControlFlowGraph cfg = loopsData().controlFlowGraph(); - work.add(cfg.blockFor(point)); - Block untilBlock = until != null ? cfg.blockFor(until) : null; + work.add(cfg.blockFor(branch)); while (!work.isEmpty()) { Block b = work.remove(); - if (b == untilBlock) { - continue; - } if (loop().getExits().contains(b)) { exits.add((LoopExitNode) b.getBeginNode()); - } else if (loop().getBlocks().contains(b)) { + } else { + assert loop().getBlocks().contains(b); blocks.add(b.getBeginNode()); work.addAll(b.getDominated()); } } - return LoopFragment.computeNodes(point.graph(), blocks, exits); + return LoopFragment.computeNodes(branch.graph(), blocks, exits); } public Map getInductionVariables() { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,10 +30,19 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.VirtualState.VirtualClosure; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.debug.*; +import com.oracle.graal.options.*; public abstract class LoopPolicies { + @Option(help = "", type = OptionType.Expert) public static final OptionValue LoopUnswitchMaxIncrease = new OptionValue<>(500); + @Option(help = "", type = OptionType.Expert) public static final OptionValue LoopUnswitchTrivial = new OptionValue<>(10); + @Option(help = "", type = OptionType.Expert) public static final OptionValue LoopUnswitchFrequencyBoost = new OptionValue<>(10.0); + + @Option(help = "", type = OptionType.Expert) public static final OptionValue FullUnrollMaxNodes = new OptionValue<>(300); + @Option(help = "", type = OptionType.Expert) public static final OptionValue FullUnrollMaxIterations = new OptionValue<>(600); + @Option(help = "", type = OptionType.Expert) public static final OptionValue ExactFullUnrollMaxNodes = new OptionValue<>(1200); private LoopPolicies() { // does not need to be instantiated @@ -82,31 +91,57 @@ } public static boolean shouldTryUnswitch(LoopEx loop) { - return loop.loopBegin().unswitches() <= LoopMaxUnswitch.getValue(); + LoopBeginNode loopBegin = loop.loopBegin(); + double loopFrequency = loopBegin.loopFrequency(); + if (loopFrequency <= 1.0) { + return false; + } + return loopBegin.unswitches() <= LoopMaxUnswitch.getValue(); + } + + private static final class CountingClosure implements VirtualClosure { + int count; + + public void apply(VirtualState node) { + count++; + } + } + + private static class IsolatedInitialization { + static final DebugMetric UNSWITCH_SPLIT_WITH_PHIS = Debug.metric("UnswitchSplitWithPhis"); } public static boolean shouldUnswitch(LoopEx loop, List controlSplits) { - int loopTotal = loop.size(); int inBranchTotal = 0; - double maxProbability = 0; + int phis = 0; for (ControlSplitNode controlSplit : controlSplits) { - Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator(); - AbstractBeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null; for (Node successor : controlSplit.successors()) { AbstractBeginNode branch = (AbstractBeginNode) successor; // this may count twice because of fall-through in switches - inBranchTotal += loop.nodesInLoopFrom(branch, postDom).count(); - double probability = controlSplit.probability(branch); - if (probability > maxProbability) { - maxProbability = probability; - } + inBranchTotal += loop.nodesInLoopBranch(branch).count(); + } + Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator(); + if (postDomBlock != null) { + IsolatedInitialization.UNSWITCH_SPLIT_WITH_PHIS.increment(); + phis += ((MergeNode) postDomBlock.getBeginNode()).phis().count(); } } - int netDiff = loopTotal - (inBranchTotal); - double uncertainty = 1 - maxProbability; - int maxDiff = LoopUnswitchMaxIncrease.getValue() + (int) (LoopUnswitchUncertaintyBoost.getValue() * loop.loopBegin().loopFrequency() * uncertainty); - Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of branches", loop, controlSplits, netDiff, maxDiff, (double) (inBranchTotal) / loopTotal * 100); - return netDiff <= maxDiff; + + CountingClosure stateNodesCount = new CountingClosure(); + double loopFrequency = loop.loopBegin().loopFrequency(); + int maxDiff = LoopUnswitchTrivial.getValue() + (int) (LoopUnswitchFrequencyBoost.getValue() * (loopFrequency - 1.0 + phis)); + + maxDiff = Math.min(maxDiff, LoopUnswitchMaxIncrease.getValue()); + int remainingGraphSpace = MaximumDesiredSize.getValue() - loop.loopBegin().graph().getNodeCount(); + maxDiff = Math.min(maxDiff, remainingGraphSpace); + + loop.loopBegin().stateAfter().applyToVirtual(stateNodesCount); + int loopTotal = loop.size() - loop.loopBegin().phis().count() - stateNodesCount.count - 1; + int actualDiff = loopTotal - inBranchTotal; + + Debug.log("shouldUnswitch(%s, %s) : delta=%d (%.2f%% inside of branches), max=%d, f=%.2f, phis=%d -> %b", loop, controlSplits, actualDiff, (double) (inBranchTotal) / loopTotal * 100, maxDiff, + loopFrequency, phis, actualDiff <= maxDiff); + return actualDiff <= maxDiff; } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Sat Feb 21 19:55:33 2015 +0100 @@ -37,22 +37,13 @@ public abstract class LoopTransformations { - private static final int UNROLL_LIMIT = FullUnrollMaxNodes.getValue() * 2; - private LoopTransformations() { // does not need to be instantiated } - public static void invert(LoopEx loop, FixedNode point) { - LoopFragmentInsideBefore head = loop.insideBefore(point); - LoopFragmentInsideBefore duplicate = head.duplicate(); - head.disconnect(); - head.insertBefore(loop); - duplicate.appendInside(loop); - } - public static void peel(LoopEx loop) { loop.inside().duplicate().insertBefore(loop); + loop.loopBegin().setLoopFrequency(Math.max(0.0, loop.loopBegin().loopFrequency() - 1)); } public static void fullUnroll(LoopEx loop, PhaseContext context, CanonicalizerPhase canonicalizer) { @@ -66,7 +57,7 @@ canonicalizer.applyIncremental(graph, context, mark); loopBegin.removeDeadPhis(); loop.invalidateFragments(); - if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) { + if (iterations++ > LoopPolicies.FullUnrollMaxIterations.getValue() || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); } } @@ -77,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); @@ -121,27 +114,6 @@ // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms) } - public static void unroll(LoopEx loop, int factor) { - assert loop.isCounted(); - if (factor > 0) { - throw new UnsupportedOperationException(); - } - // TODO (gd) implement counted loop - LoopFragmentWhole main = loop.whole(); - LoopFragmentWhole prologue = main.duplicate(); - prologue.insertBefore(loop); - // CountedLoopBeginNode counted = prologue.countedLoop(); - // StructuredGraph graph = (StructuredGraph) counted.graph(); - // ValueNode tripCountPrologue = counted.tripCount(); - // ValueNode tripCountMain = counted.tripCount(); - // graph.replaceFloating(tripCountPrologue, "tripCountPrologue % factor"); - // graph.replaceFloating(tripCountMain, "tripCountMain - (tripCountPrologue % factor)"); - LoopFragmentInside inside = loop.inside(); - for (int i = 0; i < factor; i++) { - inside.duplicate().appendInside(loop); - } - } - public static List findUnswitchable(LoopEx loop) { List controls = null; ValueNode invariantValue = null; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopUnswitchingPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,6 +34,7 @@ private static final DebugMetric UNSWITCHED = Debug.metric("Unswitched"); private static final DebugMetric UNSWITCH_CANDIDATES = Debug.metric("UnswitchCandidates"); + private static final DebugMetric UNSWITCH_EARLY_REJECTS = Debug.metric("UnswitchEarlyRejects"); @Override protected void run(StructuredGraph graph) { @@ -42,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) { @@ -57,6 +58,8 @@ break; } } + } else { + UNSWITCH_EARLY_REJECTS.increment(); } } } while (unswitched); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeProcessor.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeVerifier.java --- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeVerifier.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeVerifier.java Sat Feb 21 19:55:33 2015 +0100 @@ -117,7 +117,7 @@ List annotations = field.getAnnotationMirrors(); - boolean isNonOptionalInput = findAnnotationMirror(annotations, Input) != null; + boolean isNonOptionalInput = findAnnotationMirror(annotations, Input.asType()) != null; boolean isOptionalInput = findAnnotationMirror(annotations, OptionalInput) != null; boolean isSuccessor = findAnnotationMirror(annotations, Successor) != null; diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; /** * This class tests that integer stamps are created correctly for constants. @@ -45,7 +46,7 @@ @Before public void before() { - graph = new StructuredGraph(); + graph = new StructuredGraph(AllowAssumptions.YES); } @Test diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.compiler.test.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -56,10 +57,10 @@ @Test public void test() { - StructuredGraph graph = parseEager("loopSnippet"); + StructuredGraph graph = parseEager("loopSnippet", AllowAssumptions.YES); NodePredicate loopPhis = node -> node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode; - PhaseContext context = new PhaseContext(getProviders(), null); + PhaseContext context = new PhaseContext(getProviders()); Assert.assertEquals(5, graph.getNodes().filter(loopPhis).count()); new CanonicalizerPhase(false).apply(graph, context); Assert.assertEquals(2, graph.getNodes().filter(loopPhis).count()); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -29,6 +29,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; /** * This class tests that the canonicalization for constant negate nodes cover all cases. @@ -39,7 +40,7 @@ @Before public void before() { - graph = new StructuredGraph(); + graph = new StructuredGraph(AllowAssumptions.YES); } @Test diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -38,12 +38,14 @@ @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 diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Sat Feb 21 19:55:33 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; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -23,12 +23,14 @@ 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.spi.*; @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(DeoptimizeNode.class); protected final DeoptimizationAction action; protected final DeoptimizationReason reason; protected final int debugId; @@ -39,7 +41,7 @@ } 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; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Sat Feb 21 19:55:33 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; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -47,7 +47,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 +71,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; @@ -189,6 +190,10 @@ return; } + if (splitIfAtPhi(tool)) { + return; + } + if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) { AbstractBeginNode intermediateBegin = falseSuccessor(); IfNode nextIf = (IfNode) intermediateBegin.next(); @@ -230,7 +235,7 @@ 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)) { falseNext.replaceAtUsages(trueNext); @@ -239,7 +244,7 @@ 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) { @@ -361,6 +366,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; @@ -378,44 +393,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; } } @@ -472,6 +451,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()); @@ -512,7 +601,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) { @@ -555,6 +643,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) { @@ -602,6 +693,137 @@ } /** + * Take an if that is immediately dominated by a merge with a single phi and split off any paths + * where the test would be statically decidable creating a new merge below the approriate side + * of the IfNode. Any undecidable tests will continue to use the original IfNode. + * + * @param tool + */ + @SuppressWarnings("unchecked") + private boolean splitIfAtPhi(SimplifierTool tool) { + if (!(predecessor() instanceof MergeNode)) { + return false; + } + MergeNode merge = (MergeNode) predecessor(); + if (merge.forwardEndCount() == 1) { + // Don't bother. + return false; + } + if (merge.usages().count() != 1 || merge.phis().count() != 1) { + return false; + } + if (merge.stateAfter() != null) { + /* We'll get the chance to simplify this after frame state assignment. */ + return false; + } + PhiNode phi = merge.phis().first(); + if (phi.usages().count() != 1 || condition().usages().count() != 1) { + /* + * For simplicity the below code assumes assumes the phi goes dead at the end so skip + * this case. + */ + return false; + } + + if (condition() instanceof Canonicalizable.Unary) { + Canonicalizable.Unary unary = (Canonicalizable.Unary) condition(); + if (unary.getValue() != phi) { + return false; + } + } else if (condition() instanceof Canonicalizable.Binary) { + Canonicalizable.Binary binary = (Canonicalizable.Binary) condition(); + if (binary.getX() != phi && binary.getY() != phi) { + return false; + } + } else { + return false; + } + + /* + * We could additionally filter for the case that at least some of the Phi inputs or one of + * the condition inputs are constants but there are cases where a non-constant is + * simplifiable, usually where the stamp allows the question to be answered. + */ + + /* Each successor of the if gets a new merge if needed. */ + MergeNode trueMerge = null; + MergeNode falseMerge = null; + assert merge.stateAfter() == null; + + for (EndNode end : merge.forwardEnds().snapshot()) { + Node value = phi.valueAt(end); + Node result = null; + if (condition() instanceof Canonicalizable.Binary) { + Canonicalizable.Binary compare = (Canonicalizable.Binary) condition; + if (compare.getX() == phi) { + result = compare.canonical(tool, value, compare.getY()); + } else { + result = compare.canonical(tool, compare.getX(), value); + } + } else { + assert condition() instanceof Canonicalizable.Unary; + Canonicalizable.Unary compare = (Canonicalizable.Unary) condition; + result = compare.canonical(tool, value); + } + if (result instanceof LogicConstantNode) { + merge.removeEnd(end); + if (((LogicConstantNode) result).getValue()) { + if (trueMerge == null) { + trueMerge = insertMerge(trueSuccessor()); + } + trueMerge.addForwardEnd(end); + } else { + if (falseMerge == null) { + falseMerge = insertMerge(falseSuccessor()); + } + falseMerge.addForwardEnd(end); + } + } + } + + cleanupMerge(tool, merge); + cleanupMerge(tool, trueMerge); + cleanupMerge(tool, falseMerge); + + return true; + } + + private void cleanupMerge(SimplifierTool tool, MergeNode merge) { + if (merge != null && merge.isAlive()) { + if (merge.forwardEndCount() == 0) { + GraphUtil.killCFG(merge, tool); + } else if (merge.forwardEndCount() == 1) { + graph().reduceTrivialMerge(merge); + } + } + } + + private MergeNode insertMerge(AbstractBeginNode begin) { + MergeNode merge = graph().add(new MergeNode()); + if (!begin.anchored().isEmpty()) { + Object before = null; + before = begin.anchored().snapshot(); + begin.replaceAtUsages(InputType.Guard, merge); + begin.replaceAtUsages(InputType.Anchor, merge); + assert begin.anchored().isEmpty() : before + " " + begin.anchored().snapshot(); + } + + AbstractBeginNode theBegin = begin; + if (begin instanceof LoopExitNode) { + // Insert an extra begin to make it easier. + theBegin = graph().add(new BeginNode()); + begin.replaceAtPredecessor(theBegin); + theBegin.setNext(begin); + } + FixedNode next = theBegin.next(); + next.replaceAtPredecessor(merge); + theBegin.setNext(graph().add(new EndNode())); + merge.addForwardEnd((EndNode) theBegin.next()); + merge.setNext(next); + return merge; + } + + /** * Tries to connect code that initializes a variable directly with the successors of an if * construct that switches on the variable. For example, the pseudo code below: * @@ -684,7 +906,7 @@ } } - List mergePredecessors = merge.cfgPredecessors().snapshot(); + List mergePredecessors = merge.cfgPredecessors().snapshot(); assert phi.valueCount() == merge.forwardEndCount(); Constant[] xs = constantValues(compare.getX(), merge, false); @@ -698,8 +920,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(); @@ -708,9 +930,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); @@ -840,7 +1062,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); @@ -854,7 +1076,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Sat Feb 21 19:55:33 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,10 @@ */ @NodeInfo public final class MergeNode extends AbstractMergeNode { + + public static final NodeClass TYPE = NodeClass.create(MergeNode.class); + public MergeNode() { + super(TYPE); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Sat Feb 21 19:55:33 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,14 +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) { - super(stamp); - this.piStamp = stamp; - this.object = object; + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Sat Feb 21 19:55:33 2015 +0100 @@ -25,6 +25,8 @@ import java.util.*; import java.util.concurrent.atomic.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -80,6 +82,17 @@ } } + /** + * Constants denoting whether or not {@link Assumption}s can be made while processing a graph. + */ + public enum AllowAssumptions { + YES, + NO; + public static AllowAssumptions from(boolean flag) { + return flag ? YES : NO; + } + } + public static final int INVOCATION_ENTRY_BCI = -1; public static final long INVALID_GRAPH_ID = -1; @@ -94,40 +107,51 @@ private boolean hasValueProxies = true; /** + * The assumptions made while constructing and transforming this graph. + */ + private final Assumptions assumptions; + + /** + * The methods that were inlined while constructing this graph. + */ + private Set inlinedMethods = new HashSet<>(); + + /** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() * start} node. */ - public StructuredGraph() { - this(null, null); + public StructuredGraph(AllowAssumptions allowAssumptions) { + this(null, null, allowAssumptions); } /** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() * start} node. */ - public StructuredGraph(String name, ResolvedJavaMethod method) { - this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI); + public StructuredGraph(String name, ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI, allowAssumptions); } - public StructuredGraph(ResolvedJavaMethod method) { - this(null, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI); + public StructuredGraph(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + this(null, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI, allowAssumptions); } - public StructuredGraph(ResolvedJavaMethod method, int entryBCI) { - this(null, method, uniqueGraphIds.incrementAndGet(), entryBCI); + public StructuredGraph(ResolvedJavaMethod method, int entryBCI, AllowAssumptions allowAssumptions) { + this(null, method, uniqueGraphIds.incrementAndGet(), entryBCI, allowAssumptions); } - private StructuredGraph(String name, ResolvedJavaMethod method, long graphId, int entryBCI) { + private StructuredGraph(String name, ResolvedJavaMethod method, long graphId, int entryBCI, AllowAssumptions allowAssumptions) { super(name); this.setStart(add(new StartNode())); this.method = method; this.graphId = graphId; this.entryBCI = entryBCI; + this.assumptions = allowAssumptions == AllowAssumptions.YES ? new Assumptions() : null; } 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) { @@ -196,7 +220,17 @@ } public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod) { - StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI); + return copy(newName, newMethod, AllowAssumptions.from(assumptions != null), isInlinedMethodRecordingEnabled()); + } + + public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod, AllowAssumptions allowAssumptions, boolean enableInlinedMethodRecording) { + StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI, allowAssumptions); + if (allowAssumptions == AllowAssumptions.YES && assumptions != null) { + copy.assumptions.record(assumptions); + } + if (!enableInlinedMethodRecording) { + copy.disableInlinedMethodRecording(); + } copy.setGuardsStage(getGuardsStage()); copy.isAfterFloatingReadPhase = isAfterFloatingReadPhase; copy.hasValueProxies = hasValueProxies; @@ -212,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; } @@ -221,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; @@ -265,7 +299,7 @@ } public boolean hasLoops() { - return hasNode(LoopBeginNode.class); + return hasNode(LoopBeginNode.TYPE); } public void removeFloating(FloatingNode node) { @@ -467,4 +501,37 @@ assert !state : "cannot 'unapply' value proxy removal on graph"; hasValueProxies = state; } + + /** + * Gets the object for recording assumptions while constructing of this graph. + * + * @return {@code null} if assumptions cannot be made for this graph + */ + public Assumptions getAssumptions() { + return assumptions; + } + + /** + * Disables recording of methods inlined while constructing this graph. This can be done at most + * once and must be done before any inlined methods are recorded. + */ + public void disableInlinedMethodRecording() { + assert inlinedMethods != null : "cannot disable inlined method recording more than once"; + assert inlinedMethods.isEmpty() : "cannot disable inlined method recording once methods have been recorded"; + inlinedMethods = null; + } + + public boolean isInlinedMethodRecordingEnabled() { + return inlinedMethods != null; + } + + /** + * Gets the methods that were inlined while constructing this graph. + * + * @return {@code null} if inlined method recording has been + * {@linkplain #disableInlinedMethodRecording() disabled} + */ + public Set getInlinedMethods() { + return inlinedMethods; + } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java Sat Feb 21 19:55:33 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.Add; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -35,8 +36,14 @@ @NodeInfo(shortName = "+") public class AddNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { + 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) { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Sat Feb 21 19:55:33 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,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.And; +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.*; @@ -36,8 +38,21 @@ @NodeInfo(shortName = "&") public final class AndNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { + 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); + } } @Override diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -39,13 +39,15 @@ @NodeInfo public abstract class BinaryArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { + @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; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Sat Feb 21 19:55:33 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.*; @@ -39,6 +40,7 @@ @NodeInfo public abstract class CompareNode extends BinaryOpLogicNode { + 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()); } } @@ -165,32 +167,33 @@ return null; } - public static CompareNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { - return graph.unique(createCompareNode(condition, x, y)); + public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { + LogicNode result = createCompareNode(condition, x, y, constantReflection); + return (result.graph() == null ? graph.unique(result) : result); } - public static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) { + public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { assert x.getKind() == y.getKind(); assert condition.isCanonical() : "condition is not canonical: " + condition; assert !x.getKind().isNumericFloat(); - CompareNode comparison; + LogicNode comparison; if (condition == Condition.EQ) { if (x.stamp() instanceof AbstractObjectStamp) { - comparison = new ObjectEqualsNode(x, y); + comparison = ObjectEqualsNode.create(x, y, constantReflection); } else if (x.stamp() instanceof AbstractPointerStamp) { comparison = new PointerEqualsNode(x, y); } else { assert x.getKind().isNumericInteger(); - comparison = new IntegerEqualsNode(x, y); + comparison = IntegerEqualsNode.create(x, y, constantReflection); } } else if (condition == Condition.LT) { assert x.getKind().isNumericInteger(); - comparison = new IntegerLessThanNode(x, y); + comparison = IntegerLessThanNode.create(x, y, constantReflection); } else { assert condition == Condition.BT; assert x.getKind().isNumericInteger(); - comparison = new IntegerBelowNode(x, y); + comparison = IntegerBelowNode.create(x, y, constantReflection); } return comparison; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Sat Feb 21 19:55:33 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,13 +55,25 @@ } 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; this.falseValue = falseValue; } + public static ValueNode create(LogicNode condition) { + return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph())); + } + + public static ValueNode create(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { + ValueNode synonym = findSynonym(condition, trueValue, falseValue); + if (synonym != null) { + return synonym; + } + return new ConditionalNode(condition, trueValue, falseValue); + } + @Override public boolean inferStamp() { return updateStamp(trueValue.stamp().meet(falseValue.stamp())); @@ -75,9 +89,9 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - if (condition instanceof LogicNegationNode) { - LogicNegationNode negated = (LogicNegationNode) condition; - return new ConditionalNode(negated.getValue(), falseValue(), trueValue()); + ValueNode synonym = findSynonym(condition, trueValue(), falseValue()); + if (synonym != null) { + return synonym; } // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1 @@ -92,14 +106,6 @@ } } } - if (condition instanceof LogicConstantNode) { - LogicConstantNode c = (LogicConstantNode) condition; - if (c.getValue()) { - return trueValue(); - } else { - return falseValue(); - } - } if (condition instanceof CompareNode && ((CompareNode) condition).condition() == Condition.EQ) { // optimize the pattern (x == y) ? x : y CompareNode compare = (CompareNode) condition; @@ -114,13 +120,29 @@ return this; } + private static ValueNode findSynonym(ValueNode condition, ValueNode trueValue, ValueNode falseValue) { + if (condition instanceof LogicNegationNode) { + LogicNegationNode negated = (LogicNegationNode) condition; + return ConditionalNode.create(negated.getValue(), falseValue, trueValue); + } + if (condition instanceof LogicConstantNode) { + LogicConstantNode c = (LogicConstantNode) condition; + if (c.getValue()) { + return trueValue; + } else { + return falseValue; + } + } + return null; + } + @Override public void generate(NodeLIRBuilderTool generator) { generator.emitConditional(this); } public ConditionalNode(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { - this(createCompareNode(graph, condition, x, y)); + this(createCompareNode(graph, condition, x, y, null)); } public ConditionalNode(ValueNode type, ValueNode object) { @@ -137,4 +159,24 @@ public static boolean materializeIsInstance(Class mirror, Object object) { return mirror.isInstance(object); } + + /** + * @param thisClass + * @param otherClass + * @param dummy a marker to make this constructor unique for the + * {@link #materializeIsAssignableFrom(Class, Class, int)} NodeIntrinsic + */ + public ConditionalNode(ValueNode thisClass, ValueNode otherClass, int dummy) { + this(thisClass.graph().unique(new ClassIsAssignableFromNode(thisClass, otherClass))); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + private static boolean materializeIsAssignableFrom(Class thisClass, Class otherClass, @ConstantNodeParameter int dummy) { + return thisClass.isAssignableFrom(otherClass); + } + + public static boolean materializeIsAssignableFrom(Class thisClass, Class otherClass) { + return materializeIsAssignableFrom(thisClass, otherClass, 0); + } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Sat Feb 21 19:55:33 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.*; @@ -33,9 +34,10 @@ @NodeInfo(shortName = "==") public final class FloatEqualsNode extends CompareNode { + 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()); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Sat Feb 21 19:55:33 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)); + return LogicNegationNode.create(CompareNode.createCompareNode(Condition.EQ, forX, forY, tool.getConstantReflection())); } return this; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Sat Feb 21 19:55:33 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 @@ -33,10 +33,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,7 +95,7 @@ } if (next() instanceof IntegerDivNode) { - NodeClass nodeClass = getNodeClass(); + NodeClass nodeClass = getNodeClass(); if (next().getClass() == this.getClass() && nodeClass.getEdges(Inputs).areEqualIn(this, next()) && valueEquals(next())) { return next(); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Sat Feb 21 19:55:33 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.*; @@ -33,9 +34,10 @@ @NodeInfo(shortName = "==") public final class IntegerEqualsNode extends CompareNode { + 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,6 +47,24 @@ if (result != null) { return result; } else { + 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); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Sat Feb 21 19:55:33 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.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,11 @@ * both x and y. */ @NodeInfo -public class IntegerTestNode extends BinaryOpLogicNode { +public final class IntegerTestNode extends BinaryOpLogicNode { + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java Sat Feb 21 19:55:33 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,7 +26,8 @@ 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.Mul; +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,25 @@ @NodeInfo(shortName = "*") public class MulNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { + 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); + } } @Override @@ -59,33 +77,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Sat Feb 21 19:55:33 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,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.Or; +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.*; @@ -34,10 +36,23 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|") -public class OrNode extends BinaryArithmeticNode { +public final class OrNode extends BinaryArithmeticNode { + + 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); + } } @Override diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,6 +24,7 @@ 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.*; @@ -32,8 +33,14 @@ @NodeInfo(shortName = "==") public class PointerEqualsNode extends CompareNode { + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java Sat Feb 21 19:55:33 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,8 @@ 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.Sub; +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,25 @@ @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) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getSub(); + Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + if (tryConstantFold != null) { + return tryConstantFold; + } else { + return new SubNode(x, y); + } } @SuppressWarnings("hiding") diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Sat Feb 21 19:55:33 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,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.Xor; +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.*; @@ -34,13 +36,26 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "^") -public class XorNode extends BinaryArithmeticNode { +public final class XorNode extends BinaryArithmeticNode { + + 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); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { ValueNode ret = super.canonical(tool, forX, forY); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Sat Feb 21 19:55:33 2015 +0100 @@ -118,48 +118,45 @@ return loops; } - public void clearNodeToBlock() { - nodeToBlock.clear(); - for (Block block : reversePostOrder) { - identifyBlock(block); - } - } - private void identifyBlock(Block block) { - Node cur = block.getBeginNode(); - Node last; + AbstractBeginNode start = block.getBeginNode(); // assign proxies of a loop exit to this block - if (cur instanceof AbstractBeginNode) { - for (Node usage : cur.usages()) { + if (start instanceof LoopExitNode) { + for (Node usage : start.usages()) { if (usage instanceof ProxyNode) { nodeToBlock.set(usage, block); } } + } else if (start instanceof AbstractMergeNode) { + for (PhiNode phi : ((AbstractMergeNode) start).phis()) { + nodeToBlock.set(phi, block); + } } - do { + FixedWithNextNode cur = start; + while (true) { assert !cur.isDeleted(); - assert nodeToBlock.get(cur) == null; nodeToBlock.set(cur, block); - if (cur instanceof AbstractMergeNode) { - for (PhiNode phi : ((AbstractMergeNode) cur).phis()) { - nodeToBlock.set(phi, block); - } + FixedNode next = cur.next(); + if (next instanceof AbstractBeginNode) { + block.endNode = cur; + return; + } else if (next instanceof FixedWithNextNode) { + cur = (FixedWithNextNode) next; + } else { + nodeToBlock.set(next, block); + block.endNode = next; + return; } - - last = cur; - cur = cur.successors().first(); - } while (cur != null && !(cur instanceof AbstractBeginNode)); - - block.endNode = (FixedNode) last; + } } 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); @@ -203,14 +200,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; } } @@ -225,6 +227,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); } } } @@ -233,19 +239,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); } } @@ -269,29 +265,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("Unexpected loop exit with %s, including whole branch in the loop", sux); - unexpected.add(sux); + Debug.log(3, "Unexpected loop exit with %s, including whole branch in the loop", 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/BlackholeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/OpaqueNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/VerifyHeapNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Sat Feb 21 19:55:33 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; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Sat Feb 21 19:55:33 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; } @@ -52,6 +54,6 @@ @Override public void generate(NodeLIRBuilderTool gen) { Value addr = getLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(getObject())); - gen.setResult(this, addr); + gen.setResult(this, gen.getLIRGeneratorTool().asAllocatable(addr)); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Sat Feb 21 19:55:33 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; } @@ -73,10 +75,10 @@ ResolvedJavaType exactType; if (objectStamp.isExactType()) { exactType = objectStamp.type(); - } else if (objectStamp.type() != null && tool.assumptions().useOptimisticAssumptions()) { + } else if (objectStamp.type() != null && graph().getAssumptions() != null) { exactType = objectStamp.type().findUniqueConcreteSubtype(); if (exactType != null) { - tool.assumptions().recordConcreteSubtype(objectStamp.type(), exactType); + graph().getAssumptions().recordConcreteSubtype(objectStamp.type(), exactType); } } else { exactType = null; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Sat Feb 21 19:55:33 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.extended; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -35,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; @@ -46,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; @@ -68,10 +70,11 @@ if (StampTool.isExactType(object)) { return resolveExactMethod(tool, type); } - if (type != null && tool.assumptions().useOptimisticAssumptions()) { + Assumptions assumptions = graph().getAssumptions(); + if (type != null && assumptions != null) { ResolvedJavaMethod resolvedMethod = type.findUniqueConcreteMethod(method); if (resolvedMethod != null && !type.isInterface() && method.getDeclaringClass().isAssignableFrom(type)) { - tool.assumptions().recordConcreteMethod(method, type, resolvedMethod); + assumptions.recordConcreteMethod(method, type, resolvedMethod); return ConstantNode.forConstant(stamp(), resolvedMethod.getEncoding(), tool.getMetaAccess()); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Sat Feb 21 19:55:33 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.*; @@ -31,15 +32,24 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable { +public final class UnboxNode extends UnaryNode implements Virtualizable, Lowerable { + public static final NodeClass TYPE = NodeClass.create(UnboxNode.class); protected final Kind boxingKind; - public UnboxNode(ValueNode value, Kind boxingKind) { - super(StampFactory.forKind(boxingKind.getStackKind()), value); + protected UnboxNode(ValueNode value, Kind boxingKind) { + super(TYPE, StampFactory.forKind(boxingKind.getStackKind()), value); this.boxingKind = boxingKind; } + public static ValueNode create(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode value, Kind boxingKind) { + ValueNode synonym = findSynonym(metaAccess, constantReflection, value, boxingKind); + if (synonym != null) { + return synonym; + } + return new UnboxNode(value, boxingKind); + } + public Kind getBoxingKind() { return boxingKind; } @@ -63,11 +73,19 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode synonym = findSynonym(tool.getMetaAccess(), tool.getConstantReflection(), forValue, boxingKind); + if (synonym != null) { + return synonym; + } + return this; + } + + private static ValueNode findSynonym(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode forValue, Kind boxingKind) { if (forValue.isConstant()) { JavaConstant constant = forValue.asJavaConstant(); - JavaConstant unboxed = tool.getConstantReflection().unboxPrimitive(constant); + JavaConstant unboxed = constantReflection.unboxPrimitive(constant); if (unboxed != null && unboxed.getKind() == boxingKind) { - return ConstantNode.forConstant(unboxed, tool.getMetaAccess()); + return ConstantNode.forConstant(unboxed, metaAccess); } } else if (forValue instanceof BoxNode) { BoxNode box = (BoxNode) forValue; @@ -75,7 +93,7 @@ return box.getValue(); } } - return this; + return null; } @NodeIntrinsic diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Sat Feb 21 19:55:33 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,11 +49,16 @@ } public ArrayLengthNode(ValueNode array) { - super(StampFactory.positiveInt()); + super(TYPE, StampFactory.positiveInt()); this.array = array; } public static ValueNode create(ValueNode forValue, ConstantReflectionProvider constantReflection) { + if (forValue instanceof NewArrayNode) { + NewArrayNode newArray = (NewArrayNode) forValue; + return newArray.length(); + } + ValueNode length = readArrayLengthConstant(forValue, constantReflection); if (length != null) { return length; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,6 +26,7 @@ import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.type.*; @@ -43,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; @@ -54,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; @@ -62,6 +64,22 @@ this.forStoreCheck = forStoreCheck; } + public static ValueNode create(ResolvedJavaType inputType, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck, Assumptions assumptions) { + ResolvedJavaType type = inputType; + ValueNode synonym = findSynonym(type, object); + if (synonym != null) { + return synonym; + } + if (assumptions != null) { + ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); + if (uniqueConcreteType != null && !uniqueConcreteType.equals(type)) { + assumptions.recordConcreteSubtype(type, uniqueConcreteType); + type = uniqueConcreteType; + } + } + return new CheckCastNode(type, object, profile, forStoreCheck); + } + public boolean isForStoreCheck() { return forStoreCheck; } @@ -144,22 +162,17 @@ @Override public Node canonical(CanonicalizerTool tool) { - ResolvedJavaType objectType = StampTool.typeOrNull(object()); - if (objectType != null && type.isAssignableFrom(objectType)) { - // we don't have to check for null types here because they will also pass the - // checkcast. - return object(); + ValueNode synonym = findSynonym(type, object()); + if (synonym != null) { + return synonym; } - if (StampTool.isPointerAlwaysNull(object())) { - return object(); - } - - if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { + Assumptions assumptions = graph().getAssumptions(); + if (assumptions != null) { ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); if (exactType != null && !exactType.equals(type)) { // Propagate more precise type information to usages of the checkcast. - tool.assumptions().recordConcreteSubtype(type, exactType); + assumptions.recordConcreteSubtype(type, exactType); return new CheckCastNode(exactType, object, profile, forStoreCheck); } } @@ -167,6 +180,20 @@ return this; } + private static ValueNode findSynonym(ResolvedJavaType type, ValueNode object) { + ResolvedJavaType objectType = StampTool.typeOrNull(object); + if (objectType != null && type.isAssignableFrom(objectType)) { + // we don't have to check for null types here because they will also pass the + // checkcast. + return object; + } + + if (StampTool.isPointerAlwaysNull(object)) { + return object; + } + return null; + } + @Override public void simplify(SimplifierTool tool) { // if the previous node is also a checkcast, with a less precise and compatible type, diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ClassIsAssignableFromNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ClassIsAssignableFromNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,86 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * The {@code ClassIsAssignableFromNode} represents a type check against {@link Class} instead of + * against instances. This is used, for instance, to intrinsify + * {@link Class#isAssignableFrom(Class)} . + */ +@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; + } + + public Object getThisClass() { + return thisClass; + } + + public Object getOtherClass() { + return otherClass; + } + + @Override + public ValueNode getX() { + return thisClass; + } + + @Override + public ValueNode getY() { + return otherClass; + } + + @Override + public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + ConstantReflectionProvider constantReflection = tool.getConstantReflection(); + ResolvedJavaType thisType = constantReflection.asJavaType(forX.asJavaConstant()); + ResolvedJavaType otherType = constantReflection.asJavaType(forY.asJavaConstant()); + if (thisType != null && otherType != null) { + return LogicConstantNode.forBoolean(thisType.isAssignableFrom(otherType)); + } + } + return this; + } + + @Override + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } + +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Sat Feb 21 19:55:33 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,8 +22,10 @@ */ package com.oracle.graal.nodes.java; +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,18 +36,29 @@ * 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; } + public static LogicNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { + ObjectStamp objectStamp = (ObjectStamp) object.stamp(); + LogicNode constantValue = findSynonym(type, objectStamp.type(), objectStamp.nonNull(), objectStamp.isExactType()); + if (constantValue != null) { + return constantValue; + } else { + return new InstanceOfNode(type, object, profile); + } + } + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); @@ -67,12 +80,13 @@ if (result != null) { return result; } - if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { + Assumptions assumptions = graph().getAssumptions(); + if (assumptions != null) { ResolvedJavaType exact = stampType.findUniqueConcreteSubtype(); if (exact != null) { result = checkInstanceOf(forValue, exact, objectStamp.nonNull(), true); if (result != null) { - tool.assumptions().recordConcreteSubtype(stampType, exact); + assumptions.recordConcreteSubtype(stampType, exact); return result; } } @@ -82,7 +96,25 @@ } private ValueNode checkInstanceOf(ValueNode forValue, ResolvedJavaType inputType, boolean nonNull, boolean exactType) { - boolean subType = type().isAssignableFrom(inputType); + ValueNode result = findSynonym(type(), inputType, nonNull, exactType); + if (result != null) { + return result; + } + if (type().isAssignableFrom(inputType)) { + if (!nonNull) { + // the instanceof matches if the object is non-null, so return true + // depending on the null-ness. + return LogicNegationNode.create(new IsNullNode(forValue)); + } + } + return null; + } + + public static LogicNode findSynonym(ResolvedJavaType type, ResolvedJavaType inputType, boolean nonNull, boolean exactType) { + if (inputType == null) { + return null; + } + boolean subType = type.isAssignableFrom(inputType); if (subType) { if (nonNull) { // the instanceOf matches, so return true @@ -95,21 +127,14 @@ // also make the check fail. return LogicConstantNode.contradiction(); } else { - boolean superType = inputType.isAssignableFrom(type()); - if (!superType && !inputType.isInterface() && !type().isInterface()) { + boolean superType = inputType.isAssignableFrom(type); + if (!superType && !inputType.isInterface() && !type.isInterface()) { return LogicConstantNode.contradiction(); } // since the subtype comparison was only performed on a declared type we don't // really know if it might be true at run time... } } - if (type().isAssignableFrom(inputType)) { - 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 null; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Sat Feb 21 19:55:33 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; } @@ -94,7 +99,7 @@ } } - public static ResolvedJavaMethod findSpecialCallTarget(InvokeKind invokeKind, ValueNode receiver, ResolvedJavaMethod targetMethod, Assumptions assumptions, ResolvedJavaType contextType) { + public static ResolvedJavaMethod findSpecialCallTarget(InvokeKind invokeKind, ValueNode receiver, ResolvedJavaMethod targetMethod, ResolvedJavaType contextType) { if (invokeKind.isDirect()) { return null; } @@ -119,7 +124,8 @@ if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { return resolvedMethod; } - if (assumptions != null && assumptions.useOptimisticAssumptions()) { + Assumptions assumptions = receiver.graph().getAssumptions(); + if (assumptions != null) { ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); if (uniqueConcreteType != null) { ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod, contextType); @@ -144,7 +150,7 @@ public void simplify(SimplifierTool tool) { // attempt to devirtualize the call ResolvedJavaType contextType = (invoke().stateAfter() == null && invoke().stateDuring() == null) ? null : invoke().getContextType(); - ResolvedJavaMethod specialCallTarget = findSpecialCallTarget(invokeKind, receiver(), targetMethod, tool.assumptions(), contextType); + ResolvedJavaMethod specialCallTarget = findSpecialCallTarget(invokeKind, receiver(), targetMethod, contextType); if (specialCallTarget != null) { this.setTargetMethod(specialCallTarget); setInvokeKind(InvokeKind.Special); @@ -242,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Sat Feb 21 19:55:33 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; } @@ -67,7 +69,7 @@ } else if (objectStamp.type() != null && !objectStamp.type().hasFinalizableSubclass()) { // if either the declared type of receiver or the holder // can be assumed to have no finalizers - if (assumptions.useOptimisticAssumptions()) { + if (assumptions != null) { assumptions.recordNoFinalizableSubclassAssumption(objectStamp.type()); return false; } @@ -80,7 +82,7 @@ if (!(forValue.stamp() instanceof ObjectStamp)) { return this; } - if (!mayHaveFinalizer(forValue, tool.assumptions())) { + if (!mayHaveFinalizer(forValue, graph().getAssumptions())) { return null; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.spi; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -43,8 +42,6 @@ GuardingNode createGuard(FixedNode before, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated); - Assumptions assumptions(); - /** * Gets the closest fixed node preceding the node currently being lowered. */ diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/PiPushable.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,7 +30,7 @@ public interface PiPushable { /** - * + * * @param parent PiNode * @return true if node was moved */ diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Sat Feb 21 19:55:33 2015 +0100 @@ -25,7 +25,6 @@ import java.lang.reflect.*; import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; @@ -74,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 @@ -83,11 +89,6 @@ Class getMacroSubstitution(ResolvedJavaMethod method); /** - * Gets the assumptions with which replacement graphs are preprocessed. - */ - Assumptions getAssumptions(); - - /** * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution * macro} substitutions defined by a given class. * diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Virtualizable.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableAllocation.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizableRoot.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -35,7 +34,7 @@ /** * This tool can be used to query the current state (normal/virtualized/re-materialized) of values * and to describe the actions that would be taken for this state. - * + * * See also {@link Virtualizable}. */ public interface VirtualizerTool { @@ -52,15 +51,9 @@ ConstantReflectionProvider getConstantReflectionProvider(); /** - * @return the {@link Assumptions} associated with the current compilation, which can be used to - * make type assumptions during virtualization. - */ - Assumptions getAssumptions(); - - /** * This method should be used to query the maximum size of virtualized objects before attempting * virtualization. - * + * * @return the maximum number of entries for virtualized objects. */ int getMaximumEntryCount(); @@ -69,7 +62,7 @@ /** * Introduces a new virtual object to the current state. - * + * * @param virtualObject the new virtual object. * @param entryState the initial state of the virtual object's fields. * @param locks the initial locking depths. @@ -79,7 +72,7 @@ /** * Queries the current state of the given value: if it is virtualized (thread-local and the * compiler knows all entries) or not. - * + * * @param value the value whose state should be queried. * @return the {@link State} representing the value if it has been virtualized at some point, * null otherwise. @@ -88,7 +81,7 @@ /** * Sets the entry (field or array element) with the given index in the virtualized object. - * + * * @param state the state. * @param index the index to be set. * @param value the new value for the given index. @@ -102,7 +95,7 @@ * Replacements via {@link #replaceWithValue(ValueNode)} are not immediately committed. This * method can be used to determine if a value was replaced by another one (e.g., a load field by * the loaded value). - * + * * @param original the original input value. * @return the replacement value, or the original value if there is no replacement. */ @@ -112,14 +105,14 @@ /** * Deletes the current node and replaces it with the given virtualized object. - * + * * @param virtual the virtualized object that should replace the current node. */ void replaceWithVirtual(VirtualObjectNode virtual); /** * Deletes the current node and replaces it with the given value. - * + * * @param replacement the value that should replace the current node. */ void replaceWithValue(ValueNode replacement); @@ -131,7 +124,7 @@ /** * Replaces an input of the current node. - * + * * @param oldInput the old input value. * @param replacement the new input value. */ @@ -140,7 +133,7 @@ /** * Adds the given node to the graph.This action will only be performed when, and if, the changes * are committed. - * + * * @param node the node to add. */ void addNode(ValueNode node); @@ -148,7 +141,7 @@ /** * This method performs either {@link #replaceWithValue(ValueNode)} or * {@link #replaceWithVirtual(VirtualObjectNode)}, depending on the given value. - * + * * @param value the replacement value */ void replaceWith(ValueNode value); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Sat Feb 21 19:55:33 2015 +0100 @@ -242,13 +242,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(); @@ -257,14 +251,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() { @@ -473,22 +516,16 @@ } private static final class DefaultSimplifierTool implements SimplifierTool { - private final Assumptions assumptions; private final MetaAccessProvider metaAccess; private final ConstantReflectionProvider constantReflection; private final boolean canonicalizeReads; - public DefaultSimplifierTool(Assumptions assumptions, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean canonicalizeReads) { - this.assumptions = assumptions; + public DefaultSimplifierTool(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean canonicalizeReads) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; this.canonicalizeReads = canonicalizeReads; } - public Assumptions assumptions() { - return assumptions; - } - public MetaAccessProvider getMetaAccess() { return metaAccess; } @@ -517,7 +554,7 @@ } } - public static SimplifierTool getDefaultSimplifier(Assumptions assumptions, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean canonicalizeReads) { - return new DefaultSimplifierTool(assumptions, metaAccess, constantReflection, canonicalizeReads); + public static SimplifierTool getDefaultSimplifier(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean canonicalizeReads) { + return new DefaultSimplifierTool(metaAccess, constantReflection, canonicalizeReads); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.options; +import java.io.*; import java.util.function.*; import com.oracle.graal.options.OptionValue.OverrideScope; @@ -31,10 +32,13 @@ */ public class DerivedOptionValue { + public interface OptionSupplier extends Supplier, Serializable { + } + private final T initialValue; - private final Supplier supplier; + private final OptionSupplier supplier; - public DerivedOptionValue(Supplier supplier) { + public DerivedOptionValue(OptionSupplier supplier) { this.supplier = supplier; assert OptionValue.getOverrideScope() == null : "derived option value should be initialized outside any override scope"; this.initialValue = createValue(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,12 +22,13 @@ */ package com.oracle.graal.phases.common; -import com.oracle.graal.api.code.*; 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.graph.Graph.*; +import com.oracle.graal.graph.Graph.Mark; +import com.oracle.graal.graph.Graph.NodeEventListener; +import com.oracle.graal.graph.Graph.NodeEventScope; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -186,7 +187,7 @@ if (node.isAlive()) { METRIC_PROCESSED_NODES.increment(); - NodeClass nodeClass = node.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); if (tryGlobalValueNumbering(node, nodeClass)) { return; } @@ -212,7 +213,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) { @@ -227,7 +228,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)) { @@ -253,7 +254,7 @@ } } - 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)) { @@ -394,15 +395,6 @@ GraphUtil.killCFG(branch, this); } - /** - * @return an object that can be used for recording assumptions or {@code null} if - * assumptions are not allowed in the current context. - */ - @Override - public Assumptions assumptions() { - return context.getAssumptions(); - } - @Override public MetaAccessProvider getMetaAccess() { return context.getMetaAccess(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -49,7 +49,7 @@ * */ public class ConvertDeoptimizeToGuardPhase extends Phase { - private SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false); + private SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, false); private static AbstractBeginNode findBeginNode(FixedNode startNode) { return GraphUtil.predecessorIterable(startNode).filter(AbstractBeginNode.class).first(); @@ -58,22 +58,22 @@ @Override protected void run(final StructuredGraph graph) { 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)) { + for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.TYPE)) { 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(); + List mergePredecessors = merge.cfgPredecessors().snapshot(); Constant[] xs = IfNode.constantValues(compare.getX(), merge, true); if (xs == null) { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -79,7 +79,7 @@ deleteNodes(flood, graph); // remove chained Merges - for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class)) { + for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.TYPE)) { if (merge.forwardEndCount() == 1 && !(merge instanceof LoopBeginNode)) { graph.reduceTrivialMerge(merge); } @@ -100,7 +100,7 @@ } private static void disconnectCFGNodes(NodeFlood flood, StructuredGraph graph) { - for (AbstractEndNode node : graph.getNodes(AbstractEndNode.class)) { + for (AbstractEndNode node : graph.getNodes(AbstractEndNode.TYPE)) { if (!flood.isMarked(node)) { AbstractMergeNode merge = node.merge(); if (merge != null && flood.isMarked(merge)) { @@ -109,7 +109,7 @@ } } } - for (LoopBeginNode loop : graph.getNodes(LoopBeginNode.class)) { + for (LoopBeginNode loop : graph.getNodes(LoopBeginNode.TYPE)) { if (flood.isMarked(loop)) { boolean reachable = false; for (LoopEndNode end : loop.loopEnds()) { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LockEliminationPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Sat Feb 21 19:55:33 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,7 +26,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.Graph.Mark; @@ -48,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; } @@ -120,11 +120,6 @@ return createGuard(before, condition, deoptReason, action, false); } - @Override - public Assumptions assumptions() { - return context.getAssumptions(); - } - public StampProvider getStampProvider() { return context.getStampProvider(); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/VerifyHeapAtReturnPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -27,9 +27,8 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.common.*; -import com.oracle.graal.phases.common.inlining.policy.GreedyInliningPolicy; -import com.oracle.graal.phases.common.inlining.policy.InliningPolicy; -import com.oracle.graal.phases.common.inlining.walker.InliningData; +import com.oracle.graal.phases.common.inlining.policy.*; +import com.oracle.graal.phases.common.inlining.walker.*; import com.oracle.graal.phases.tiers.*; public class InliningPhase extends AbstractInliningPhase { @@ -93,5 +92,4 @@ assert data.inliningDepth() == 0; assert data.graphCount() == 0; } - } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Sat Feb 21 19:55:33 2015 +0100 @@ -114,7 +114,15 @@ public static void logNotInlinedMethod(Invoke invoke, String msg) { if (shouldLogInliningDecision()) { - String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName()); + String methodString = invoke.toString(); + if (invoke.callTarget() == null) { + methodString += " callTarget=null"; + } else { + String targetName = invoke.callTarget().targetName(); + if (!methodString.endsWith(targetName)) { + methodString += " " + targetName; + } + } logInliningDecision(methodString, false, msg, new Object[0]); } } @@ -323,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); } @@ -355,6 +363,21 @@ invokeNode.replaceAtUsages(null); GraphUtil.killCFG(invokeNode); + // Copy assumptions from inlinee to caller + Assumptions assumptions = graph.getAssumptions(); + if (assumptions != null) { + if (inlineGraph.getAssumptions() != null) { + assumptions.record(inlineGraph.getAssumptions()); + } + } else { + assert inlineGraph.getAssumptions() == null : "cannot inline graph which makes assumptions into a graph that doesn't: " + inlineGraph + " -> " + graph; + } + + // Copy inlined methods from inlinee to caller + if (inlineGraph.isInlinedMethodRecordingEnabled() && graph.isInlinedMethodRecordingEnabled()) { + graph.getInlinedMethods().addAll(inlineGraph.getInlinedMethods()); + } + return duplicates; } @@ -366,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); } @@ -387,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,16 +24,13 @@ import java.util.*; -import com.oracle.graal.api.code.Assumptions; -import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.common.CanonicalizerPhase; -import com.oracle.graal.phases.common.inlining.InliningUtil; -import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; -import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; -import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; -import com.oracle.graal.phases.tiers.HighTierContext; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.inlining.*; +import com.oracle.graal.phases.common.inlining.info.elem.*; +import com.oracle.graal.phases.tiers.*; public abstract class AbstractInlineInfo implements InlineInfo { @@ -53,7 +50,7 @@ return invoke; } - protected static Collection inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, Assumptions assumptions, boolean receiverNullCheck) { + protected static Collection inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, boolean receiverNullCheck) { List canonicalizeNodes = new ArrayList<>(); if (inlineable instanceof InlineableGraph) { StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph(); @@ -68,12 +65,15 @@ } InliningUtil.InlinedBytecodes.add(concrete.getCodeSize()); - assumptions.recordMethodContents(concrete); + StructuredGraph graph = invoke.asNode().graph(); + if (graph.isInlinedMethodRecordingEnabled()) { + graph.getInlinedMethods().add(concrete); + } return canonicalizeNodes; } 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()) { @@ -83,9 +83,9 @@ } } - public final void populateInlinableElements(HighTierContext context, Assumptions calleeAssumptions, CanonicalizerPhase canonicalizer) { + public final void populateInlinableElements(HighTierContext context, StructuredGraph caller, CanonicalizerPhase canonicalizer) { for (int i = 0; i < numberOfMethods(); i++) { - Inlineable elem = Inlineable.getInlineableElement(methodAt(i), invoke, context.replaceAssumptions(calleeAssumptions), canonicalizer); + Inlineable elem = Inlineable.getInlineableElement(methodAt(i), invoke, context, canonicalizer); setInlinableElement(i, elem); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -47,14 +46,14 @@ } @Override - public Collection inline(Providers providers, Assumptions assumptions) { - assumptions.record(takenAssumption); - return super.inline(providers, assumptions); + public Collection inline(Providers providers) { + invoke.asNode().graph().getAssumptions().record(takenAssumption); + return super.inline(providers); } @Override - public void tryToDevirtualizeInvoke(Providers providers, Assumptions assumptions) { - assumptions.record(takenAssumption); + public void tryToDevirtualizeInvoke(Providers providers) { + invoke.asNode().graph().getAssumptions().record(takenAssumption); InliningUtil.replaceInvokeCallTarget(invoke, graph(), InvokeKind.Special, concrete); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -52,12 +51,12 @@ } @Override - public Collection inline(Providers providers, Assumptions assumptions) { - return inline(invoke, concrete, inlineableElement, assumptions, !suppressNullCheck); + public Collection inline(Providers providers) { + return inline(invoke, concrete, inlineableElement, !suppressNullCheck); } @Override - public void tryToDevirtualizeInvoke(Providers providers, Assumptions assumptions) { + public void tryToDevirtualizeInvoke(Providers providers) { // nothing todo, can already be bound statically } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -74,16 +73,16 @@ * * @return a collection of nodes that need to be canonicalized after the inlining */ - Collection inline(Providers providers, Assumptions assumptions); + Collection inline(Providers providers); /** * Try to make the call static bindable to avoid interface and virtual method calls. */ - void tryToDevirtualizeInvoke(Providers providers, Assumptions assumptions); + void tryToDevirtualizeInvoke(Providers providers); boolean shouldInline(); - void populateInlinableElements(HighTierContext context, Assumptions calleeAssumptions, CanonicalizerPhase canonicalizer); + void populateInlinableElements(HighTierContext context, StructuredGraph caller, CanonicalizerPhase canonicalizer); int determineNodeCount(); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,7 +26,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.compiler.common.calc.*; @@ -142,11 +141,11 @@ } @Override - public Collection inline(Providers providers, Assumptions assumptions) { + public Collection inline(Providers providers) { if (hasSingleMethod()) { - return inlineSingleMethod(graph(), providers.getMetaAccess(), assumptions, providers.getStampProvider()); + return inlineSingleMethod(graph(), providers.getMetaAccess(), providers.getStampProvider()); } else { - return inlineMultipleMethods(graph(), providers, assumptions); + return inlineMultipleMethods(graph(), providers); } } @@ -167,7 +166,7 @@ return notRecordedTypeProbability > 0; } - private Collection inlineMultipleMethods(StructuredGraph graph, Providers providers, Assumptions assumptions) { + private Collection inlineMultipleMethods(StructuredGraph graph, Providers providers) { int numberOfMethods = concretes.size(); FixedNode continuation = invoke.next(); @@ -276,7 +275,7 @@ if (opportunities > 0) { metricInliningTailDuplication.increment(); Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities); - PhaseContext phaseContext = new PhaseContext(providers, assumptions); + PhaseContext phaseContext = new PhaseContext(providers); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue()); TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, phaseContext, canonicalizer); } @@ -286,7 +285,7 @@ // do the actual inlining for every invoke for (int i = 0; i < numberOfMethods; i++) { Invoke invokeForInlining = (Invoke) successors[i].next(); - canonicalizeNodes.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), assumptions, false)); + canonicalizeNodes.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), false)); } if (returnValuePhi != null) { canonicalizeNodes.add(returnValuePhi); @@ -327,7 +326,7 @@ return result; } - private Collection inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions, StampProvider stampProvider) { + private Collection inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, StampProvider stampProvider) { assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); @@ -338,7 +337,7 @@ calleeEntryNode.setNext(invoke.asNode()); - return inline(invoke, methodAt(0), inlineableElementAt(0), assumptions, false); + return inline(invoke, methodAt(0), inlineableElementAt(0), false); } private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess, StampProvider stampProvider) { @@ -376,7 +375,7 @@ FixedNode lastSucc = successors[concretes.size()]; for (int i = concretes.size() - 1; i >= 0; --i) { LoadMethodNode method = graph.add(new LoadMethodNode(stampProvider.createMethodStamp(), concretes.get(i), receiverType, hub)); - CompareNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i]); + LogicNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i], null); IfNode ifNode = graph.add(new IfNode(methodCheck, successors[i], lastSucc, probability[i])); method.setNext(ifNode); lastSucc = method; @@ -465,7 +464,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); @@ -500,7 +499,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); @@ -511,7 +510,7 @@ } @Override - public void tryToDevirtualizeInvoke(Providers providers, Assumptions assumptions) { + public void tryToDevirtualizeInvoke(Providers providers) { if (hasSingleMethod()) { devirtualizeWithTypeSwitch(graph(), InvokeKind.Special, concretes.get(0), providers.getMetaAccess(), providers.getStampProvider()); } else { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; @@ -90,13 +89,13 @@ } @Override - public Collection inline(Providers providers, Assumptions assumptions) { + public Collection inline(Providers providers) { createGuard(graph(), providers); - return inline(invoke, concrete, inlineableElement, assumptions, false); + return inline(invoke, concrete, inlineableElement, false); } @Override - public void tryToDevirtualizeInvoke(Providers providers, Assumptions assumptions) { + public void tryToDevirtualizeInvoke(Providers providers) { createGuard(graph(), providers); InliningUtil.replaceInvokeCallTarget(invoke, graph(), InvokeKind.Special, concrete); } @@ -106,7 +105,7 @@ LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver)); ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(), type.getObjectHub(), providers.getMetaAccess(), graph); - CompareNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub); + LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection()); FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); assert invoke.predecessor() != null; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; import com.oracle.graal.phases.graph.*; @@ -58,7 +59,7 @@ private FixedNodeProbabilityCache probabilites = new FixedNodeProbabilityCache(); public InlineableGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer) { - StructuredGraph original = getOriginalGraph(method, context, canonicalizer); + StructuredGraph original = getOriginalGraph(method, context, canonicalizer, invoke.asNode().graph()); // TODO copying the graph is only necessary if it is modified or if it contains any invokes this.graph = original.copy(); specializeGraphToArguments(invoke, context, canonicalizer); @@ -69,7 +70,7 @@ * The graph thus obtained is returned, ie the caller is responsible for cloning before * modification. */ - private static StructuredGraph getOriginalGraph(final ResolvedJavaMethod method, final HighTierContext context, CanonicalizerPhase canonicalizer) { + private static StructuredGraph getOriginalGraph(final ResolvedJavaMethod method, final HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { StructuredGraph result = InliningUtil.getIntrinsicGraph(context.getReplacements(), method); if (result != null) { return result; @@ -78,7 +79,7 @@ if (result != null) { return result; } - return parseBytecodes(method, context, canonicalizer); + return parseBytecodes(method, context, canonicalizer, caller); } /** @@ -142,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 @@ -184,6 +185,8 @@ if (context.getGraphCache() != null) { StructuredGraph cachedGraph = context.getGraphCache().get(method); if (cachedGraph != null) { + // TODO: check that cachedGraph.getAssumptions() are still valid + // instead of waiting for code installation to do it. return cachedGraph; } } @@ -195,9 +198,16 @@ * Provided profiling info is mature, the resulting graph is cached. The caller is responsible * for cloning before modification.

    */ - private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer) { - StructuredGraph newGraph = new StructuredGraph(method); + private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { + StructuredGraph newGraph = new StructuredGraph(method, AllowAssumptions.from(caller.getAssumptions() != null)); try (Debug.Scope s = Debug.scope("InlineGraph", newGraph)) { + if (!caller.isInlinedMethodRecordingEnabled()) { + // Don't record inlined methods in the callee if + // the caller doesn't want them. This decision is + // preserved in the graph cache (if used) which is + // ok since the graph cache is compilation local. + newGraph.disableInlinedMethodRecording(); + } if (context.getGraphBuilderSuite() != null) { context.getGraphBuilderSuite().apply(newGraph, context); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderExplorable.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Sat Feb 21 19:55:33 2015 +0100 @@ -100,8 +100,7 @@ this.inliningPolicy = inliningPolicy; this.maxGraphs = 1; - Assumptions rootAssumptions = context.getAssumptions(); - invocationQueue.push(new MethodInvocation(null, rootAssumptions, 1.0, 1.0, null)); + invocationQueue.push(new MethodInvocation(null, 1.0, 1.0, null)); graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0, null)); } @@ -145,7 +144,7 @@ * @param invoke the invoke that should be inlined * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke */ - private InlineInfo getInlineInfo(Invoke invoke, Assumptions assumptions) { + private InlineInfo getInlineInfo(Invoke invoke) { final String failureMessage = InliningUtil.checkInvokeConditions(invoke); if (failureMessage != null) { InliningUtil.logNotInlinedMethod(invoke, failureMessage); @@ -194,7 +193,7 @@ } } - if (assumptions.useOptimisticAssumptions()) { + if (callTarget.graph().getAssumptions() != null) { ResolvedJavaType uniqueSubtype = holder.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { ResolvedJavaMethod resolvedMethod = uniqueSubtype.resolveConcreteMethod(targetMethod, contextType); @@ -354,16 +353,15 @@ return null; } - private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation, Assumptions callerAssumptions) { + private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation) { StructuredGraph callerGraph = callerCallsiteHolder.graph(); InlineInfo calleeInfo = calleeInvocation.callee(); try { try (Debug.Scope scope = Debug.scope("doInline", callerGraph)) { Set canonicalizedNodes = Node.newSet(); calleeInfo.invoke().asNode().usages().snapshotTo(canonicalizedNodes); - Collection parameterUsages = calleeInfo.inline(new Providers(context), callerAssumptions); + Collection parameterUsages = calleeInfo.inline(new Providers(context)); canonicalizedNodes.addAll(parameterUsages); - callerAssumptions.record(calleeInvocation.assumptions()); metricInliningRuns.increment(); Debug.dump(callerGraph, "after %s", calleeInfo); @@ -409,20 +407,19 @@ * * @return true iff inlining was actually performed */ - private boolean tryToInline(MethodInvocation calleeInvocation, MethodInvocation parentInvocation, int inliningDepth) { + private boolean tryToInline(MethodInvocation calleeInvocation, int inliningDepth) { CallsiteHolderExplorable callerCallsiteHolder = (CallsiteHolderExplorable) currentGraph(); InlineInfo calleeInfo = calleeInvocation.callee(); assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke()); - Assumptions callerAssumptions = parentInvocation.assumptions(); metricInliningConsidered.increment(); if (inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true)) { - doInline(callerCallsiteHolder, calleeInvocation, callerAssumptions); + doInline(callerCallsiteHolder, calleeInvocation); return true; } if (context.getOptimisticOptimizations().devirtualizeInvokes()) { - calleeInfo.tryToDevirtualizeInvoke(new Providers(context), callerAssumptions); + calleeInfo.tryToDevirtualizeInvoke(new Providers(context)); } return false; @@ -450,22 +447,19 @@ *

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

    */ private void processNextInvoke() { CallsiteHolderExplorable callsiteHolder = (CallsiteHolderExplorable) currentGraph(); Invoke invoke = callsiteHolder.popInvoke(); - MethodInvocation callerInvocation = currentInvocation(); - Assumptions parentAssumptions = callerInvocation.assumptions(); - InlineInfo info = getInlineInfo(invoke, parentAssumptions); + InlineInfo info = getInlineInfo(invoke); if (info != null) { - Assumptions calleeAssumptions = new Assumptions(parentAssumptions.useOptimisticAssumptions()); - info.populateInlinableElements(context, calleeAssumptions, canonicalizer); + info.populateInlinableElements(context, currentGraph().graph(), canonicalizer); double invokeProbability = callsiteHolder.invokeProbability(invoke); double invokeRelevance = callsiteHolder.invokeRelevance(invoke); - MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance, freshlyInstantiatedArguments(invoke, callsiteHolder.getFixedParams())); + MethodInvocation methodInvocation = new MethodInvocation(info, invokeProbability, invokeRelevance, freshlyInstantiatedArguments(invoke, callsiteHolder.getFixedParams())); pushInvocationAndGraphs(methodInvocation); } } @@ -640,12 +634,12 @@ * {@link #processNextInvoke() delve} into one of the callsites hosted in the current graph, * such callsite is explored next by {@link #moveForward()} *
  13. - * {@link #tryToInline(MethodInvocation, MethodInvocation, int) try to inline}: move past the - * current graph (remove it from the topmost element). + * {@link #tryToInline(MethodInvocation, int) try to inline}: move past the current graph + * (remove it from the topmost element). *
      *
    • - * If that was the last one then {@link #tryToInline(MethodInvocation, MethodInvocation, int) - * try to inline} the callsite under consideration (ie, the "current invocation").
    • + * If that was the last one then {@link #tryToInline(MethodInvocation, int) try to inline} the + * callsite under consideration (ie, the "current invocation"). *
    • * Whether inlining occurs or not, that callsite is removed from the top of {@link InliningData} * .
    • @@ -703,9 +697,8 @@ * "all concrete methods that come into question already had the callees they contain analyzed for inlining" */ popInvocation(); - final MethodInvocation parentInvoke = currentInvocation(); try (Debug.Scope s = Debug.scope("Inlining", inliningContext())) { - return tryToInline(currentInvocation, parentInvoke, inliningDepth() + 1); + return tryToInline(currentInvocation, inliningDepth() + 1); } catch (Throwable e) { throw Debug.handle(e); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,16 +22,13 @@ */ package com.oracle.graal.phases.common.inlining.walker; -import com.oracle.graal.api.code.Assumptions; -import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.CallTargetNode; -import com.oracle.graal.nodes.java.MethodCallTargetNode; -import com.oracle.graal.phases.common.inlining.info.InlineInfo; -import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; -import com.oracle.graal.phases.common.inlining.info.elem.InlineableGraph; -import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; +import java.util.*; -import java.util.BitSet; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.common.inlining.info.*; +import com.oracle.graal.phases.common.inlining.info.elem.*; /** *

      @@ -47,7 +44,6 @@ public class MethodInvocation { private final InlineInfo callee; - private final Assumptions assumptions; private final double probability; private final double relevance; @@ -79,9 +75,8 @@ private final int sizeFreshArgs; - public MethodInvocation(InlineInfo info, Assumptions assumptions, double probability, double relevance, BitSet freshlyInstantiatedArguments) { + public MethodInvocation(InlineInfo info, double probability, double relevance, BitSet freshlyInstantiatedArguments) { this.callee = info; - this.assumptions = assumptions; this.probability = probability; this.relevance = relevance; this.freshlyInstantiatedArguments = freshlyInstantiatedArguments; @@ -106,10 +101,6 @@ return callee; } - public Assumptions assumptions() { - return assumptions; - } - public double probability() { return probability; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -33,7 +33,6 @@ import com.oracle.graal.compiler.common.cfg.*; 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.cfg.*; import com.oracle.graal.nodes.extended.*; @@ -306,6 +305,7 @@ private BlockMap> blockToNodesMap; private BlockMap blockToKillSet; private final SchedulingStrategy selectedStrategy; + private boolean scheduleConstants; public SchedulePhase() { this(OptScheduleOutOfLoops.getValue() ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST); @@ -315,6 +315,10 @@ this.selectedStrategy = strategy; } + public void setScheduleConstants(boolean value) { + scheduleConstants = value; + } + @Override protected void run(StructuredGraph graph) { assert GraphOrder.assertNonCyclicGraph(graph); @@ -450,6 +454,12 @@ if (cfg.getNodeToBlock().containsKey(node)) { return; } + if (!scheduleConstants && node instanceof ConstantNode) { + return; + } + if (node instanceof VirtualObjectNode) { + return; + } // PhiNodes, ProxyNodes and FixedNodes should already have been placed in blocks by // ControlFlowGraph.identifyBlocks if (node instanceof PhiNode || node instanceof ProxyNode || node instanceof FixedNode) { @@ -473,7 +483,7 @@ assert dominates(earliestBlock, block) : String.format("%s (%s) cannot be scheduled before earliest schedule (%s). location: %s", read, block, earliestBlock, read.getLocationIdentity()); } else { - block = latestBlock(node, strategy); + block = latestBlock(node, strategy, earliestBlock); } if (block == null) { // handle nodes without usages @@ -484,16 +494,7 @@ block = scheduleOutOfLoops(node, block, earliestBlock); } - if (assertionEnabled()) { - if (scheduleRead) { - FloatingReadNode read = (FloatingReadNode) node; - MemoryNode lastLocationAccess = read.getLastLocationAccess(); - Block upperBound = blockForMemoryNode(lastLocationAccess); - assert dominates(upperBound, block) : String.format( - "out of loop movement voilated memory semantics for %s (location %s). moved to %s but upper bound is %s (earliest: %s, latest: %s)", read, - read.getLocationIdentity(), block, upperBound, earliestBlock, latest); - } - } + assert assertReadSchedule(node, earliestBlock, block, latest, scheduleRead); break; default: throw new GraalInternalError("unknown scheduling strategy"); @@ -505,11 +506,15 @@ blockToNodesMap.get(block).add(node); } - @SuppressWarnings("all") - private static boolean assertionEnabled() { - boolean enabled = false; - assert enabled = true; - return enabled; + private boolean assertReadSchedule(ValueNode node, Block earliestBlock, Block block, Block latest, boolean scheduleRead) { + if (scheduleRead) { + FloatingReadNode read = (FloatingReadNode) node; + MemoryNode lastLocationAccess = read.getLastLocationAccess(); + Block upperBound = blockForMemoryNode(lastLocationAccess); + assert dominates(upperBound, block) : String.format("out of loop movement voilated memory semantics for %s (location %s). moved to %s but upper bound is %s (earliest: %s, latest: %s)", + read, read.getLocationIdentity(), block, upperBound, earliestBlock, latest); + } + return true; } /** @@ -540,7 +545,7 @@ Block earliestBlock = earliestBlock(n); assert dominates(upperBoundBlock, earliestBlock) : "upper bound (" + upperBoundBlock + ") should dominate earliest (" + earliestBlock + ")"; - Block latestBlock = latestBlock(n, strategy); + Block latestBlock = latestBlock(n, strategy, earliestBlock); assert latestBlock != null && dominates(earliestBlock, latestBlock) : "earliest (" + earliestBlock + ") should dominate latest block (" + latestBlock + ")"; Debug.log("processing %s (accessing %s): latest %s, earliest %s, upper bound %s (%s)", n, locid, latestBlock, earliestBlock, upperBoundBlock, n.getLastLocationAccess()); @@ -613,26 +618,27 @@ * dominator of all usages. To do so all usages are also assigned to blocks. * * @param strategy + * @param earliestBlock */ - private Block latestBlock(ValueNode node, SchedulingStrategy strategy) { + private Block latestBlock(ValueNode node, SchedulingStrategy strategy, Block earliestBlock) { CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null); - for (Node succ : node.successors().nonNull()) { - if (cfg.getNodeToBlock().get(succ) == null) { - throw new SchedulingError(); - } - cdbc.apply(cfg.getNodeToBlock().get(succ)); - } ensureScheduledUsages(node, strategy); for (Node usage : node.usages()) { blocksForUsage(node, usage, cdbc, strategy); + if (cdbc.block == earliestBlock) { + break; + } } - if (assertionEnabled()) { - 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)); - } + 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 cdbc.block; + return true; } /** @@ -744,10 +750,8 @@ * @param usage the usage whose blocks need to be considered * @param closure the closure that will be called for each block */ - private void blocksForUsage(ValueNode node, Node usage, BlockClosure closure, SchedulingStrategy strategy) { - if (node instanceof PhiNode) { - throw new SchedulingError(node.toString()); - } + private void blocksForUsage(ValueNode node, Node usage, CommonDominatorBlockClosure closure, SchedulingStrategy strategy) { + assert !(node instanceof PhiNode); if (usage instanceof PhiNode) { // An input to a PhiNode is used at the end of the predecessor block that corresponds to @@ -757,19 +761,8 @@ PhiNode phi = (PhiNode) usage; AbstractMergeNode merge = phi.merge(); Block mergeBlock = cfg.getNodeToBlock().get(merge); - if (mergeBlock == null) { - throw new SchedulingError("no block for merge %s", merge.toString(Verbosity.Id)); - } for (int i = 0; i < phi.valueCount(); ++i) { if (phi.valueAt(i) == node) { - if (mergeBlock.getPredecessorCount() <= i) { - TTY.println(merge.toString()); - TTY.println(phi.toString()); - TTY.println(merge.cfgPredecessors().toString()); - TTY.println(mergeBlock.getPredecessors().toString()); - TTY.println(phi.inputs().toString()); - TTY.println("value count: " + phi.valueCount()); - } closure.apply(mergeBlock.getPredecessors().get(i)); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java Sat Feb 21 19:55:33 2015 +0100 @@ -23,6 +23,10 @@ package com.oracle.graal.phases.tiers; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.lir.phases.*; +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 { @@ -32,4 +36,10 @@ PhaseSuite createMidTier(); PhaseSuite createLowTier(); + + LIRPhaseSuite createPreAllocationOptimizationStage(); + + LIRPhaseSuite createAllocationStage(); + + LIRPhaseSuite createPostAllocationOptimizationStage(); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; @@ -37,9 +36,8 @@ private final Map cache; private final OptimisticOptimizations optimisticOpts; - public HighTierContext(Providers providers, Assumptions assumptions, Map cache, PhaseSuite graphBuilderSuite, - OptimisticOptimizations optimisticOpts) { - super(providers, assumptions); + public HighTierContext(Providers providers, Map cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts) { + super(providers); this.cache = cache; this.graphBuilderSuite = graphBuilderSuite; this.optimisticOpts = optimisticOpts; @@ -56,8 +54,4 @@ public OptimisticOptimizations getOptimisticOptimizations() { return optimisticOpts; } - - public HighTierContext replaceAssumptions(Assumptions newAssumptions) { - return new HighTierContext(new Providers(this), newAssumptions, cache, graphBuilderSuite, optimisticOpts); - } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java Sat Feb 21 19:55:33 2015 +0100 @@ -29,8 +29,8 @@ private final TargetDescription target; - public LowTierContext(Providers copyFrom, Assumptions assumptions, TargetDescription target) { - super(copyFrom, assumptions); + public LowTierContext(Providers copyFrom, TargetDescription target) { + super(copyFrom); this.target = target; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,8 +34,8 @@ private final ProfilingInfo profilingInfo; private final SpeculationLog log; - public MidTierContext(Providers copyFrom, Assumptions assumptions, TargetDescription target, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog log) { - super(copyFrom, assumptions); + public MidTierContext(Providers copyFrom, TargetDescription target, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog log) { + super(copyFrom); this.target = target; this.optimisticOpts = optimisticOpts; this.profilingInfo = profilingInfo; diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.phases.tiers; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; @@ -33,21 +32,18 @@ private final ConstantReflectionProvider constantReflection; private final LoweringProvider lowerer; private final Replacements replacements; - private final Assumptions assumptions; private final StampProvider stampProvider; - public PhaseContext(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, LoweringProvider lowerer, Replacements replacements, Assumptions assumptions, - StampProvider stampProvider) { + public PhaseContext(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; this.lowerer = lowerer; this.replacements = replacements; - this.assumptions = assumptions; this.stampProvider = stampProvider; } - public PhaseContext(Providers providers, Assumptions assumptions) { - this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getLowerer(), providers.getReplacements(), assumptions, providers.getStampProvider()); + public PhaseContext(Providers providers) { + this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getLowerer(), providers.getReplacements(), providers.getStampProvider()); } public MetaAccessProvider getMetaAccess() { @@ -66,10 +62,6 @@ return replacements; } - public Assumptions getAssumptions() { - return assumptions; - } - public StampProvider getStampProvider() { return stampProvider; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -129,4 +130,22 @@ return new Suites(config); } + public static LIRSuites createDefaultLIRSuites() { + String selected = CompilerConfiguration.getValue(); + if (selected.equals("")) { + return new LIRSuites(defaultConfiguration.createPreAllocationOptimizationStage(), defaultConfiguration.createAllocationStage(), + defaultConfiguration.createPostAllocationOptimizationStage()); + } else { + return createLIRSuites(selected); + } + } + + public static LIRSuites createLIRSuites(String name) { + CompilerConfiguration config = configurations.get(name); + if (config == null) { + throw new GraalInternalError("unknown compiler configuration: " + name); + } + return new LIRSuites(config.createPreAllocationOptimizationStage(), config.createAllocationStage(), config.createPostAllocationOptimizationStage()); + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.phases.tiers; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.phases.*; public interface SuitesProvider { @@ -42,4 +43,15 @@ */ PhaseSuite getDefaultGraphBuilderSuite(); + /** + * Get the default phase suites of this compiler. + */ + LIRSuites getDefaultLIRSuites(); + + /** + * Create a new set of low-level phase suites. Initially, the suites are the same as the + * {@link #getDefaultLIRSuites default} suites. + */ + LIRSuites createLIRSuites(); + } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Sat Feb 21 19:55:33 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; } }); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyDebugUsage.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Sat Feb 21 19:55:33 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,7 +439,7 @@ } private void writeEdges(Node node, Edges.Type type) throws IOException { - NodeClass nodeClass = node.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); Edges edges = nodeClass.getEdges(type); for (int i = 0; i < edges.getDirectCount(); i++) { writeNodeRef(edges.getNode(node, i)); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,8 +26,8 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -330,13 +330,12 @@ @Test public void testCanonicalLength() { - StructuredGraph graph = parseEager("testCanonicalLengthSnippet"); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = parseEager("testCanonicalLengthSnippet", AllowAssumptions.NO); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + 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}; @@ -347,13 +346,12 @@ @Test public void testCanonicalEqual() { - StructuredGraph graph = parseEager("testCanonicalEqualSnippet"); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = parseEager("testCanonicalEqualSnippet", AllowAssumptions.NO); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + 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() { @@ -362,15 +360,14 @@ @Test public void testVirtualEqual() { - StructuredGraph graph = parseEager("testVirtualEqualSnippet"); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = parseEager("testVirtualEqualSnippet", AllowAssumptions.NO); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + 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() { @@ -381,15 +378,14 @@ @Test public void testVirtualNotEqual() { - StructuredGraph graph = parseEager("testVirtualNotEqualSnippet"); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", AllowAssumptions.NO); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,11 +24,11 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -247,18 +247,18 @@ * @return the returned value or null if {@code expectedClass} is not found in the graph. */ private ValueNode parseAndInline(String name, Class expectedClass) { - StructuredGraph graph = parseEager(name); - HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE); + StructuredGraph graph = parseEager(name, AllowAssumptions.YES); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context); new InliningPhase(canonicalizer).apply(graph, context); canonicalizer.apply(graph, context); - Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); + 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.common.*; @@ -40,8 +41,8 @@ } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m) { - StructuredGraph graph = super.parseEager(m); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + StructuredGraph graph = super.parseEager(m, allowAssumptions); int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count(); Assert.assertEquals(1, handlers); return graph; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,13 +26,13 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Edges.Type; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; @@ -45,16 +45,18 @@ @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); } } - StructuredGraph graph = new StructuredGraph(); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO); TestNode node; ConstantNode i1; ConstantNode i2; @@ -113,9 +115,8 @@ } ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); - StructuredGraph g = parseProfiled(javaMethod); - Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph g = parseProfiled(javaMethod, AllowAssumptions.NO); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new InlineMethodSubstitutionsPolicy(), new CanonicalizerPhase(true)).apply(g, context); new CanonicalizerPhase(false).apply(g, context); Assert.assertTrue(g.getNodes().filter(CheckCastNode.class).isEmpty()); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -48,9 +49,8 @@ protected StructuredGraph test(final String snippet) { try (Scope s = Debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) { - StructuredGraph graph = parseEager(snippet); - Assumptions assumptions = new Assumptions(true); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); Debug.dump(graph, "Graph"); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.replacements.*; @@ -45,55 +46,55 @@ private final ReplacementsImpl installer; public ObjectAccessTest() { - installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), new Assumptions(false), getTarget()); + installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), getTarget()); } private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m) { + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { return installer.makeGraph(m, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); } @Test public void testRead1() { for (Kind kind : KINDS) { - assertRead(parseEager("read" + kind.name() + "1"), kind, true, ID); + assertRead(parseEager("read" + kind.name() + "1", AllowAssumptions.YES), kind, true, ID); } } @Test public void testRead2() { for (Kind kind : KINDS) { - assertRead(parseEager("read" + kind.name() + "2"), kind, true, ID); + assertRead(parseEager("read" + kind.name() + "2", AllowAssumptions.YES), kind, true, ID); } } @Test public void testRead3() { for (Kind kind : KINDS) { - assertRead(parseEager("read" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION); + assertRead(parseEager("read" + kind.name() + "3", AllowAssumptions.YES), kind, true, LocationIdentity.ANY_LOCATION); } } @Test public void testWrite1() { for (Kind kind : KINDS) { - assertWrite(parseEager("write" + kind.name() + "1"), true, ID); + assertWrite(parseEager("write" + kind.name() + "1", AllowAssumptions.YES), true, ID); } } @Test public void testWrite2() { for (Kind kind : KINDS) { - assertWrite(parseEager("write" + kind.name() + "2"), true, ID); + assertWrite(parseEager("write" + kind.name() + "2", AllowAssumptions.YES), true, ID); } } @Test public void testWrite3() { for (Kind kind : KINDS) { - assertWrite(parseEager("write" + kind.name() + "3"), true, LocationIdentity.ANY_LOCATION); + assertWrite(parseEager("write" + kind.name() + "3", AllowAssumptions.YES), true, LocationIdentity.ANY_LOCATION); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; @@ -51,55 +52,55 @@ public PointerTest() { target = getCodeCache().getTarget(); - installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), new Assumptions(false), getTarget()); + installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), getTarget()); } private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m) { + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { return installer.makeGraph(m, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); } @Test public void testRead1() { for (Kind kind : KINDS) { - assertRead(parseEager("read" + kind.name() + "1"), kind, true, ID); + assertRead(parseEager("read" + kind.name() + "1", AllowAssumptions.YES), kind, true, ID); } } @Test public void testRead2() { for (Kind kind : KINDS) { - assertRead(parseEager("read" + kind.name() + "2"), kind, true, ID); + assertRead(parseEager("read" + kind.name() + "2", AllowAssumptions.YES), kind, true, ID); } } @Test public void testRead3() { for (Kind kind : KINDS) { - assertRead(parseEager("read" + kind.name() + "3"), kind, true, LocationIdentity.ANY_LOCATION); + assertRead(parseEager("read" + kind.name() + "3", AllowAssumptions.YES), kind, true, LocationIdentity.ANY_LOCATION); } } @Test public void testWrite1() { for (Kind kind : KINDS) { - assertWrite(parseEager("write" + kind.name() + "1"), true, ID); + assertWrite(parseEager("write" + kind.name() + "1", AllowAssumptions.YES), true, ID); } } @Test public void testWrite2() { for (Kind kind : KINDS) { - assertWrite(parseEager("write" + kind.name() + "2"), true, ID); + assertWrite(parseEager("write" + kind.name() + "2", AllowAssumptions.YES), true, ID); } } @Test public void testWrite3() { for (Kind kind : KINDS) { - assertWrite(parseEager("write" + kind.name() + "3"), true, LocationIdentity.ANY_LOCATION); + assertWrite(parseEager("write" + kind.name() + "3", AllowAssumptions.YES), true, LocationIdentity.ANY_LOCATION); } } @@ -399,10 +400,9 @@ } private void assertNumWordCasts(String snippetName, int expectedWordCasts) { - Assumptions assumptions = new Assumptions(true); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, null, OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), null, null, OptimisticOptimizations.ALL); - StructuredGraph graph = parseEager(snippetName); + StructuredGraph graph = parseEager(snippetName, AllowAssumptions.YES); new CanonicalizerPhase(false).apply(graph, context); Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count()); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -177,4 +177,25 @@ public static double longBitsToDouble(long value) { return Double.longBitsToDouble(value); } + + @SuppressWarnings("all") + public static boolean isInstance(Class clazz) { + return clazz.isInstance(Number.class); + } + + @SuppressWarnings("all") + public static boolean isAssignableFrom(Class clazz) { + return clazz.isInstance(Number.class); + } + + @Test + public void testClassSubstitutions() { + test("isInstance"); + for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) { + for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { + assertDeepEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o)); + assertDeepEquals(c.isAssignableFrom(o.getClass()), ClassSubstitutions.isAssignableFrom(c, o.getClass())); + } + } + } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,10 +24,10 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; @@ -41,13 +41,13 @@ private final ReplacementsImpl installer; public WordTest() { - installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), new Assumptions(false), getTarget()); + installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), getTarget()); } private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m) { + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { return installer.makeGraph(m, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ClassSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ClassSubstitutions.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,43 @@ +/* + * 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 com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.calc.*; + +/** + * Substitutions for {@link java.lang.Class} methods. + */ +@ClassSubstitution(java.lang.Class.class) +public class ClassSubstitutions { + + @MethodSubstitution(isStatic = false) + public static boolean isInstance(Class thisObj, Object obj) { + return ConditionalNode.materializeIsInstance(thisObj, obj); + } + + @MethodSubstitution(isStatic = false) + public static boolean isAssignableFrom(Class thisClass, Class otherClass) { + return ConditionalNode.materializeIsAssignableFrom(thisClass, otherClass); + } +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Sat Feb 21 19:55:33 2015 +0100 @@ -62,6 +62,7 @@ replacements.registerSubstitutions(Short.class, ShortSubstitutions.class); replacements.registerSubstitutions(UnsignedMath.class, UnsignedMathSubstitutions.class); replacements.registerSubstitutions(Edges.class, EdgesSubstitutions.class); + replacements.registerSubstitutions(Class.class, ClassSubstitutions.class); } if (Options.UseBlackholeSubstitution.getValue()) { replacements.registerSubstitutions(new Type() { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Sat Feb 21 19:55:33 2015 +0100 @@ -206,7 +206,7 @@ */ public void inline(InvokeNode invoke, SnippetReflectionProvider snippetReflection) { ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); - ReplacementsImpl repl = new ReplacementsImpl(providers, snippetReflection, new Assumptions(false), providers.getCodeCache().getTarget()); + ReplacementsImpl repl = new ReplacementsImpl(providers, snippetReflection, providers.getCodeCache().getTarget()); StructuredGraph calleeGraph = repl.makeGraph(method, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); InliningUtil.inline(invoke, calleeGraph, false, null); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Sat Feb 21 19:55:33 2015 +0100 @@ -65,7 +65,7 @@ protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); public void lower(FloatingNode instanceOf, LoweringTool tool) { - assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode; + assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode || instanceOf instanceof ClassIsAssignableFromNode; List usages = instanceOf.usages().snapshot(); Instantiation instantiation = new Instantiation(); @@ -112,7 +112,7 @@ public static final class Instantiation { private ValueNode result; - private CompareNode condition; + private LogicNode condition; private ValueNode trueValue; private ValueNode falseValue; @@ -141,9 +141,9 @@ assert testValue.isConstant(); return LogicConstantNode.forBoolean(result.asConstant().equals(testValue.asConstant()), result.graph()); } - if (condition == null || condition.getY() != testValue) { + if (condition == null || (!(condition instanceof CompareNode)) || ((CompareNode) condition).getY() != testValue) { // Re-use previously generated condition if the trueValue for the test is the same - condition = createCompareNode(result.graph(), Condition.EQ, result, testValue); + condition = createCompareNode(result.graph(), Condition.EQ, result, testValue, null); } return condition; } @@ -176,7 +176,7 @@ public final ValueNode falseValue; public InstanceOfUsageReplacer(Instantiation instantiation, FloatingNode instanceOf, ValueNode trueValue, ValueNode falseValue) { - assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode; + assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode || instanceOf instanceof ClassIsAssignableFromNode; this.instantiation = instantiation; this.instanceOf = instanceOf; this.trueValue = trueValue; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Log.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Sat Feb 21 19:55:33 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); @@ -171,34 +216,41 @@ } ConstantNode constantNode = (ConstantNode) argument; Constant constant = constantNode.asConstant(); - ResolvedJavaType type = providers.getConstantReflection().asJavaType(constant); + /* + * For intrinsification (but not for folding) if we have a Class object we want + * the corresponding ResolvedJavaType. + */ + ResolvedJavaType type = folding ? null : providers.getConstantReflection().asJavaType(constant); + Object arg; if (type != null) { - reflectionCallArguments[i] = type; + /* If we found such a type then it's our arg */ + arg = type; parameterTypes[i] = providers.getMetaAccess().lookupJavaType(ResolvedJavaType.class); } else { JavaConstant javaConstant = (JavaConstant) constant; - if (parameterTypes[i].getKind() == Kind.Boolean) { - reflectionCallArguments[i] = Boolean.valueOf(javaConstant.asInt() != 0); - } else if (parameterTypes[i].getKind() == Kind.Byte) { - reflectionCallArguments[i] = Byte.valueOf((byte) javaConstant.asInt()); - } else if (parameterTypes[i].getKind() == Kind.Short) { - reflectionCallArguments[i] = Short.valueOf((short) javaConstant.asInt()); - } else if (parameterTypes[i].getKind() == Kind.Char) { - reflectionCallArguments[i] = Character.valueOf((char) javaConstant.asInt()); - } else if (parameterTypes[i].getKind() == Kind.Object) { - if (!folding) { - reflectionCallArguments[i] = snippetReflection.asObject(parameterTypes[i], javaConstant); + if (folding) { + /* For folding we want JavaConstants */ + arg = javaConstant; + } else { + /* For intrinsification we want want corresponding objects */ + if (parameterTypes[i].getKind() == Kind.Boolean) { + arg = Boolean.valueOf(javaConstant.asInt() != 0); + } else if (parameterTypes[i].getKind() == Kind.Byte) { + arg = Byte.valueOf((byte) javaConstant.asInt()); + } else if (parameterTypes[i].getKind() == Kind.Short) { + arg = Short.valueOf((short) javaConstant.asInt()); + } else if (parameterTypes[i].getKind() == Kind.Char) { + arg = Character.valueOf((char) javaConstant.asInt()); + } else if (parameterTypes[i].getKind() == Kind.Object) { + arg = snippetReflection.asObject(parameterTypes[i], javaConstant); } else { - reflectionCallArguments[i] = javaConstant; + arg = javaConstant.asBoxedPrimitive(); } - } else { - reflectionCallArguments[i] = javaConstant.asBoxedPrimitive(); } } - if (folding && reflectionCallArguments[i] != constant) { - assert !(reflectionCallArguments[i] instanceof JavaConstant); - reflectionCallArguments[i] = snippetReflection.forObject(reflectionCallArguments[i]); - } + + assert folding || !(arg instanceof JavaConstant); + reflectionCallArguments[i] = arg; } else { reflectionCallArguments[i] = argument; parameterTypes[i] = providers.getMetaAccess().lookupJavaType(ValueNode.class); @@ -219,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; @@ -241,7 +293,7 @@ } try { - ValueNode intrinsicNode = (ValueNode) snippetReflection.invoke(constructor, null, arguments); + ValueNode intrinsicNode = (ValueNode) invokeConstructor(constructor, arguments); if (setStampFromReturnType) { intrinsicNode.setStamp(invokeStamp); @@ -252,6 +304,10 @@ } } + protected Object invokeConstructor(ResolvedJavaMethod constructor, Object[] arguments) { + return snippetReflection.invoke(constructor, null, arguments); + } + private static String sigString(ResolvedJavaType[] types) { StringBuilder sb = new StringBuilder("("); for (int i = 0; i < types.length; i++) { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -47,6 +47,7 @@ import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPhase.Instance; 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.*; @@ -63,7 +64,7 @@ public final Providers providers; public final SnippetReflectionProvider snippetReflection; public final TargetDescription target; - public final Assumptions assumptions; + public final NodeIntrinsificationPhase nodeIntrinsificationPhase; /** * The preprocessed replacement graphs. @@ -219,15 +220,15 @@ // it is stable across VM executions (in support of replay compilation). private final Map snippetTemplateCache; - public ReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, Assumptions assumptions, TargetDescription target) { + public ReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { this.providers = providers.copyWith(this); this.classReplacements = CollectionsFactory.newMap(); this.internalNameToSubstitutionClasses = CollectionsFactory.newMap(); this.snippetReflection = snippetReflection; this.target = target; - this.assumptions = assumptions; this.graphs = new ConcurrentHashMap<>(); this.snippetTemplateCache = CollectionsFactory.newMap(); + this.nodeIntrinsificationPhase = createNodeIntrinsificationPhase(); } private static final boolean UseSnippetGraphCache = Boolean.parseBoolean(System.getProperty("graal.useSnippetGraphCache", "true")); @@ -286,8 +287,8 @@ // Do deferred intrinsification of node intrinsics - createNodeIntrinsificationPhase().apply(specializedSnippet); - new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers, assumptions)); + nodeIntrinsificationPhase.apply(specializedSnippet); + new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers)); NodeIntrinsificationVerificationPhase.verify(specializedSnippet); } @@ -319,10 +320,6 @@ return cr == null ? null : cr.macroSubstitutions.get(method); } - public Assumptions getAssumptions() { - return assumptions; - } - private SubstitutionGuard getGuard(Class guardClass) { if (guardClass != SubstitutionGuard.class) { Constructor[] constructors = guardClass.getConstructors(); @@ -536,7 +533,7 @@ * 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); } @@ -612,20 +609,26 @@ * Builds the initial graph for a snippet. */ protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod methodToParse) { - final StructuredGraph graph = new StructuredGraph(methodToParse); + // Replacements cannot have optimistic assumptions since they have + // to be valid for the entire run of the VM. + final StructuredGraph graph = new StructuredGraph(methodToParse, AllowAssumptions.NO); + + // They will also never be never be evolved or have breakpoints set in them + graph.disableInlinedMethodRecording(); + try (Scope s = Debug.scope("buildInitialGraph", graph)) { MetaAccessProvider metaAccess = replacements.providers.getMetaAccess(); if (MethodsElidedInSnippets != null && methodToParse.getSignature().getReturnKind() == Kind.Void && MethodFilter.matches(MethodsElidedInSnippets, methodToParse)) { graph.addAfterFixed(graph.start(), graph.add(new ReturnNode(null))); } else { - createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.assumptions, replacements.providers.getConstantReflection(), - GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); + createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), GraphBuilderConfiguration.getSnippetDefault(), + OptimisticOptimizations.NONE).apply(graph); } afterParsing(graph); if (OptCanonicalizer.getValue()) { - new CanonicalizerPhase(true).apply(graph, new PhaseContext(replacements.providers, replacements.assumptions)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(replacements.providers)); } } catch (Throwable e) { throw Debug.handle(e); @@ -633,9 +636,9 @@ return graph; } - protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, - GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - return new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, constantReflection, graphBuilderConfig, optimisticOpts); + protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, + OptimisticOptimizations optimisticOpts) { + return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, graphBuilderConfig, optimisticOpts); } protected void afterParsing(StructuredGraph graph) { @@ -657,7 +660,7 @@ */ protected void afterInline(StructuredGraph caller, StructuredGraph callee, Object beforeInlineData) { if (OptCanonicalizer.getValue()) { - new CanonicalizerPhase(true).apply(caller, new PhaseContext(replacements.providers, replacements.assumptions)); + new CanonicalizerPhase(true).apply(caller, new PhaseContext(replacements.providers)); } } @@ -665,10 +668,10 @@ * 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, replacements.assumptions)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(replacements.providers)); } } @@ -678,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; } @@ -734,7 +737,7 @@ afterInlining(graph); - for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { + for (LoopEndNode end : graph.getNodes(LoopEndNode.TYPE)) { end.disableSafepoint(); } @@ -827,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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Sat Feb 21 19:55:33 2015 +0100 @@ -45,10 +45,12 @@ 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.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -391,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; } @@ -561,10 +564,14 @@ ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); - PhaseContext phaseContext = new PhaseContext(providers, new Assumptions(false)); + PhaseContext phaseContext = new PhaseContext(providers); // Copy snippet graph, replacing constant parameters with given arguments - final StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); + final StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method(), AllowAssumptions.NO); + if (!snippetGraph.isInlinedMethodRecordingEnabled()) { + snippetCopy.disableInlinedMethodRecording(); + } + Map nodeReplacements = Node.newIdentityMap(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); @@ -731,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) { @@ -1214,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); @@ -1245,7 +1252,7 @@ // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; - StructuredGraph snippetCopy = new StructuredGraph(name, snippet.method()); + StructuredGraph snippetCopy = new StructuredGraph(name, snippet.method(), AllowAssumptions.NO); StartNode entryPointNode = snippet.start(); FixedNode firstCFGNode = entryPointNode.next(); StructuredGraph replaceeGraph = replacee.graph(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Sat Feb 21 19:55:33 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; @@ -51,8 +52,9 @@ @Input ValueNode length; 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(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Sat Feb 21 19:55:33 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 @@ -61,7 +64,7 @@ /* * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an * exact type) and if it is a cloneable type. - * + * * If yes, then the exact type is returned, otherwise it returns null. */ protected static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { @@ -105,7 +108,7 @@ } else { obj = tool.getReplacedValue(getObject()); } - ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider()); + ResolvedJavaType type = getConcreteType(obj.stamp(), graph().getAssumptions(), tool.getMetaAccessProvider()); if (type != null && !type.isArray()) { VirtualInstanceNode newVirtual = createVirtualInstanceNode(type, true); ResolvedJavaField[] fields = newVirtual.getFields(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Sat Feb 21 19:55:33 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(); @@ -129,7 +130,7 @@ * @param replacementGraph a replacement (i.e., snippet or method substitution) graph */ protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) { - final PhaseContext c = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getLowerer(), tool.getReplacements(), tool.assumptions(), tool.getStampProvider()); + final PhaseContext c = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getLowerer(), tool.getReplacements(), tool.getStampProvider()); if (!graph().hasValueProxies()) { new RemoveValueProxyPhase().apply(replacementGraph); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Sat Feb 21 19:55:33 2015 +0100 @@ -45,7 +45,9 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.inlining.*; @@ -96,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(); } } @@ -175,16 +188,16 @@ MetaAccessProvider metaAccess = providers.getMetaAccess(); SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); Suites suites = suitesProvider.createSuites(); + LIRSuites lirSuites = suitesProvider.createLIRSuites(); removeInliningPhase(suites); - StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), - OptimisticOptimizations.ALL).apply(graph); + StructuredGraph graph = new StructuredGraph(javaMethod, AllowAssumptions.NO); + new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); PhaseSuite graphBuilderSuite = getGraphBuilderSuite(suitesProvider); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); CompilationResultBuilderFactory factory = getOptimizedCallTargetInstrumentationFactory(backend.getTarget().arch.getName(), javaMethod); return compileGraph(graph, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), null, - suites, new CompilationResult(), factory); + suites, lirSuites, new CompilationResult(), factory); } private static Providers getGraalProviders() { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,187 @@ +/* + * 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.truffle.test; + +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 + * the instrumentation ultimate does anything, so should compile away. + */ +public class InstrumentationPartialEvaluationTest extends PartialEvaluationTest { + + public static Object constant42() { + return 42; + } + + @Test + public void constantValueUninstrumented() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedNoInstruments() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + result.probe(); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedNullInstrument() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument = Instrument.create(new DefaultEventListener(), "Null test Instrument"); + probe.attach(instrument); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedNullInstrumentDisposed() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument = Instrument.create(new DefaultEventListener(), "Null test Instrument"); + probe.attach(instrument); + instrument.dispose(); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedTwoNullInstruments() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1"); + probe.attach(instrument1); + Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2"); + probe.attach(instrument2); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedThreeNullInstruments() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1"); + probe.attach(instrument1); + Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2"); + probe.attach(instrument2); + Instrument instrument3 = Instrument.create(new DefaultEventListener(), "Null test Instrument 3"); + probe.attach(instrument3); + assertPartialEvalEquals("constant42", root); + } + + @Test + public void constantValueProbedThreeNullInstrumentsOneDisposed() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + RootTestNode root = new RootTestNode(fd, "constantValue", result); + root.adoptChildren(); + Probe probe = result.probe(); + Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1"); + probe.attach(instrument1); + Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2"); + probe.attach(instrument2); + Instrument instrument3 = Instrument.create(new DefaultEventListener(), "Null test Instrument 3"); + probe.attach(instrument3); + 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. + Probe.registerASTProber(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; + } + + }); + } + }); + 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 + + } +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,11 +24,11 @@ import org.junit.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -53,18 +53,16 @@ } protected OptimizedCallTarget compileHelper(String methodName, RootNode root, Object[] arguments) { - Assumptions assumptions = new Assumptions(true); final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); - StructuredGraph actual = partialEval(compilable, arguments, assumptions); - truffleCompiler.compileMethodHelper(actual, assumptions, methodName, getSpeculationLog(), compilable); + StructuredGraph actual = partialEval(compilable, arguments, AllowAssumptions.YES); + truffleCompiler.compileMethodHelper(actual, methodName, null, getSpeculationLog(), compilable); return compilable; } protected OptimizedCallTarget assertPartialEvalEquals(String methodName, RootNode root, Object[] arguments) { - Assumptions assumptions = new Assumptions(true); final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); - StructuredGraph actual = partialEval(compilable, arguments, assumptions); - truffleCompiler.compileMethodHelper(actual, assumptions, methodName, getSpeculationLog(), compilable); + StructuredGraph actual = partialEval(compilable, arguments, AllowAssumptions.YES); + truffleCompiler.compileMethodHelper(actual, methodName, null, getSpeculationLog(), compilable); removeFrameStates(actual); StructuredGraph expected = parseForComparison(methodName); Assert.assertEquals(getCanonicalGraphString(expected, true, true), getCanonicalGraphString(actual, true, true)); @@ -76,40 +74,39 @@ } protected void assertPartialEvalNoInvokes(RootNode root, Object[] arguments) { - Assumptions assumptions = new Assumptions(true); final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); - StructuredGraph actual = partialEval(compilable, arguments, assumptions); + 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); } } - protected StructuredGraph partialEval(OptimizedCallTarget compilable, Object[] arguments, final Assumptions assumptions) { + protected StructuredGraph partialEval(OptimizedCallTarget compilable, Object[] arguments, AllowAssumptions allowAssumptions) { // Executed AST so that all classes are loaded and initialized. compilable.call(arguments); compilable.call(arguments); compilable.call(arguments); try (Scope s = Debug.scope("TruffleCompilation", new TruffleDebugJavaMethod(compilable))) { - return truffleCompiler.getPartialEvaluator().createGraph(compilable, assumptions); + 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(); } - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new DeadCodeEliminationPhase().apply(graph); } protected StructuredGraph parseForComparison(final String methodName) { try (Scope s = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName))) { - StructuredGraph graph = parseEager(methodName); + StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); compile(graph.method(), graph); return graph; } catch (Throwable e) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java Sat Feb 21 19:55:33 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.ProbeNode.WrapperNode; import com.oracle.truffle.api.nodes.*; public abstract class AbstractTestNode extends Node { @@ -31,5 +32,15 @@ super(null); } + @Override + public boolean isInstrumentable() { + return true; + } + + @Override + public WrapperNode createWrapperNode() { + return new WrapperTestNode(this); + } + public abstract int execute(VirtualFrame frame); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,7 +30,7 @@ @Children private final AbstractTestNode[] statements; - public BlockTestNode(AbstractTestNode[] statements) { + public BlockTestNode(AbstractTestNode... statements) { this.statements = statements; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/WrapperTestNode.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/WrapperTestNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,80 @@ +/* + * 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode; +import com.oracle.truffle.api.nodes.*; + +/** + * Support for PE testing instrumentation. + */ +public final class WrapperTestNode extends AbstractTestNode implements WrapperNode { + + @Child private AbstractTestNode child; + @Child private ProbeNode probeNode; + + public WrapperTestNode(AbstractTestNode child) { + this.child = child; + } + + public String instrumentationInfo() { + return "Wrapper for PE test nodes"; + } + + @Override + public boolean isInstrumentable() { + return false; + } + + public void insertProbe(ProbeNode newProbeNode) { + this.probeNode = newProbeNode; + } + + public Probe getProbe() { + return probeNode.getProbe(); + } + + @Override + public Node getChild() { + return child; + } + + @Override + public int execute(VirtualFrame frame) { + probeNode.enter(child, frame); + try { + final int result = child.execute(frame); + probeNode.returnValue(child, frame, result); + return result; + } catch (KillException e) { + throw (e); + } catch (Exception e) { + probeNode.returnExceptional(child, frame, e); + throw (e); + } + + } + +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,13 +22,11 @@ */ package com.oracle.graal.truffle; -import java.nio.*; import java.lang.reflect.*; import java.util.*; import sun.misc.*; -import com.oracle.graal.api.meta.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; @@ -43,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; @@ -69,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() { @@ -85,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 = alignPrimitive(slot, Kind.Byte); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Byte.ordinal(); - return unsafeGetByte(getPrimitiveLocals(), offset, condition, slot); + 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 = alignPrimitive(slot, Kind.Boolean); - unsafePutByte(getPrimitiveLocals(), offset, value, 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 = alignPrimitive(slot, Kind.Boolean); - boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Boolean.ordinal(); - return unsafeGetBoolean(getPrimitiveLocals(), offset, condition, slot); + 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 = alignPrimitive(slot, Kind.Boolean); - unsafePutBoolean(getPrimitiveLocals(), offset, value, 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 = alignPrimitive(slot, Kind.Float); - 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 = alignPrimitive(slot, Kind.Float); + 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 = alignPrimitive(slot, Kind.Long); - 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 = alignPrimitive(slot, Kind.Long); + 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 = alignPrimitive(slot, Kind.Int); - 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 = alignPrimitive(slot, Kind.Int); + 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 = alignPrimitive(slot, Kind.Double); - 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 = alignPrimitive(slot, Kind.Double); + private void setDoubleUnsafe(int slotIndex, FrameSlot slot, double value) { + long offset = getPrimitiveOffset(slotIndex); unsafePutDouble(getPrimitiveLocals(), offset, value, slot); } @@ -243,65 +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 alignPrimitive(FrameSlot slot, Kind forKind) { - long offset = Unsafe.ARRAY_LONG_BASE_OFFSET + slot.getIndex() * (long) Unsafe.ARRAY_LONG_INDEX_SCALE; - if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - // On big endian, we use int in long type, which means, when byteCount() <=4, the value - // is right aligned in the 4 byte half, which has the lower address. - offset += Kind.Long.getByteCount() - Math.min((long) Unsafe.ARRAY_LONG_INDEX_SCALE, 4 + forKind.getByteCount()); - } - return offset; + 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); } } @@ -329,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"}) @@ -368,16 +387,6 @@ } @SuppressWarnings("unused") - static boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getBoolean(receiver, offset); - } - - @SuppressWarnings("unused") - static byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getByte(receiver, offset); - } - - @SuppressWarnings("unused") static int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity) { return UNSAFE.getInt(receiver, offset); } @@ -403,16 +412,6 @@ } @SuppressWarnings("unused") - static void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity) { - UNSAFE.putBoolean(receiver, offset, value); - } - - @SuppressWarnings("unused") - static void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity) { - UNSAFE.putByte(receiver, offset, value); - } - - @SuppressWarnings("unused") static void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity) { UNSAFE.putInt(receiver, offset, value); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,10 +34,12 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.truffle.debug.*; +import com.oracle.graal.truffle.unsafe.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.unsafe.*; public abstract class GraalTruffleRuntime implements TruffleRuntime { @@ -111,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 @@ -181,6 +187,9 @@ } public T getCapability(Class capability) { + if (capability == UnsafeAccessFactory.class) { + return capability.cast(new UnsafeAccessFactoryImpl()); + } return null; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.*; import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; @@ -50,7 +51,8 @@ @Override public void check() throws InvalidAssumptionException { - if (!isValid) { + if (!this.isValid()) { + CompilerDirectives.transferToInterpreterAndInvalidate(); throw new InvalidAssumptionException(); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,7 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; @@ -38,9 +38,12 @@ 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.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -97,7 +100,7 @@ } } - public StructuredGraph createGraph(final OptimizedCallTarget callTarget, final Assumptions assumptions) { + public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions) { if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) { constantReceivers = new HashSet<>(); } @@ -108,7 +111,7 @@ throw Debug.handle(e); } - final StructuredGraph graph = new StructuredGraph(callTarget.toString(), callRootMethod); + final StructuredGraph graph = new StructuredGraph(callTarget.toString(), callRootMethod, allowAssumptions); assert graph != null : "no graph for root method"; try (Scope s = Debug.scope("CreateGraph", graph); Indent indent = Debug.logAndIndent("createGraph %s", graph)) { @@ -117,14 +120,14 @@ if (CacheGraphs.getValue()) { graphCache = new HashMap<>(); } - PhaseContext baseContext = new PhaseContext(providers, assumptions); - HighTierContext tierContext = new HighTierContext(providers, assumptions, graphCache, new PhaseSuite(), OptimisticOptimizations.NONE); + PhaseContext baseContext = new PhaseContext(providers); + HighTierContext tierContext = new HighTierContext(providers, graphCache, new PhaseSuite(), OptimisticOptimizations.NONE); if (TruffleCompilerOptions.FastPE.getValue()) { - fastPartialEvaluation(callTarget, assumptions, graph, baseContext, tierContext); + fastPartialEvaluation(callTarget, graph, baseContext, tierContext); } else { createRootGraph(graph); - partialEvaluation(callTarget, assumptions, graph, baseContext, tierContext); + partialEvaluation(callTarget, graph, baseContext, tierContext); } if (Thread.currentThread().isInterrupted()) { @@ -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,15 +183,56 @@ } } - 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; @@ -207,21 +241,32 @@ } @SuppressWarnings("unused") - private void fastPartialEvaluation(OptimizedCallTarget callTarget, Assumptions assumptions, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) { + 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 = new DefaultGraphBuilderPlugins(); - Iterable sl = Services.load(GraphBuilderPluginsProvider.class); - for (GraphBuilderPluginsProvider p : sl) { - p.registerPlugins(providers.getMetaAccess(), plugins); + 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"); + + 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); + } + } } - TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), newConfig, plugins, - TruffleCompilerImpl.Optimizations).apply(graph); - Debug.dump(graph, "After FastPE"); + + // 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)) { @@ -232,7 +277,7 @@ } } - private void partialEvaluation(final OptimizedCallTarget callTarget, final Assumptions assumptions, final StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) { + private void partialEvaluation(final OptimizedCallTarget callTarget, final StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) { injectConstantCallTarget(graph, callTarget, baseContext); Debug.dump(graph, "Before expansion"); @@ -242,7 +287,7 @@ expansionLogger = new TruffleExpansionLogger(providers, graph); } - expandTree(graph, assumptions, expansionLogger); + expandTree(graph, expansionLogger); TruffleInliningCache inliningCache = null; if (TruffleFunctionInlining.getValue()) { @@ -252,7 +297,7 @@ } } - expandDirectCalls(graph, assumptions, expansionLogger, callTarget.getInlining(), inliningCache); + expandDirectCalls(graph, expansionLogger, callTarget.getInlining(), inliningCache); if (Thread.currentThread().isInterrupted()) { return; @@ -267,7 +312,7 @@ } catch (Throwable t) { Debug.handle(t); } - } while (expandTree(graph, assumptions, expansionLogger)); + } while (expandTree(graph, expansionLogger)); if (expansionLogger != null) { expansionLogger.print(callTarget); @@ -275,25 +320,23 @@ } public StructuredGraph createRootGraph(StructuredGraph graph) { - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), configForRoot, - TruffleCompilerImpl.Optimizations).apply(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompilerImpl.Optimizations).apply(graph); return graph; } - public StructuredGraph createInlineGraph(String name) { - StructuredGraph graph = new StructuredGraph(name, callInlinedMethod); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), configForRoot, - TruffleCompilerImpl.Optimizations).apply(graph); + public StructuredGraph createInlineGraph(String name, StructuredGraph caller) { + StructuredGraph graph = new StructuredGraph(name, callInlinedMethod, AllowAssumptions.from(caller.getAssumptions() != null)); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompilerImpl.Optimizations).apply(graph); return graph; } 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); @@ -339,8 +382,8 @@ new DebugHistogramAsciiPrinter(TTY.out().out()).print(histogram); } - private boolean expandTree(StructuredGraph graph, Assumptions assumptions, TruffleExpansionLogger expansionLogger) { - PhaseContext phaseContext = new PhaseContext(providers, assumptions); + private boolean expandTree(StructuredGraph graph, TruffleExpansionLogger expansionLogger) { + PhaseContext phaseContext = new PhaseContext(providers); boolean changed = false; boolean changedInIteration; ArrayDeque queue = new ArrayDeque<>(); @@ -437,7 +480,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(); @@ -481,23 +524,23 @@ } } - private void expandDirectCalls(StructuredGraph graph, Assumptions assumptions, TruffleExpansionLogger expansionLogger, TruffleInlining inlining, TruffleInliningCache inliningCache) { - PhaseContext phaseContext = new PhaseContext(providers, assumptions); + private void expandDirectCalls(StructuredGraph graph, TruffleExpansionLogger expansionLogger, TruffleInlining inlining, TruffleInliningCache inliningCache) { + PhaseContext phaseContext = new PhaseContext(providers); - for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { - StructuredGraph inlineGraph = parseDirectCallGraph(phaseContext, assumptions, inlining, inliningCache, methodCallTargetNode); + for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.TYPE).snapshot()) { + StructuredGraph inlineGraph = parseDirectCallGraph(phaseContext, graph, inlining, inliningCache, methodCallTargetNode); if (inlineGraph != null) { expandTreeInline(graph, phaseContext, expansionLogger, methodCallTargetNode, inlineGraph); } } // non inlined direct calls need to be expanded until TruffleCallBoundary. - expandTree(graph, assumptions, expansionLogger); + expandTree(graph, expansionLogger); assert noDirectCallsLeft(graph); } 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; } @@ -505,13 +548,32 @@ return true; } - private StructuredGraph parseDirectCallGraph(PhaseContext phaseContext, Assumptions assumptions, TruffleInlining inlining, TruffleInliningCache inliningCache, + private StructuredGraph parseDirectCallGraph(PhaseContext phaseContext, StructuredGraph caller, TruffleInlining inlining, TruffleInliningCache inliningCache, MethodCallTargetNode methodCallTargetNode) { OptimizedDirectCallNode callNode = resolveConstantCallNode(methodCallTargetNode); if (callNode == null) { 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()) { @@ -528,25 +590,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, assumptions, null, decision); - } else { - graph = inliningCache.getCachedGraph(phaseContext, assumptions, decision); - } - decision.getProfile().setGraalDeepNodeCount(graph.getNodeCount()); - - assumptions.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) { @@ -589,17 +635,17 @@ return (OptimizedDirectCallNode) value; } - private StructuredGraph createInlineGraph(PhaseContext phaseContext, Assumptions assumptions, TruffleInliningCache cache, TruffleInliningDecision decision) { + private StructuredGraph createInlineGraph(PhaseContext phaseContext, StructuredGraph caller, TruffleInliningCache cache, TruffleInliningDecision decision) { try (Scope s = Debug.scope("GuestLanguageInlinedGraph", new DebugDumpScope(decision.getTarget().toString()))) { OptimizedCallTarget target = decision.getTarget(); - StructuredGraph inlineGraph = createInlineGraph(target.toString()); + StructuredGraph inlineGraph = createInlineGraph(target.toString(), caller); injectConstantCallTarget(inlineGraph, decision.getTarget(), phaseContext); TruffleExpansionLogger expansionLogger = null; if (TraceTruffleExpansion.getValue()) { expansionLogger = new TruffleExpansionLogger(providers, inlineGraph); } - expandTree(inlineGraph, assumptions, expansionLogger); - expandDirectCalls(inlineGraph, assumptions, expansionLogger, decision, cache); + expandTree(inlineGraph, expansionLogger); + expandDirectCalls(inlineGraph, expansionLogger, decision, cache); if (expansionLogger != null) { expansionLogger.print(target); @@ -630,11 +676,11 @@ this.cache = new HashMap<>(); } - public StructuredGraph getCachedGraph(PhaseContext phaseContext, Assumptions assumptions, TruffleInliningDecision decision) { + public StructuredGraph getCachedGraph(PhaseContext phaseContext, StructuredGraph caller, TruffleInliningDecision decision) { CacheKey cacheKey = new CacheKey(decision); StructuredGraph inlineGraph = cache.get(cacheKey); if (inlineGraph == null) { - inlineGraph = createInlineGraph(phaseContext, assumptions, this, decision); + inlineGraph = createInlineGraph(phaseContext, caller, this, decision); cache.put(cacheKey, inlineGraph); } return inlineGraph; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -25,7 +25,6 @@ import java.util.*; import java.util.Map.Entry; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -35,6 +34,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @@ -60,7 +60,7 @@ private final HashMap, StructuredGraph> cache = new HashMap<>(); private final HashMap, Long> lastUsed = new HashMap<>(); - private final StructuredGraph markerGraph = new StructuredGraph(); + private final StructuredGraph markerGraph = new StructuredGraph(AllowAssumptions.NO); private final ResolvedJavaType stringBuilderClass; private final ResolvedJavaType runtimeExceptionClass; @@ -119,11 +119,11 @@ lookupExceedsMaxSize(); } - StructuredGraph graph; - PhaseContext phaseContext = new PhaseContext(providers, new Assumptions(false)); + StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO); + PhaseContext phaseContext = new PhaseContext(providers); try (Scope s = Debug.scope("TruffleCache", providers.getMetaAccess(), method)) { - graph = parseGraph(method, phaseContext); + graph = parseGraph(graph, phaseContext); if (graph == null) { return null; } @@ -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())); @@ -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); } @@ -268,9 +268,8 @@ canonicalizer.applyIncremental(graph, phaseContext, canonicalizerUsages); } - protected StructuredGraph parseGraph(final ResolvedJavaMethod method, final PhaseContext phaseContext) { - final StructuredGraph graph = new StructuredGraph(method); - new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), phaseContext.getStampProvider(), phaseContext.getAssumptions(), null, config, optimisticOptimizations).apply(graph); + protected StructuredGraph parseGraph(StructuredGraph graph, final PhaseContext phaseContext) { + new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), phaseContext.getStampProvider(), null, config, optimisticOptimizations).apply(graph); return graph; } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -27,8 +27,8 @@ import java.util.*; +import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -40,7 +40,9 @@ import com.oracle.graal.debug.internal.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; +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.*; @@ -59,6 +61,7 @@ private final Providers providers; private final Suites suites; + private final LIRSuites lirSuites; private final PartialEvaluator partialEvaluator; private final Backend backend; private final GraphBuilderConfiguration config; @@ -66,7 +69,8 @@ private final TruffleCache truffleCache; private final GraalTruffleCompilationListener compilationNotify; - private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class}; + private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class, + VirtualMachineError.class, ClassCastException.class}; public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability, OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints); @@ -77,13 +81,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)); @@ -115,10 +130,10 @@ compilationNotify.notifyCompilationStarted(compilable); try { - Assumptions assumptions = new Assumptions(true); + PhaseSuite graphBuilderSuite = createGraphBuilderSuite(); try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) { - graph = partialEvaluator.createGraph(compilable, assumptions); + graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES); } if (Thread.currentThread().isInterrupted()) { @@ -127,21 +142,22 @@ if (!TruffleCompilerOptions.TruffleInlineAcrossTruffleBoundary.getValue()) { // Do not inline across Truffle boundaries. - for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.class)) { + for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.TYPE)) { mct.invoke().setUseForInlining(false); } } compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph); - CompilationResult compilationResult = compileMethodHelper(graph, assumptions, compilable.toString(), 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; } } - public CompilationResult compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode) { + public CompilationResult compileMethodHelper(StructuredGraph graph, String name, PhaseSuite graphBuilderSuite, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode) { try (Scope s = Debug.scope("TruffleFinal")) { Debug.dump(1, graph, "After TruffleTier"); } catch (Throwable e) { @@ -153,29 +169,33 @@ 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, createGraphBuilderSuite(), Optimizations, getProfilingInfo(graph), speculationLog, - suites, 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); } compilationNotify.notifyCompilationGraalTierFinished((OptimizedCallTarget) predefinedInstalledCode, graph); + if (graph.isInlinedMethodRecordingEnabled()) { + result.setMethods(graph.method(), graph.getInlinedMethods()); + } else { + assert result.getMethods() == null; + } + List validAssumptions = new ArrayList<>(); - Assumptions newAssumptions = new Assumptions(true); - if (assumptions != null) { - for (Assumption assumption : assumptions.getAssumptions()) { + Set newAssumptions = new HashSet<>(); + for (Assumption assumption : graph.getAssumptions()) { + processAssumption(newAssumptions, assumption, validAssumptions); + } + + if (result.getAssumptions() != null) { + for (Assumption assumption : result.getAssumptions()) { processAssumption(newAssumptions, assumption, validAssumptions); } } - if (result.getAssumptions() != null) { - for (Assumption assumption : result.getAssumptions().getAssumptions()) { - processAssumption(newAssumptions, assumption, validAssumptions); - } - } - - result.setAssumptions(newAssumptions); + result.setAssumptions(newAssumptions.toArray(new Assumption[newAssumptions.size()])); InstalledCode installedCode; try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); TimerCloseable a = CodeInstallationTime.start(); Closeable c = CodeInstallationMemUse.start()) { @@ -197,19 +217,18 @@ private PhaseSuite createGraphBuilderSuite() { PhaseSuite suite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); - GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous(); iterator.remove(); - iterator.add(new GraphBuilderPhase(config, graphBuilderPhase.getGraphBuilderPlugins())); + iterator.add(new GraphBuilderPhase(config)); return suite; } - public void processAssumption(Assumptions newAssumptions, Assumption assumption, List manual) { + public void processAssumption(Set newAssumptions, Assumption assumption, List manual) { if (assumption != null) { if (assumption instanceof AssumptionValidAssumption) { AssumptionValidAssumption assumptionValidAssumption = (AssumptionValidAssumption) assumption; manual.add(assumptionValidAssumption); } else { - newAssumptions.record(assumption); + newAssumptions.add(assumption); } } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; import com.oracle.graal.truffle.substitutions.*; +import com.oracle.graal.truffle.unsafe.*; import com.oracle.truffle.api.*; /** @@ -42,19 +43,22 @@ private final Replacements graalReplacements; protected TruffleReplacements(Providers providers, SnippetReflectionProvider snippetReflection) { - super(providers, snippetReflection, providers.getReplacements().getAssumptions(), providers.getCodeCache().getTarget()); + super(providers, snippetReflection, providers.getCodeCache().getTarget()); this.graalReplacements = providers.getReplacements(); registerTruffleSubstitutions(); } 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); + 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationFailureListener.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Sat Feb 21 19:55:33 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,10 +22,12 @@ */ package com.oracle.graal.truffle.nodes; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -37,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; } @@ -62,14 +66,15 @@ @Override public void simplify(SimplifierTool tool) { ValueNode assumption = getAssumption(); - if (tool.assumptions() != null && assumption.isConstant()) { + Assumptions assumptions = graph().getAssumptions(); + if (assumption.isConstant()) { JavaConstant c = assumption.asJavaConstant(); assert c.getKind() == Kind.Object; Object object = getSnippetReflection().asObject(Object.class, c); OptimizedAssumption assumptionObject = (OptimizedAssumption) object; StructuredGraph graph = graph(); if (assumptionObject.isValid()) { - tool.assumptions().record(new AssumptionValidAssumption(assumptionObject)); + assumptions.record(new AssumptionValidAssumption(assumptionObject)); if (super.getReturnType().getKind() == Kind.Boolean) { graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(true, graph())); } else { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IsCompilationConstantNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Sat Feb 21 19:55:33 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); } - tool.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); + 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); } @@ -195,11 +209,7 @@ Kind graalKind = null; switch (kind) { case Boolean: - graalKind = Kind.Boolean; - break; case Byte: - graalKind = Kind.Byte; - break; case Int: graalKind = Kind.Int; break; @@ -234,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 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +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.truffle.nodes.typesystem; - -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.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.truffle.nodes.*; - -/** - * Load of a final value from a location specified as an offset relative to an object. - * - * Substitution for method CompilerDirectives#unsafeGet*. - */ -@NodeInfo -public final class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable { - @Input ValueNode object; - @Input ValueNode offset; - @Input ValueNode condition; - @Input ValueNode location; - protected final Kind accessKind; - - public CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) { - super(StampFactory.forKind(accessKind.getStackKind())); - this.object = object; - this.offset = offset; - this.condition = condition; - this.location = location; - this.accessKind = accessKind; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - if (object.isConstant() && !object.isNullConstant() && offset.isConstant() && condition.isConstant() && condition.asJavaConstant().asInt() == 1) { - JavaConstant constant = tool.getConstantReflection().getMemoryAccessProvider().readUnsafeConstant(accessKind, object.asJavaConstant(), offset.asJavaConstant().asLong()); - return ConstantNode.forConstant(constant, tool.getMetaAccess()); - } - return this; - } - - /** - * @see UnsafeLoadNode#virtualize(VirtualizerTool) - */ - @Override - public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object); - if (state != null && state.getState() == EscapeState.Virtual) { - ValueNode offsetValue = tool.getReplacedValue(offset); - if (offsetValue.isConstant()) { - long constantOffset = offsetValue.asJavaConstant().asLong(); - int entryIndex = state.getVirtualObject().entryIndexForOffset(constantOffset, accessKind); - if (entryIndex != -1) { - ValueNode entry = state.getEntry(entryIndex); - if (entry.getKind() == getKind() || state.getVirtualObject().entryKind(entryIndex) == accessKind) { - tool.replaceWith(entry); - } - } - } - } - } - - @Override - public void lower(LoweringTool tool) { - CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph())); - LocationIdentity locationIdentity; - if (!location.isConstant() || location.isNullConstant()) { - locationIdentity = LocationIdentity.ANY_LOCATION; - } else { - locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); - } - UnsafeLoadNode result = graph().add(new UnsafeLoadNode(object, offset, accessKind, locationIdentity, compare)); - graph().replaceFixedWithFixed(this, result); - result.lower(tool); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static T load(Object object, long offset, boolean condition, Object locationIdentity, @ConstantNodeParameter Kind kind) { - return UnsafeLoadNode.load(object, offset, kind, null); - } -} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Sat Feb 21 19:55:33 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; } @@ -63,7 +64,7 @@ } else { locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); } - CompareNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true)); + LogicNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true), tool.getConstantReflection()); Kind returnKind = this.getTargetMethod().getSignature().getReturnKind(); return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Sat Feb 21 19:55:33 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; } @@ -64,7 +66,7 @@ } else { Stamp piStamp = StampFactory.declaredTrusted(lookupJavaType, nonNullArgument.asJavaConstant().asInt() != 0); ConditionAnchorNode valueAnchorNode = graph().add( - new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph())))); + new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection()))); PiNode piCast = graph().unique(new PiNode(objectArgument, piStamp, valueAnchorNode)); replaceAtUsages(piCast); graph().replaceFixedWithFixed(this, valueAnchorNode); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Sat Feb 21 19:55:33 2015 +0100 @@ -31,7 +31,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.truffle.nodes.*; import com.oracle.graal.truffle.nodes.frame.*; -import com.oracle.graal.truffle.nodes.typesystem.*; import com.oracle.truffle.api.*; @ClassSubstitution(CompilerDirectives.class) @@ -74,103 +73,13 @@ @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); - - @MacroSubstitution(macro = UnsafeTypeCastMacroNode.class, isStatic = true) - public static native Object unsafeCast(Object value, Class clazz, boolean condition, boolean nonNull); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native short unsafeGetShort(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutShort(Object receiver, long offset, short value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity); - @MethodSubstitution - public static boolean unsafeGetFinalBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Boolean); - } - - @MethodSubstitution - public static byte unsafeGetFinalByte(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Byte); - } - - @MethodSubstitution - public static short unsafeGetFinalShort(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Short); - } - - @MethodSubstitution - public static int unsafeGetFinalInt(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Int); - } - - @MethodSubstitution - public static long unsafeGetFinalLong(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Long); - } - - @MethodSubstitution - public static float unsafeGetFinalFloat(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Float); - } - - @MethodSubstitution - public static double unsafeGetFinalDouble(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Double); - } - - @MethodSubstitution - public static Object unsafeGetFinalObject(Object receiver, long offset, boolean condition, Object locationIdentity) { - return CustomizedUnsafeLoadFinalNode.load(receiver, offset, condition, locationIdentity, Kind.Object); + public static boolean isCompilationConstant(Object value) { + return IsCompilationConstantNode.check(value); } @MethodSubstitution public static void materialize(Object obj) { ForceMaterializeNode.force(obj); } - } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Sat Feb 21 19:55:33 2015 +0100 @@ -41,12 +41,6 @@ public static native Object unsafeCast(Object value, Class clazz, boolean condition, boolean nonNull); @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) public static native int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity); @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) @@ -62,12 +56,6 @@ public static native Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity); @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) public static native void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity); @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,30 +26,105 @@ 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.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.*; import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.nodes.*; +import com.oracle.graal.truffle.nodes.arithmetic.*; import com.oracle.graal.truffle.nodes.frame.*; +import com.oracle.graal.truffle.unsafe.*; import com.oracle.truffle.api.*; 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); + + 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) { + if (arg.isConstant()) { + Constant constant = arg.asConstant(); + OptimizedAssumption assumption = builder.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant); + builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(assumption.isValid()))); + if (assumption.isValid()) { + builder.getAssumptions().record(new AssumptionValidAssumption(assumption)); + } + } else { + throw builder.bailout("assumption could not be reduced to a constant"); + } + return true; + } + }); + } - // CompilerDirectives.class + public static void registerExactMathPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration 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; + } + }); + r.register2("addExact", Long.TYPE, Long.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Long, builder.append(new IntegerAddExactNode(x, y))); + return true; + } + }); + r.register2("subtractExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Int.getStackKind(), builder.append(new IntegerSubExactNode(x, y))); + return true; + } + }); + r.register2("subtractExact", Long.TYPE, Long.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Long, builder.append(new IntegerSubExactNode(x, y))); + return true; + } + }); + r.register2("multiplyExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Int.getStackKind(), builder.append(new IntegerMulExactNode(x, y))); + return true; + } + }); + r.register2("multiplyExact", Long.TYPE, Long.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Long, builder.append(new IntegerMulExactNode(x, y))); + return true; + } + }); + } + + 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) { @@ -87,25 +162,26 @@ }); r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { - builder.append(new BranchProbabilityNode(probability, condition)); + builder.push(Kind.Boolean.getStackKind(), builder.append(new BranchProbabilityNode(probability, condition))); return true; } }); 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() { @@ -114,24 +190,48 @@ return true; } }); + } - // OptimizedCallTarget.class - r = new Registration(plugins, metaAccess, OptimizedCallTarget.class); + 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()) { @@ -140,19 +240,40 @@ if (javaType == null) { builder.push(Kind.Object, object); } else { - Stamp piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0); - ConditionAnchorNode valueAnchorNode = builder.append(new ConditionAnchorNode(CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, - ConstantNode.forBoolean(true, object.graph())))); + 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) { + LogicConstantNode logicConstantNode = (LogicConstantNode) compareNode; + if (logicConstantNode.getValue()) { + skipAnchor = true; + } + } + ConditionAnchorNode valueAnchorNode = null; + if (!skipAnchor) { + valueAnchorNode = builder.append(new ConditionAnchorNode(compareNode)); + } PiNode piCast = builder.append(new PiNode(object, piStamp, valueAnchorNode)); builder.push(Kind.Object, piCast); } return true; } - // TODO: should we throw GraalInternalError.shouldNotReachHere() here? - return false; + throw GraalInternalError.shouldNotReachHere("unsafeCast arguments could not reduce to a constant: " + clazz + ", " + nonNull); } }); - for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}) { + } + + protected static void registerUnsafeLoadStorePlugins(Registration r, Kind... kinds) { + for (Kind kind : kinds) { String kindName = kind.getJavaName(); kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); String getName = "unsafeGet" + kindName; @@ -178,7 +299,7 @@ } else { locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); } - CompareNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()))); + LogicNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), builder.getConstantReflection())); builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); return true; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnsafeAccessSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnsafeAccessSubstitutions.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,82 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.nodes.typesystem.*; +import com.oracle.graal.truffle.unsafe.*; + +@ClassSubstitution(UnsafeAccessImpl.class) +public class UnsafeAccessSubstitutions { + @MacroSubstitution(macro = UnsafeTypeCastMacroNode.class, isStatic = true) + public static native Object unsafeCast(Object value, Class clazz, boolean condition, boolean nonNull); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native short unsafeGetShort(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) + public static native Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutShort(Object receiver, long offset, short value, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity); + + @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) + public static native void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity); +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/unsafe/UnsafeAccessFactoryImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/unsafe/UnsafeAccessFactoryImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,33 @@ +/* + * 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 + * 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.unsafe; + +import sun.misc.*; + +import com.oracle.truffle.api.unsafe.*; + +public final class UnsafeAccessFactoryImpl implements UnsafeAccessFactory { + public UnsafeAccess createUnsafeAccess(Unsafe unsafe) { + return new UnsafeAccessImpl(unsafe); + } +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/unsafe/UnsafeAccessImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/unsafe/UnsafeAccessImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,189 @@ +/* + * 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 + * 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.unsafe; + +import java.lang.reflect.*; + +import sun.misc.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.unsafe.*; + +@SuppressWarnings("unused") +public final class UnsafeAccessImpl implements UnsafeAccess { + public UnsafeAccessImpl(Unsafe unsafe) { + } + + public T uncheckedCast(Object value, Class type, boolean condition, boolean nonNull) { + return unsafeCast(value, type, condition, nonNull); + } + + public boolean getBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetBoolean(receiver, offset, condition, locationIdentity); + } + + public byte getByte(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetByte(receiver, offset, condition, locationIdentity); + } + + public short getShort(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetShort(receiver, offset, condition, locationIdentity); + } + + public int getInt(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetInt(receiver, offset, condition, locationIdentity); + } + + public long getLong(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetLong(receiver, offset, condition, locationIdentity); + } + + public float getFloat(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetFloat(receiver, offset, condition, locationIdentity); + } + + public double getDouble(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetDouble(receiver, offset, condition, locationIdentity); + } + + public Object getObject(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafeGetObject(receiver, offset, condition, locationIdentity); + } + + public void putBoolean(Object receiver, long offset, boolean value, Object locationIdentity) { + unsafePutBoolean(receiver, offset, value, locationIdentity); + } + + public void putByte(Object receiver, long offset, byte value, Object locationIdentity) { + unsafePutByte(receiver, offset, value, locationIdentity); + } + + public void putShort(Object receiver, long offset, short value, Object locationIdentity) { + unsafePutShort(receiver, offset, value, locationIdentity); + } + + public void putInt(Object receiver, long offset, int value, Object locationIdentity) { + unsafePutInt(receiver, offset, value, locationIdentity); + } + + public void putLong(Object receiver, long offset, long value, Object locationIdentity) { + unsafePutLong(receiver, offset, value, locationIdentity); + } + + public void putFloat(Object receiver, long offset, float value, Object locationIdentity) { + unsafePutFloat(receiver, offset, value, locationIdentity); + } + + public void putDouble(Object receiver, long offset, double value, Object locationIdentity) { + unsafePutDouble(receiver, offset, value, locationIdentity); + } + + public void putObject(Object receiver, long offset, Object value, Object locationIdentity) { + unsafePutObject(receiver, offset, value, locationIdentity); + } + + @SuppressWarnings("unchecked") + private static T unsafeCast(Object value, Class type, boolean condition, boolean nonNull) { + return (T) value; + } + + private static boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getBoolean(receiver, offset); + } + + private static byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getByte(receiver, offset); + } + + private static short unsafeGetShort(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getShort(receiver, offset); + } + + private static int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getInt(receiver, offset); + } + + private static long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getLong(receiver, offset); + } + + private static float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getFloat(receiver, offset); + } + + private static double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getDouble(receiver, offset); + } + + private static Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity) { + return UNSAFE.getObject(receiver, offset); + } + + private static void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity) { + UNSAFE.putBoolean(receiver, offset, value); + } + + private static void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity) { + UNSAFE.putByte(receiver, offset, value); + } + + private static void unsafePutShort(Object receiver, long offset, short value, Object locationIdentity) { + UNSAFE.putShort(receiver, offset, value); + } + + private static void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity) { + UNSAFE.putInt(receiver, offset, value); + } + + private static void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity) { + UNSAFE.putLong(receiver, offset, value); + } + + private static void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity) { + UNSAFE.putFloat(receiver, offset, value); + } + + private static void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity) { + UNSAFE.putDouble(receiver, offset, value); + } + + private 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Sat Feb 21 19:55:33 2015 +0100 @@ -108,14 +108,14 @@ add("add virtual mapping", new Effect() { @Override public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { - assert node.isAlive() && !state.isAlive() && !state.isDeleted(); + assert node.isAlive() && !state.isDeleted(); FrameState stateAfter = node; for (int i = 0; i < stateAfter.virtualObjectMappingCount(); i++) { if (stateAfter.virtualObjectMappingAt(i).object() == state.object()) { stateAfter.virtualObjectMappings().remove(i); } } - stateAfter.addVirtualObjectMapping(graph.unique(state)); + stateAfter.addVirtualObjectMapping(state.isAlive() ? state : graph.unique(state)); } @Override diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,11 +24,13 @@ import java.util.*; +import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.virtual.nodes.*; /** * This class describes the state of a virtual object while iterating over the graph. It describes @@ -37,6 +39,9 @@ */ public class ObjectState extends Virtualizable.State { + public static final DebugMetric CREATE_ESCAPED_OBJECT_STATE = Debug.metric("CreateEscapeObjectState"); + public static final DebugMetric GET_ESCAPED_OBJECT_STATE = Debug.metric("GetEscapeObjectState"); + final VirtualObjectNode virtual; private EscapeState state; @@ -44,6 +49,8 @@ private ValueNode materializedValue; private LockState locks; + private EscapeObjectState cachedState; + public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, EscapeState state, List locks) { this(virtual, entries, state, (LockState) null); for (int i = locks.size() - 1; i >= 0; i--) { @@ -71,12 +78,23 @@ materializedValue = other.materializedValue; locks = other.locks; state = other.state; + cachedState = other.cachedState; } public ObjectState cloneState() { return new ObjectState(this); } + public EscapeObjectState createEscapeObjectState() { + GET_ESCAPED_OBJECT_STATE.increment(); + if (cachedState == null) { + CREATE_ESCAPED_OBJECT_STATE.increment(); + cachedState = isVirtual() ? new VirtualObjectState(virtual, entries) : new MaterializedObjectState(virtual, materializedValue); + } + return cachedState; + + } + @Override public EscapeState getState() { return state; @@ -104,7 +122,10 @@ public void setEntry(int index, ValueNode value) { assert isVirtual(); - entries[index] = value; + if (entries[index] != value) { + cachedState = null; + entries[index] = value; + } } public void escape(ValueNode materialized, EscapeState newState) { @@ -112,6 +133,7 @@ state = newState; materializedValue = materialized; entries = null; + cachedState = null; assert !isVirtual(); } @@ -123,7 +145,10 @@ public void updateMaterializedValue(ValueNode value) { assert !isVirtual(); - materializedValue = value; + if (value != materializedValue) { + cachedState = null; + materializedValue = value; + } } @Override diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,7 +26,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -39,8 +38,8 @@ public class PEReadEliminationClosure extends PartialEscapeClosure { - public PEReadEliminationClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) { - super(schedule, metaAccess, constantReflection, assumptions); + public PEReadEliminationClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + super(schedule, metaAccess, constantReflection); } @Override diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; @@ -39,7 +38,6 @@ import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.schedule.*; -import com.oracle.graal.virtual.nodes.*; public abstract class PartialEscapeClosure> extends EffectsClosure { @@ -94,8 +92,8 @@ */ public static final class Final extends PartialEscapeClosure { - public Final(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) { - super(schedule, metaAccess, constantReflection, assumptions); + public Final(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + super(schedule, metaAccess, constantReflection); } @Override @@ -109,10 +107,10 @@ } } - public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) { + public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { super(schedule, schedule.getCFG()); this.usages = schedule.getCFG().graph.createNodeBitMap(); - this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, assumptions, this); + this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, this); } /** @@ -163,7 +161,7 @@ frameState.applyToNonVirtual(new CollectVirtualObjectsClosure(virtual, effects, state)); collectLockedVirtualObjects(state, virtual); collectReferencedVirtualObjects(state, virtual); - addVirtualMappings(state, effects, frameState, virtual); + addVirtualMappings(effects, frameState, virtual); } } @@ -177,15 +175,9 @@ return frameState; } - private void addVirtualMappings(final BlockT state, final GraphEffectList effects, FrameState frameState, Set virtual) { + private static void addVirtualMappings(GraphEffectList effects, FrameState frameState, Set virtual) { for (ObjectState obj : virtual) { - EscapeObjectState v; - if (obj.isVirtual()) { - v = createVirtualObjectState(state, obj); - } else { - v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); - } - effects.addVirtualMapping(frameState, v); + effects.addVirtualMapping(frameState, obj.createEscapeObjectState()); } } @@ -207,24 +199,7 @@ } } - private EscapeObjectState createVirtualObjectState(final BlockT state, ObjectState obj) { - EscapeObjectState v; - ValueNode[] fieldState = obj.getEntries().clone(); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = getObjectState(state, fieldState[i]); - if (valueObj != null) { - if (valueObj.isVirtual()) { - fieldState[i] = valueObj.virtual; - } else { - fieldState[i] = valueObj.getMaterializedValue(); - } - } - } - v = new VirtualObjectState(obj.virtual, fieldState); - return v; - } - - private void collectLockedVirtualObjects(final BlockT state, final Set virtual) { + private void collectLockedVirtualObjects(final BlockT state, Set virtual) { for (ObjectState obj : state.getStates()) { if (obj.isVirtual() && obj.hasLocks()) { virtual.add(obj); @@ -240,6 +215,7 @@ if (obj.getState() == EscapeState.Virtual) { metric.increment(); state.materializeBefore(materializeBefore, obj.virtual, EscapeState.Materialized, effects); + updateStatesForMaterialized(state, obj); assert !obj.isVirtual(); return true; } else { @@ -248,6 +224,20 @@ } } + 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()) { + ValueNode[] entries = objState.getEntries(); + for (int i = 0; i < entries.length; i++) { + if (entries[i] == obj.virtual) { + objState.setEntry(i, obj.getMaterializedValue()); + } + } + } + } + } + private boolean replaceWithMaterialized(Node value, Node usage, FixedNode materializeBefore, BlockT state, ObjectState obj, GraphEffectList effects, DebugMetric metric) { boolean materialized = ensureMaterialized(state, obj, materializeBefore, effects, metric); effects.replaceFirstInput(usage, value, obj.getMaterializedValue()); @@ -539,8 +529,8 @@ int valueIndex = 0; while (valueIndex < values.length) { for (int i = 1; i < objStates.length; i++) { - ValueNode[] fields = objStates[i].getEntries(); - if (phis[valueIndex] == null && values[valueIndex] != fields[valueIndex]) { + ValueNode field = objStates[i].getEntry(valueIndex); + if (phis[valueIndex] == null && values[valueIndex] != field) { phis[valueIndex] = new ValuePhiNode(values[valueIndex].stamp().unrestricted(), merge); } } @@ -597,14 +587,16 @@ if (!objStates[i].isVirtual()) { break; } - ValueNode[] entries = objStates[i].getEntries(); - if (entries[entryIndex] instanceof VirtualObjectNode) { - ObjectState obj = blockStates.get(i).getObjectState((VirtualObjectNode) entries[entryIndex]); + ValueNode entry = objStates[i].getEntry(entryIndex); + if (entry instanceof VirtualObjectNode) { + ObjectState obj = blockStates.get(i).getObjectState((VirtualObjectNode) entry); Block predecessor = mergeBlock.getPredecessors().get(i); materialized |= ensureMaterialized(blockStates.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE); - entries[entryIndex] = obj.getMaterializedValue(); + if (objStates[i].isVirtual()) { + objStates[i].setEntry(entryIndex, entry = obj.getMaterializedValue()); + } } - afterMergeEffects.addPhiInput(phi, entries[entryIndex]); + afterMergeEffects.addPhiInput(phi, entry); } return materialized; } @@ -618,7 +610,7 @@ if (!state.isVirtual()) { break; } - afterMergeEffects.addPhiInput(phi, state.getEntries()[entryIndex]); + afterMergeEffects.addPhiInput(phi, state.getEntry(entryIndex)); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -89,9 +89,9 @@ protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) { assert schedule != null; if (readElimination) { - return new PEReadEliminationClosure(schedule, context.getMetaAccess(), context.getConstantReflection(), context.getAssumptions()); + return new PEReadEliminationClosure(schedule, context.getMetaAccess(), context.getConstantReflection()); } else { - return new PartialEscapeClosure.Final(schedule, context.getMetaAccess(), context.getConstantReflection(), context.getAssumptions()); + return new PartialEscapeClosure.Final(schedule, context.getMetaAccess(), context.getConstantReflection()); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,7 +26,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -41,13 +40,11 @@ private final MetaAccessProvider metaAccess; private final ConstantReflectionProvider constantReflection; - private final Assumptions assumptions; private final PartialEscapeClosure closure; - VirtualizerToolImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions, PartialEscapeClosure closure) { + VirtualizerToolImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, PartialEscapeClosure closure) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; - this.assumptions = assumptions; this.closure = closure; } @@ -66,11 +63,6 @@ return constantReflection; } - @Override - public Assumptions getAssumptions() { - return assumptions; - } - public void reset(PartialEscapeBlockState newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) { deleted = false; state = newState; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Sat Feb 21 19:55:33 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; } @@ -65,6 +66,17 @@ /* If the cast is unused, it can be eliminated. */ return input; } + + assert !stamp().isCompatible(input.stamp()); + if (input.isConstant()) { + /* Null pointers are uncritical for GC, so they can be constant folded. */ + if (input.asJavaConstant().isNull()) { + return ConstantNode.forIntegerStamp(stamp(), 0); + } else if (input.asJavaConstant().getKind().isNumericInteger() && input.asJavaConstant().asLong() == 0) { + return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, tool.getMetaAccess()); + } + } + return this; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Sat Feb 21 19:55:33 2015 +0100 @@ -113,6 +113,8 @@ protected void rewriteNode(StructuredGraph graph, Node node) { if (node instanceof CheckCastNode) { rewriteCheckCast(graph, (CheckCastNode) node); + } else if (node instanceof PiNode) { + rewritePi(graph, (PiNode) node); } else if (node instanceof LoadFieldNode) { rewriteLoadField(graph, (LoadFieldNode) node); } else if (node instanceof AccessIndexedNode) { @@ -133,6 +135,16 @@ } /** + * Remove casts between word types (which by now no longer have kind Object). + */ + protected void rewritePi(StructuredGraph graph, PiNode node) { + if (node.getKind() == wordKind) { + node.replaceAtUsages(node.object()); + graph.removeFloating(node); + } + } + + /** * Fold constant field reads, e.g. enum constants. */ protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java --- a/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.nfi/src/com/oracle/nfi/api/NativeFunctionPointer.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,120 +22,236 @@ */ package com.oracle.truffle.api.dsl.test; +import static com.oracle.truffle.api.dsl.test.TestHelper.*; +import static org.junit.Assert.*; + +import java.util.*; + import org.junit.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.DerivedAssumptionNodeFactory; -import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.DerivedAssumptionRedeclaredNodeFactory; -import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.MultipleAssumptionsNodeFactory; -import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.SingleAssumptionNodeFactory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.AssumptionArrayTestFactory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.CacheAssumptionTestFactory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.FieldTestFactory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.MethodTestFactory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.NodeFieldTest2Factory; +import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.StaticFieldTestFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; public class AssumptionsTest { @Test - public void testSingleAssumption() { + public void testField() { + CallTarget root = createCallTarget(FieldTestFactory.getInstance()); + FieldTest node = getNode(root); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(42)); + node.field.invalidate(); + try { + root.call(45); + fail(); + } catch (UnsupportedSpecializationException e) { + } + } + + @NodeChild + static class FieldTest extends ValueNode { + + protected final Assumption field = Truffle.getRuntime().createAssumption(); + + @Specialization(assumptions = "field") + static int do1(int value) { + return value; + } + } + + @Test + public void testNodeField() { Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(SingleAssumptionNodeFactory.getInstance(), assumption); + CallTarget root = createCallTarget(NodeFieldTest2Factory.getInstance(), assumption); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(42)); + assumption.invalidate(); + try { + root.call(45); + fail(); + } catch (UnsupportedSpecializationException e) { + } + } + + @NodeChild + @NodeField(name = "field", type = Assumption.class) + static class NodeFieldTest2 extends ValueNode { - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); + @Specialization(assumptions = "field") + static int do1(int value) { + return value; + } + } + + @Test + public void testStaticField() { + CallTarget root = createCallTarget(StaticFieldTestFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(42)); + StaticFieldTest.FIELD.invalidate(); + try { + root.call(45); + fail(); + } catch (UnsupportedSpecializationException e) { + } + } + + @NodeChild + static class StaticFieldTest extends ValueNode { + + static final Assumption FIELD = Truffle.getRuntime().createAssumption(); + + @Specialization(assumptions = "FIELD") + static int do1(int value) { + return value; + } + } + + @Test + public void testMethod() { + CallTarget root = createCallTarget(MethodTestFactory.getInstance()); + MethodTest node = getNode(root); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(42)); + node.hiddenAssumption.invalidate(); + try { + root.call(45); + fail(); + } catch (UnsupportedSpecializationException e) { + } } - @NodeAssumptions("assumption") - abstract static class SingleAssumptionNode extends ValueNode { + @NodeChild + static class MethodTest extends ValueNode { - @Specialization(assumptions = "assumption") - int do2() { - return 42; + private final Assumption hiddenAssumption = Truffle.getRuntime().createAssumption(); + + @Specialization(assumptions = "getAssumption()") + static int do1(int value) { + return value; } - @Fallback - Object doFallBack() { - return "42"; + Assumption getAssumption() { + return hiddenAssumption; + } + } + + @Test + public void testCacheAssumption() { + CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance()); + CacheAssumptionTest node = getNode(root); + assertEquals("do1", root.call(42)); + assertEquals("do1", root.call(43)); + assertEquals("do1", root.call(44)); + node.assumptions.get(42).invalidate(); + node.assumptions.put(42, null); // clear 42 + node.assumptions.get(43).invalidate(); + node.assumptions.get(44).invalidate(); + assertEquals("do1", root.call(42)); // recreates 42 + assertEquals("do2", root.call(43)); // invalid 43 -> remove -> insert do2 + assertEquals("do2", root.call(46)); // no more lines can be created. + } + + @Test + public void testCacheAssumptionLimit() { + CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance()); + assertEquals("do1", root.call(42)); + assertEquals("do1", root.call(43)); + assertEquals("do1", root.call(44)); + assertEquals("do2", root.call(45)); + assertEquals("do1", root.call(43)); + assertEquals("do1", root.call(44)); + } + + @NodeChild + @SuppressWarnings("unused") + static class CacheAssumptionTest extends ValueNode { + + private final Map assumptions = new HashMap<>(); + + @Specialization(guards = "value == cachedValue", assumptions = "getAssumption(cachedValue)") + static String do1(int value, @Cached("value") int cachedValue) { + return "do1"; + } + + @Specialization + static String do2(int value) { + return "do2"; + } + + Assumption getAssumption(int value) { + Assumption assumption = assumptions.get(value); + if (assumption == null) { + assumption = Truffle.getRuntime().createAssumption(); + assumptions.put(value, assumption); + } + return assumption; + } + } + + @Test + public void testAssumptionArrays() { + CallTarget root = createCallTarget(AssumptionArrayTestFactory.getInstance()); + AssumptionArrayTest node = getNode(root); + + Assumption a1 = Truffle.getRuntime().createAssumption(); + Assumption a2 = Truffle.getRuntime().createAssumption(); + + node.assumptions = new Assumption[]{a1, a2}; + + assertEquals("do1", root.call(42)); + + a2.invalidate(); + + assertEquals("do2", root.call(42)); + } + + @NodeChild + @SuppressWarnings("unused") + static class AssumptionArrayTest extends ValueNode { + + Assumption[] assumptions; + + @Specialization(assumptions = "assumptions") + static String do1(int value) { + return "do1"; + } + + @Specialization + static String do2(int value) { + return "do2"; } } - @Test - public void testMultipleAssumption() { - Assumption assumption1 = Truffle.getRuntime().createAssumption(); - Assumption assumption2 = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(MultipleAssumptionsNodeFactory.getInstance(), assumption1, assumption2); - - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption2.invalidate(); - Assert.assertEquals("41", TestHelper.executeWith(root)); - assumption1.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); - } - - @NodeAssumptions({"assumption1", "assumption2"}) - abstract static class MultipleAssumptionsNode extends ValueNode { - - @Specialization(assumptions = {"assumption1", "assumption2"}) - int doInt() { - return 42; - } - - @Specialization(assumptions = "assumption1") - Object doObject() { - return "41"; - } - - @Fallback - Object doFallBack() { - return "42"; + @NodeChild + static class ErrorIncompatibleReturnType extends ValueNode { + @ExpectError("Incompatible return type int. Assumptions must be assignable to Assumption or Assumption[].") + @Specialization(assumptions = "3") + static int do1(int value) { + return value; } } - @Test - public void testDerivedAssumption() { - Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); - Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(DerivedAssumptionNodeFactory.getInstance(), assumption, additionalAssumption); + @NodeChild + static class ErrorBoundDynamicValue extends ValueNode { - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption.invalidate(); - Assert.assertEquals(43, TestHelper.executeWith(root)); - additionalAssumption.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); - } - - @NodeAssumptions({"additionalAssumption"}) - abstract static class DerivedAssumptionNode extends SingleAssumptionNode { - - @Specialization(assumptions = "additionalAssumption") - int doIntDerived() { - return 43; + @ExpectError("Assumption expressions must not bind dynamic parameter values.") + @Specialization(assumptions = "createAssumption(value)") + static int do1(int value) { + return value; } - } - - @Test - public void testDerivedAssumptionRedeclared() { - Assumption additionalAssumption = Truffle.getRuntime().createAssumption(); - Assumption assumption = Truffle.getRuntime().createAssumption(); - TestRootNode root = TestHelper.createRoot(DerivedAssumptionRedeclaredNodeFactory.getInstance(), additionalAssumption, assumption); - - Assert.assertEquals(42, TestHelper.executeWith(root)); - assumption.invalidate(); - Assert.assertEquals(43, TestHelper.executeWith(root)); - additionalAssumption.invalidate(); - Assert.assertEquals("42", TestHelper.executeWith(root)); - } - - @NodeAssumptions({"additionalAssumption", "assumption"}) - abstract static class DerivedAssumptionRedeclaredNode extends SingleAssumptionNode { - - @Specialization(assumptions = "additionalAssumption") - int doIntDerived() { - return 43; + Assumption createAssumption(int value) { + return Truffle.getRuntime().createAssumption(String.valueOf(value)); } - } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,320 @@ +/* + * 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.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.BoundCacheFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.BoundCacheOverflowFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestBoundCacheOverflowContainsFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheFieldFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheMethodFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheNodeFieldFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithCachedAndDynamicParameterFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithJustCachedParameterFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestMultipleCachesFactory; +import com.oracle.truffle.api.dsl.test.CachedTestFactory.UnboundCacheFactory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +@SuppressWarnings("unused") +public class CachedTest { + + @Test + public void testUnboundCache() { + CallTarget root = createCallTarget(UnboundCacheFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(43)); + assertEquals(42, root.call(44)); + } + + @NodeChild + static class UnboundCache extends ValueNode { + @Specialization + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + } + + @Test + public void testBoundCache() { + CallTarget root = createCallTarget(BoundCacheFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + assertEquals(44, root.call(44)); + try { + root.call(45); + fail(); + } catch (UnsupportedSpecializationException e) { + } + } + + @NodeChild + static class BoundCache extends ValueNode { + + @Specialization(guards = "value == cachedValue", limit = "3") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + + } + + @Test + public void testBoundCacheOverflow() { + CallTarget root = createCallTarget(BoundCacheOverflowFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + assertEquals(-1, root.call(44)); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + assertEquals(-1, root.call(44)); + } + + @NodeChild + static class BoundCacheOverflow extends ValueNode { + + @Specialization(guards = "value == cachedValue", limit = "2") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + + @Specialization + static int do2(int value) { + return -1; + } + + } + + @Test + public void testBoundCacheOverflowContains() { + CallTarget root = createCallTarget(TestBoundCacheOverflowContainsFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + assertEquals(-1, root.call(44)); + assertEquals(-1, root.call(42)); + assertEquals(-1, root.call(43)); + assertEquals(-1, root.call(44)); + } + + @NodeChild + static class TestBoundCacheOverflowContains extends ValueNode { + + @Specialization(guards = "value == cachedValue", limit = "2") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + + @Specialization(contains = "do1") + static int do2(int value) { + return -1; + } + + } + + @Test + public void testCacheField() { + CallTarget root = createCallTarget(TestCacheFieldFactory.getInstance()); + assertEquals(3, root.call(42)); + assertEquals(3, root.call(43)); + } + + @NodeChild + static class TestCacheField extends ValueNode { + + protected int field = 3; + + @Specialization() + static int do1(int value, @Cached("field") int cachedValue) { + return cachedValue; + } + + } + + @Test + public void testCacheNodeField() { + CallTarget root = createCallTarget(TestCacheNodeFieldFactory.getInstance(), 21); + assertEquals(21, root.call(42)); + assertEquals(21, root.call(43)); + } + + @NodeChild + @NodeField(name = "field", type = int.class) + static class TestCacheNodeField extends ValueNode { + + @Specialization + static int do1(int value, @Cached("field") int cachedValue) { + return cachedValue; + } + + } + + @Test + public void testCacheMethod() { + TestCacheMethod.invocations = 0; + CallTarget root = createCallTarget(TestCacheMethodFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(43)); + assertEquals(42, root.call(44)); + assertEquals(1, TestCacheMethod.invocations); + } + + @NodeChild + static class TestCacheMethod extends ValueNode { + + static int invocations = 0; + + @Specialization + static int do1(int value, @Cached("someMethod(value)") int cachedValue) { + return cachedValue; + } + + static int someMethod(int value) { + invocations++; + return value; + } + + } + + @Test + public void testGuardWithJustCachedParameter() { + TestGuardWithJustCachedParameter.invocations = 0; + CallTarget root = createCallTarget(TestGuardWithJustCachedParameterFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(43)); + assertEquals(42, root.call(44)); + // guards with just cached parameters are just invoked on the slow path + assertEquals(assertionsEnabled() ? 4 : 1, TestGuardWithJustCachedParameter.invocations); + } + + @NodeChild + static class TestGuardWithJustCachedParameter extends ValueNode { + + static int invocations = 0; + + @Specialization(guards = "someMethod(cachedValue)") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + + static boolean someMethod(int value) { + invocations++; + return true; + } + + } + + @Test + public void testGuardWithCachedAndDynamicParameter() { + TestGuardWithCachedAndDynamicParameter.cachedMethodInvocations = 0; + TestGuardWithCachedAndDynamicParameter.dynamicMethodInvocations = 0; + CallTarget root = createCallTarget(TestGuardWithCachedAndDynamicParameterFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(42, root.call(43)); + assertEquals(42, root.call(44)); + // guards with just cached parameters are just invoked on the slow path + assertEquals(assertionsEnabled() ? 4 : 1, TestGuardWithCachedAndDynamicParameter.cachedMethodInvocations); + assertEquals(4, TestGuardWithCachedAndDynamicParameter.dynamicMethodInvocations); + } + + @NodeChild + static class TestGuardWithCachedAndDynamicParameter extends ValueNode { + + static int cachedMethodInvocations = 0; + static int dynamicMethodInvocations = 0; + + @Specialization(guards = {"dynamicMethod(value)", "cachedMethod(cachedValue)"}) + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + + static boolean cachedMethod(int value) { + cachedMethodInvocations++; + return true; + } + + static boolean dynamicMethod(int value) { + dynamicMethodInvocations++; + return true; + } + + } + + @NodeChild + static class TestMultipleCaches extends ValueNode { + + @Specialization + static int do1(int value, @Cached("value") int cachedValue1, @Cached("value") int cachedValue2) { + return cachedValue1 + cachedValue2; + } + + } + + @Test + public void testMultipleCaches() { + CallTarget root = createCallTarget(TestMultipleCachesFactory.getInstance()); + assertEquals(42, root.call(21)); + assertEquals(42, root.call(22)); + assertEquals(42, root.call(23)); + } + + @NodeChild + static class CachedError1 extends ValueNode { + @Specialization + static int do1(int value, @ExpectError("Incompatible return type int. The expression type must be equal to the parameter type double.")// + @Cached("value") double cachedValue) { + return value; + } + } + + @NodeChild + static class CachedError2 extends ValueNode { + + // caches are not allowed to make backward references + + @Specialization + static int do1(int value, + @ExpectError("The initializer expression of parameter 'cachedValue1' binds unitialized parameter 'cachedValue2. Reorder the parameters to resolve the problem.") @Cached("cachedValue2") int cachedValue1, + @Cached("value") int cachedValue2) { + return cachedValue1 + cachedValue2; + } + + } + + @NodeChild + static class CachedError3 extends ValueNode { + + // cyclic dependency between cached expressions + @Specialization + static int do1(int value, + @ExpectError("The initializer expression of parameter 'cachedValue1' binds unitialized parameter 'cachedValue2. Reorder the parameters to resolve the problem.") @Cached("cachedValue2") int cachedValue1, + @Cached("cachedValue1") int cachedValue2) { + return cachedValue1 + cachedValue2; + } + + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -51,11 +51,11 @@ return true; } - @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2", - "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1"}) + @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()", + "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()"}) public int execute() { return 42; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -100,7 +100,7 @@ return a == 0; } - @Specialization(guards = "isZero") + @Specialization(guards = "isZero(a)") int f1(int a) { return a + 1; } @@ -142,17 +142,16 @@ return a > 0; } - @Implies("isGreaterZero") static boolean isOne(int a) { return a == 1; } - @Specialization(guards = {"isOne"}) + @Specialization(guards = {"isOne(a)"}) int f1(int a) { return a + 1; } - @Specialization(contains = "f1", guards = {"isGreaterZero"}) + @Specialization(contains = "f1", guards = {"isGreaterZero(a)"}) int f2(int a) { if (a == 1) { return 2; @@ -190,21 +189,16 @@ @NodeChild("a") abstract static class Contains4 extends ValueNode { - static boolean isGreaterEqualZero(int a) { - return a >= 0; - } - - @Implies("isGreaterEqualZero") static boolean isOne(int a) { return a == 1; } - @Specialization(guards = {"isOne"}) + @Specialization(guards = "isOne(a)") int f0(int a) { return 1; } - @Specialization(contains = "f0", guards = {"isGreaterEqualZero"}) + @Specialization(contains = "f0", guards = "a >= 0") int f1(int a) { return a; } @@ -329,7 +323,7 @@ return a; } - @ExpectError({"Specialization is not reachable. It is shadowed by f0(double).", "The contained specialization 'f0' is not fully compatible.%"}) + @ExpectError({"Specialization is not reachable. It is shadowed by f0(double)."}) @Specialization(contains = "f0") int f1(int a) { // implicit type return a; @@ -343,7 +337,6 @@ return a; } - @ExpectError("The contained specialization 'f0' is not fully compatible.%") @Specialization(contains = "f0") Object f1(int a, Object b) { return a; @@ -357,7 +350,6 @@ return a; } - @ExpectError("The contained specialization 'f0' is not fully compatible.%") @Specialization(contains = "f0") Object f1(int a, double b) { // implicit type return a; @@ -370,7 +362,7 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } @@ -392,8 +384,8 @@ return null; } - @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(guards = "g1", contains = "f0") + @ExpectError({"Specialization is not reachable. It is shadowed by f0()."}) + @Specialization(guards = "g1()", contains = "f0") Object f1() { return null; } @@ -405,13 +397,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(guards = "!g1", contains = "f0") + @Specialization(guards = "!g1()", contains = "f0") Object f1() { return null; } @@ -427,13 +418,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(guards = "g2", contains = "f0") + @Specialization(guards = "g2()", contains = "f0") Object f1() { return null; } @@ -441,7 +431,6 @@ abstract static class ContainsGuard5 extends ValueNode { - @Implies("g2") boolean g1() { return true; } @@ -450,12 +439,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @Specialization(guards = "g2", contains = "f0") + @Specialization(guards = "g2()", contains = "f0") Object f1() { return null; } @@ -463,7 +452,6 @@ abstract static class ContainsGuard6 extends ValueNode { - @Implies("!g2") boolean g1() { return true; } @@ -472,12 +460,12 @@ return true; } - @Specialization(guards = "g1") + @Specialization(guards = "g1()") Object f0() { return null; } - @Specialization(guards = "!g2", contains = "f0") + @Specialization(guards = "!g2()", contains = "f0") Object f1() { return null; } @@ -493,84 +481,12 @@ return true; } - @Specialization(guards = {"g1", "g2"}) - Object f0() { - return null; - } - - @Specialization(guards = "g2", contains = "f0") - Object f1() { - return null; - } - } - - @NodeAssumptions("a1") - abstract static class ContainsAssumption1 extends ValueNode { - - @Specialization(assumptions = "a1") - Object f0() { - return null; - } - - @Specialization(contains = "f0") - Object f1() { - return null; - } - } - - @NodeAssumptions("a1") - abstract static class ContainsAssumption2 extends ValueNode { - - @Specialization + @Specialization(guards = {"g1()", "g2()"}) Object f0() { return null; } - @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(contains = "f0", assumptions = "a1") - Object f1() { - return null; - } - } - - @NodeAssumptions({"a1", "a2"}) - abstract static class ContainsAssumption3 extends ValueNode { - - @Specialization(assumptions = "a1") - Object f0() { - return null; - } - - @ExpectError({"The contained specialization 'f0' is not fully compatible.%"}) - @Specialization(contains = "f0", assumptions = "a2") - Object f1() { - return null; - } - } - - @NodeAssumptions({"a1", "a2"}) - abstract static class ContainsAssumption4 extends ValueNode { - - @Specialization(assumptions = {"a1", "a2"}) - Object f0() { - return null; - } - - @Specialization(contains = "f0", assumptions = "a1") - Object f1() { - return null; - } - } - - @NodeAssumptions({"a1", "a2"}) - abstract static class ContainsAssumption5 extends ValueNode { - - @Specialization(assumptions = {"a2", "a1"}) - Object f0() { - return null; - } - - @Specialization(contains = "f0", assumptions = "a1") + @Specialization(guards = "g2()", contains = "f0") Object f1() { return null; } @@ -619,20 +535,12 @@ @NodeChild("a") static class PolymorphicToMonomorphic0 extends ValueNode { - boolean isOne(int a) { - return a == 1; - } - - boolean isTwo(int a) { - return a == 2; - } - - @Specialization(guards = "isOne") + @Specialization(guards = "a == 1") int do1(int a) { return a; } - @Specialization(guards = "isTwo") + @Specialization(guards = "a == 2") int do2(int a) { return a; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -35,7 +35,8 @@ import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs3Factory; import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs4Factory; import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs5Factory; -import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluatedNodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluated1NodeFactory; +import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluated2NodeFactory; import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode; @@ -79,12 +80,12 @@ } @Test - public void testDoubleEvaluated() { + public void testDoubleEvaluated1() { ArgumentNode arg0 = new ArgumentNode(0); ArgumentNode arg1 = new ArgumentNode(1); - CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluatedNodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null))); + CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluated1NodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null))); - Assert.assertEquals(85, callTarget.call(new Object[]{42, 43})); + Assert.assertEquals(42, callTarget.call(new Object[]{43, 1})); Assert.assertEquals(1, arg0.getInvocationCount()); Assert.assertEquals(1, arg1.getInvocationCount()); } @@ -94,7 +95,7 @@ @Specialization int doExecuteWith(int exp0, int exp1) { - return exp0 + exp1; + return exp0 - exp1; } public abstract Object executeEvaluated(VirtualFrame frame, Object exp0, Object exp1); @@ -103,11 +104,32 @@ } @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp0", "exp1"})}) - abstract static class UseDoubleEvaluatedNode extends ValueNode { + abstract static class UseDoubleEvaluated1Node extends ValueNode { @Specialization int call(int exp0, int exp1, int exp2) { - Assert.assertEquals(exp0 + exp1, exp2); + Assert.assertEquals(exp0 - exp1, exp2); + return exp2; + } + } + + @Test + public void testDoubleEvaluated2() { + ArgumentNode arg0 = new ArgumentNode(0); + ArgumentNode arg1 = new ArgumentNode(1); + CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluated2NodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null))); + + Assert.assertEquals(42, callTarget.call(new Object[]{1, 43})); + Assert.assertEquals(1, arg0.getInvocationCount()); + Assert.assertEquals(1, arg1.getInvocationCount()); + } + + @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp1", "exp0"})}) + abstract static class UseDoubleEvaluated2Node extends ValueNode { + + @Specialization + int call(int exp0, int exp1, int exp2) { + Assert.assertEquals(exp1 - exp0, exp2); return exp2; } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -319,7 +319,6 @@ @TypeSystemReference(ExecuteMethodTypes.class) @NodeChild(value = "a", type = ChildNoFrame.class) - @ExpectError("Invalid inconsistent frame types [MaterializedFrame, void] found for the declared execute methods.%") abstract static class ExecuteWithFrameError5 extends Node { abstract Object execute(); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -104,7 +104,7 @@ return "(int)"; } - @Specialization(guards = "notInt") + @Specialization(guards = "notInt(a)") String f2(Object a) { return "(object)"; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,40 +32,40 @@ public class ImportGuardsTest { - @ImportGuards(Imports0.class) + @ImportStatic(Imports0.class) @NodeChild("a") static class ImportGuards0 extends ValueNode { - @Specialization(guards = "staticGuard") + @Specialization(guards = "staticGuard(a)") int f0(int a) { return a; } } @NodeChild("a") - @ImportGuards(Imports0.class) + @ImportStatic(Imports0.class) static class ImportGuards1 extends ValueNode { - @ExpectError("No compatible guard with method name 'nonStaticGuard' found.") - @Specialization(guards = "nonStaticGuard") + @ExpectError("Error parsing expression 'nonStaticGuard(a)': The method nonStaticGuard is undefined for the enclosing scope.") + @Specialization(guards = "nonStaticGuard(a)") int f1(int a) { return a; } - @ExpectError("No compatible guard with method name 'protectedGuard' found.") - @Specialization(guards = "protectedGuard") + @ExpectError("Error parsing expression 'protectedGuard(a)': The method protectedGuard is undefined for the enclosing scope.") + @Specialization(guards = "protectedGuard(a)") int f2(int a) { return a; } - @ExpectError("No compatible guard with method name 'packageGuard' found.") - @Specialization(guards = "packageGuard") + @ExpectError("Error parsing expression 'packageGuard(a)': The method packageGuard is undefined for the enclosing scope.") + @Specialization(guards = "packageGuard(a)") int f3(int a) { return a; } - @ExpectError("No compatible guard with method name 'privateGuard' found.") - @Specialization(guards = "privateGuard") + @ExpectError("Error parsing expression 'privateGuard(a)': The method privateGuard is undefined for the enclosing scope.") + @Specialization(guards = "privateGuard(a)") int f4(int a) { return a; } @@ -97,7 +97,7 @@ @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports1' must be public.") @NodeChild("a") - @ImportGuards(Imports1.class) + @ImportStatic(Imports1.class) static class ImportGuards2 extends ValueNode { int do1(int a) { @@ -111,7 +111,7 @@ @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports2' must be public.") @NodeChild("a") - @ImportGuards(Imports2.class) + @ImportStatic(Imports2.class) static class ImportGuards3 extends ValueNode { int do1(int a) { @@ -121,7 +121,7 @@ @ExpectError("The specified import guard class 'boolean' is not a declared type.") @NodeChild("a") - @ImportGuards(boolean.class) + @ImportStatic(boolean.class) static class ImportGuards4 extends ValueNode { int do1(int a) { @@ -135,7 +135,7 @@ @ExpectError("At least import guard classes must be specified.") @NodeChild("a") - @ImportGuards({}) + @ImportStatic({}) static class ImportGuards5 extends ValueNode { int do1(int a) { @@ -151,7 +151,7 @@ array(1, 1)); } - @ImportGuards(Imports0.class) + @ImportStatic(Imports0.class) @NodeChild("a") static class ImportGuards6 extends ValueNode { @@ -159,7 +159,7 @@ return a == 1; } - @Specialization(guards = "staticGuard") + @Specialization(guards = "staticGuard(a)") int f0(int a) { return a; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,20 +30,12 @@ @NodeChild("a") static class InsertBefore1Base extends ValueNode { - boolean g1(int a) { - return a == 1; - } - - boolean g2(int a) { - return a == 2; - } - - @Specialization(guards = "g1") + @Specialization(guards = "a == 1") int f1(int a) { return a; } - @Specialization(guards = "g2") + @Specialization(guards = "a == 2") int f3(int a) { return a; } @@ -63,11 +55,7 @@ @NodeChild("a") static class InsertBefore1T2 extends InsertBefore1Base { - boolean g0(int a) { - return a == 0; - } - - @Specialization(guards = "g0", insertBefore = "f1") + @Specialization(guards = "a == 0", insertBefore = "f1") int f0(int a) { return a; } @@ -77,11 +65,7 @@ @NodeChild("a") static class InsertBefore1T3 extends InsertBefore1Base { - boolean g0(int a) { - return a == 0; - } - - @Specialization(guards = "g0", insertBefore = "f3") + @Specialization(guards = "a == 0", insertBefore = "f3") int f0(int a) { return a; } @@ -93,10 +77,6 @@ "Method f1(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."}) static class InsertBefore1T4 extends InsertBefore1Base { - boolean g0(int a) { - return a == 0; - } - @Specialization(insertBefore = "f1") int f0(int a) { return a; @@ -126,7 +106,7 @@ return a == 0; } - @Specialization(insertBefore = "f1", guards = "g0") + @Specialization(insertBefore = "f1", guards = "a == 0") int f0(int a) { return a; } @@ -136,11 +116,7 @@ @NodeChild("a") static class InsertBefore1T6part2 extends InsertBefore1T6part1 { - boolean g(int a) { - return a == 0; - } - - @Specialization(insertBefore = "f0", guards = "g") + @Specialization(insertBefore = "f0", guards = "a == 3") int f(int a) { return a; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LimitTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LimitTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,171 @@ +/* + * 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.truffle.api.dsl.test; + +import static com.oracle.truffle.api.dsl.test.TestHelper.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.LimitTestFactory.ConstantLimitTestFactory; +import com.oracle.truffle.api.dsl.test.LimitTestFactory.DefaultLimit3TestFactory; +import com.oracle.truffle.api.dsl.test.LimitTestFactory.LocalLimitTestFactory; +import com.oracle.truffle.api.dsl.test.LimitTestFactory.MethodLimitTestFactory; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +@SuppressWarnings("unused") +public class LimitTest { + + @Test + public void testDefaultLimit3() { + CallTarget root = createCallTarget(DefaultLimit3TestFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + assertEquals(44, root.call(44)); + try { + root.call(45); + fail(); + } catch (UnsupportedSpecializationException e) { + } + } + + @NodeChild + static class DefaultLimit3Test extends ValueNode { + @Specialization(guards = "value == cachedValue") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + } + + @Test + public void testConstantLimit() { + CallTarget root = createCallTarget(ConstantLimitTestFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + try { + root.call(44); + fail(); + } catch (UnsupportedSpecializationException e) { + } + } + + @NodeChild + static class ConstantLimitTest extends ValueNode { + + public static final int LIMIT = 2; + + @Specialization(limit = "LIMIT", guards = "value == cachedValue") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + } + + @Test + public void testLocalLimit() { + CallTarget root = createCallTarget(LocalLimitTestFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + try { + root.call(44); + fail(); + } catch (UnsupportedSpecializationException e) { + } + } + + @NodeChild + static class LocalLimitTest extends ValueNode { + + protected int localLimit = 2; + + @Specialization(limit = "localLimit", guards = "value == cachedValue") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + } + + @Test + public void testMethodLimit() { + MethodLimitTest.invocations = 0; + CallTarget root = createCallTarget(MethodLimitTestFactory.getInstance()); + assertEquals(42, root.call(42)); + assertEquals(43, root.call(43)); + try { + root.call(44); + fail(); + } catch (UnsupportedSpecializationException e) { + } + assertEquals(3, MethodLimitTest.invocations); + } + + @NodeChild + static class MethodLimitTest extends ValueNode { + + static int invocations = 0; + + @Specialization(limit = "calculateLimitFor(cachedValue, invocations)", guards = "value == cachedValue") + static int do1(int value, @Cached("value") int cachedValue) { + return cachedValue; + } + + int calculateLimitFor(int cachedValue, int boundField) { + invocations = boundField + 1; + return 2; + } + + } + + @NodeChild + static class LimitErrorTest1 extends ValueNode { + @ExpectError("The limit expression has no effect.%") + @Specialization(limit = "4") + static int do1(int value) { + return value; + } + } + + @NodeChild + static class LimitErrorTest2 extends ValueNode { + public static final Object CONSTANT = new Object(); + + @ExpectError("Incompatible return type Object. Limit expressions must return int.") + @Specialization(limit = "CONSTANT", guards = "value == cachedValue") + static int do1(int value, @Cached("value") int cachedValue) { + return value; + } + } + + @NodeChild + static class LimitErrorTest3 extends ValueNode { + + public static final Object CONSTANT = new Object(); + + @ExpectError("Limit expressions must not bind dynamic parameter values.") + @Specialization(limit = "value", guards = "value == cachedValue") + static int do1(int value, @Cached("value") int cachedValue) { + return value; + } + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -27,296 +27,473 @@ import org.junit.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.Guard1Factory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.Guard2Factory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBaseClassFactory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBoxedPrimitiveFactory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithObjectFactory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestAbstractGuard1Factory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve1Factory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve2Factory; -import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve3Factory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.Interface; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.dsl.test.LimitTestFactory.ConstantLimitTestFactory; +import com.oracle.truffle.api.dsl.test.LimitTestFactory.LocalLimitTestFactory; +import com.oracle.truffle.api.dsl.test.LimitTestFactory.MethodLimitTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardCompareWithFieldTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardComplexTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardFieldTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardGreaterEqualTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardGreaterTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardLessEqualTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardLessTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMethodTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMultipleAndMethodTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMultipleOrMethodTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardNotTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardOrTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardStaticFieldTestFactory; +import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardUnboundMethodTestFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; @SuppressWarnings("unused") public class MethodGuardsTest { - private static final Object NULL = new Object(); + @Test + public void testGuardEqual() { + CallTarget root = createCallTarget(GuardEqualTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do2", root.call(2)); + assertEquals("do1", root.call(1)); + } + + @NodeChild + static class GuardEqualTest extends ValueNode { + @Specialization(guards = "value == 1") + static String do1(int value) { + return "do1"; + } + + @Specialization + static String do2(int value) { + return "do2"; + } + } @Test - public void testInvocations() { - TestRootNode root = createRoot(Guard1Factory.getInstance()); - - assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1)); - assertEquals(1, Guard1.specializedInvocations); - assertEquals(0, Guard1.genericInvocations); - - assertEquals(42, executeWith(root, Integer.MAX_VALUE)); - assertEquals(1, Guard1.specializedInvocations); - assertEquals(1, Guard1.genericInvocations); + public void testGuardLessEqual() { + CallTarget root = createCallTarget(GuardLessEqualTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do1", root.call(0)); + assertEquals("do2", root.call(2)); + assertEquals("do1", root.call(0)); } @NodeChild - static class Guard1 extends ValueNode { - - static int specializedInvocations = 0; - static int genericInvocations = 0; - - boolean g(int value0) { - return value0 != Integer.MAX_VALUE; + static class GuardLessEqualTest extends ValueNode { + @Specialization(guards = "value <= 1") + static String do1(int value) { + return "do1"; } - @Specialization(guards = "g") - int f1(int value0) { - specializedInvocations++; - return value0 + 1; + @Specialization + static String do2(int value) { + return "do2"; + } + } + + @Test + public void testGuardLess() { + CallTarget root = createCallTarget(GuardLessTestFactory.getInstance()); + assertEquals("do1", root.call(0)); + assertEquals("do2", root.call(1)); + assertEquals("do2", root.call(2)); + assertEquals("do1", root.call(-1)); + } + + @NodeChild + static class GuardLessTest extends ValueNode { + @Specialization(guards = "value < 1") + static String do1(int value) { + return "do1"; } - @Fallback - int f2(Object value0) { - genericInvocations++; - return 42; + @Specialization + static String do2(int value) { + return "do2"; + } + } + + @Test + public void testGuardGreaterEqual() { + CallTarget root = createCallTarget(GuardGreaterEqualTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do2", root.call(0)); + assertEquals("do1", root.call(2)); + assertEquals("do2", root.call(0)); + } + + @NodeChild + static class GuardGreaterEqualTest extends ValueNode { + @Specialization(guards = "value >= 1") + static String do1(int value) { + return "do1"; + } + + @Specialization + static String do2(int value) { + return "do2"; } } @Test - public void testGuardSideEffect() { - TestRootNode root = createRoot(Guard2Factory.getInstance()); - - assertEquals(42, executeWith(root, NULL)); - - Guard2.globalFlag = true; - assertEquals(41, executeWith(root, NULL)); - - Guard2.globalFlag = false; - assertEquals(42, executeWith(root, NULL)); + public void testGuardGreater() { + CallTarget root = createCallTarget(GuardGreaterTestFactory.getInstance()); + assertEquals("do1", root.call(2)); + assertEquals("do2", root.call(0)); + assertEquals("do2", root.call(1)); + assertEquals("do2", root.call(0)); } @NodeChild - static class Guard2 extends ValueNode { - - static boolean globalFlag = false; - - static boolean globalFlagGuard() { - return globalFlag; + static class GuardGreaterTest extends ValueNode { + @Specialization(guards = "value > 1") + static String do1(int value) { + return "do1"; } - @Specialization(guards = "globalFlagGuard") - int f1(Object value0) { - return 41; + @Specialization + static String do2(int value) { + return "do2"; + } + } + + @Test + public void testGuardOr() { + CallTarget root = createCallTarget(GuardOrTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do1", root.call(0)); + assertEquals("do2", root.call(2)); + assertEquals("do2", root.call(-1)); + } + + @NodeChild + static class GuardOrTest extends ValueNode { + @Specialization(guards = "value == 1 || value == 0") + static String do1(int value) { + return "do1"; } - @Fallback - int f2(Object value0) { - return 42; // the generic answer to all questions + @Specialization + static String do2(int value) { + return "do2"; } } @Test - public void testGuardWithBaseClass() { - TestRootNode root = createRoot(GuardWithBaseClassFactory.getInstance()); - - assertEquals(42, executeWith(root, new BExtendsAbstract())); + public void testGuardNot() { + CallTarget root = createCallTarget(GuardNotTestFactory.getInstance()); + assertEquals("do1", root.call(0)); + assertEquals("do1", root.call(2)); + assertEquals("do2", root.call(1)); + assertEquals("do1", root.call(0)); } - @NodeChild("expression") - public abstract static class GuardWithBaseClass extends ValueNode { - - boolean baseGuard(Abstract base) { - return true; + @NodeChild + static class GuardNotTest extends ValueNode { + @Specialization(guards = "!(value == 1)") + static String do1(int value) { + return "do1"; } - @Specialization(guards = "baseGuard") - int doSpecialized(BExtendsAbstract value0) { - return 42; - } - } - - @NodeChild("expression") - public abstract static class GuardWithBaseInterface extends ValueNode { - - boolean baseGuard(CharSequence base) { - return true; - } - - @Specialization(guards = "baseGuard") - @ExpectError("No guard with name 'baseGuard' matched the required signature.%") - int doSpecialized(String value0) { - return 42; + @Specialization + static String do2(int value) { + return "do2"; } } @Test - public void testGuardWithPrimitive() { - TestRootNode root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance()); + public void testGuardField() { + CallTarget root = createCallTarget(GuardFieldTestFactory.getInstance()); + GuardFieldTest node = getNode(root); + node.field = true; + assertEquals("do1", root.call(0)); + assertEquals("do1", root.call(2)); - assertEquals(42, executeWith(root, 42)); + node.field = false; + try { + root.call(2); + fail("expected Assertion failed"); + } catch (AssertionError e) { + } } - @NodeChild("expression") - public abstract static class GuardWithBoxedPrimitive extends ValueNode { + @NodeChild + static class GuardFieldTest extends ValueNode { - boolean baseGuard(Integer primitive) { - return true; + boolean field; + + @Specialization(guards = "field") + static String do1(int value) { + return "do1"; } - @Specialization(guards = "baseGuard") - int doSpecialized(int value0) { - return value0; + @Specialization + static String do2(int value) { + return "do2"; + } + } + + @Test + public void testGuardCompareWithField() { + CallTarget root = createCallTarget(GuardCompareWithFieldTestFactory.getInstance()); + GuardCompareWithFieldTest node = getNode(root); + node.field = 1; + assertEquals("do1", root.call(1)); + assertEquals("do2", root.call(2)); + + node.field = 2; + assertEquals("do2", root.call(1)); + assertEquals("do1", root.call(2)); + } + + @NodeChild + static class GuardCompareWithFieldTest extends ValueNode { + + int field; + + @Specialization(guards = "value == field") + static String do1(int value) { + return "do1"; + } + + @Specialization + static String do2(int value) { + return "do2"; } } @Test - public void testGuardWithObject() { - TestRootNode root = createRoot(GuardWithObjectFactory.getInstance()); - - assertEquals(42, executeWith(root, 42)); + public void testGuardStaticField() { + CallTarget root = createCallTarget(GuardStaticFieldTestFactory.getInstance()); + GuardStaticFieldTest.field = true; + assertEquals("do1", root.call(1)); + assertEquals("do1", root.call(2)); + GuardStaticFieldTest.field = false; + try { + root.call(2); + fail("expected Assertion failed"); + } catch (AssertionError e) { + } } - @NodeChild("expression") - public abstract static class GuardWithObject extends ValueNode { + @NodeChild + static class GuardStaticFieldTest extends ValueNode { - boolean baseGuard(Object primitive) { - return true; + static boolean field; + + @Specialization(guards = "field") + static String do1(int value) { + return "do1"; } - @Specialization(guards = "baseGuard") - int doSpecialized(int value0) { - return value0; + @Specialization + static String do2(int value) { + return "do2"; } } @Test - public void testGuardResolve1() { - TestRootNode root = createRoot(TestGuardResolve1Factory.getInstance()); - - assertEquals(42, executeWith(root, 42)); + public void testGuardMethod() { + CallTarget root = createCallTarget(GuardMethodTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do2", root.call(2)); + assertEquals("do1", root.call(1)); + assertEquals("do2", root.call(0)); } - @NodeChild("expression") - public abstract static class TestGuardResolve1 extends ValueNode { + @NodeChild + static class GuardMethodTest extends ValueNode { - boolean guard(Object primitive) { - return false; + @Specialization(guards = "method(value)") + static String do1(int value) { + return "do1"; } - boolean guard(int primitive) { - return true; + @Specialization + static String do2(int value) { + return "do2"; } - @Specialization(guards = "guard") - int doSpecialized(int value0) { - return value0; + boolean method(int value) { + return value == 1; } } @Test - public void testGuardResolve2() { - TestRootNode root = createRoot(TestGuardResolve2Factory.getInstance()); - assertEquals(42, executeWith(root, new BExtendsAbstract())); + public void testGuardUnboundMethodField() { + CallTarget root = createCallTarget(GuardUnboundMethodTestFactory.getInstance()); + GuardUnboundMethodTest node = getNode(root); + node.hiddenValue = true; + assertEquals("do1", root.call(1)); + assertEquals("do1", root.call(2)); + node.hiddenValue = false; + try { + root.call(2); + fail("expected Assertion failed"); + } catch (AssertionError e) { + } } - @NodeChild("expression") - public abstract static class TestGuardResolve2 extends ValueNode { + @NodeChild + static class GuardUnboundMethodTest extends ValueNode { - boolean guard(Object primitive) { - return false; + private boolean hiddenValue; + + @Specialization(guards = "method()") + static String do1(int value) { + return "do1"; } - boolean guard(Abstract primitive) { - return true; + boolean method() { + return hiddenValue; + } + } + + @Test + public void testStaticGuardMethod() { + CallTarget root = createCallTarget(GuardMethodTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do2", root.call(2)); + assertEquals("do1", root.call(1)); + assertEquals("do2", root.call(0)); + } + + @NodeChild + static class StaticGuardMethodTest extends ValueNode { + + @Specialization(guards = "method(value)") + static String do1(int value) { + return "do1"; } - @Specialization(guards = "guard") - int doSpecialized(BExtendsAbstract value0) { - return 42; + @Specialization + static String do2(int value) { + return "do2"; + } + + static boolean method(int value) { + return value == 1; } } @Test - public void testGuardResolve3() { - TestRootNode root = createRoot(TestGuardResolve3Factory.getInstance()); - - assertEquals(42, executeWith(root, new BExtendsAbstract())); + public void testMultipleGuardAndMethod() { + CallTarget root = createCallTarget(GuardMultipleAndMethodTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do1", root.call(2)); + assertEquals("do2", root.call(3)); + assertEquals("do2", root.call(0)); } - @NodeChild("expression") - public abstract static class TestGuardResolve3 extends ValueNode { - - boolean guard(Object primitive) { - return false; - } + @NodeChild + static class GuardMultipleAndMethodTest extends ValueNode { - boolean guard(Abstract primitive) { - return false; - } - - boolean guard(BExtendsAbstract primitive) { - return true; + @Specialization(guards = {"method1(value)", "method2(value)"}) + static String do1(int value) { + return "do1"; } - @Specialization(guards = "guard") - int doSpecialized(BExtendsAbstract value0) { - return 42; - } - } - - @NodeChild("expression") - public abstract static class TestGuardResolve4 extends ValueNode { - - boolean guard(Abstract primitive) { - return false; + @Specialization + static String do2(int value) { + return "do2"; } - @Specialization(guards = "guard") - int doSpecialized(BExtendsAbstract value0) { - return 42; - } - } - - @NodeChildren({@NodeChild("a"), @NodeChild("b")}) - abstract static class TestGuardResolve5 extends ValueNode { - - @Specialization(guards = "guard") - int add(Interface left, Interface right) { - return 42; + boolean method1(int value) { + return value >= 1; } - boolean guard(Interface left, Object right) { - return true; + boolean method2(int value) { + return value <= 2; } } @Test - public void testAbstractGuard1() { - TestRootNode root = createRoot(TestAbstractGuard1Factory.getInstance()); - - assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE)); - assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE)); + public void testMultipleGuardOrMethod() { + CallTarget root = createCallTarget(GuardMultipleOrMethodTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do1", root.call(2)); + assertEquals("do2", root.call(3)); + assertEquals("do2", root.call(0)); } - @NodeChild("expression") - public abstract static class TestAbstractGuard1 extends ValueNode { + @NodeChild + static class GuardMultipleOrMethodTest extends ValueNode { - boolean guard(Abstract value0) { - return true; + @Specialization(guards = {"method1(value) || method2(value)"}) + static String do1(int value) { + return "do1"; } - @Specialization(guards = "guard") - BExtendsAbstract do1(BExtendsAbstract value0) { - return value0; + @Specialization + static String do2(int value) { + return "do2"; } - @Specialization(guards = "guard") - CExtendsAbstract do2(CExtendsAbstract value0) { - return value0; + boolean method1(int value) { + return value == 1; + } + + boolean method2(int value) { + return value == 2; } } + @Test + public void testComplexGuard() { + CallTarget root = createCallTarget(GuardComplexTestFactory.getInstance()); + assertEquals("do1", root.call(1)); + assertEquals("do1", root.call(2)); + assertEquals("do2", root.call(3)); + assertEquals("do1", root.call(0)); + } + + @NodeChild + static class GuardComplexTest extends ValueNode { + + int field1 = 1; + static int field2 = 2; + + @Specialization(guards = {"method2(method1(field1 == 1), value <= 2)", "field2 == 2"}) + static String do1(int value) { + return "do1"; + } + + @Specialization + static String do2(int value) { + return "do2"; + } + + static boolean method1(boolean value) { + return value; + } + + boolean method2(boolean value1, boolean value2) { + return value1 && value2; + } + } + + @NodeChild + static class ErrorGuardNotTest extends ValueNode { + @ExpectError("Error parsing expression '!value == 1': The operator ! is undefined for the argument type int.") + @Specialization(guards = "!value == 1") + static String do1(int value) { + return "do1"; + } + } + + @NodeChild + static class ErrorIncompatibleReturnTypeTest extends ValueNode { + + @ExpectError("Incompatible return type int. Guards must return boolean.") + @Specialization(guards = "1") + static String do1(int value) { + return "do1"; + } + + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -69,7 +69,7 @@ return true; } - @Specialization(guards = "guard ()") + @Specialization(guards = "guard()") int do1() { return 42; } @@ -214,7 +214,7 @@ return true; } - @ExpectError("No compatible guard with method name 'guard(' found.%") + @ExpectError("Error parsing expression 'guard(': -- line 1 col 7: \")\" expected%") @Specialization(guards = "guard(") int do1() { return 42; @@ -227,7 +227,7 @@ return true; } - @ExpectError("No compatible guard with method name 'guard)' found.%") + @ExpectError("Error parsing expression 'guard)': -- line 1 col 6: EOF expected%") @Specialization(guards = "guard)") int do1() { return 42; @@ -241,7 +241,7 @@ return true; } - @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.") + @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.") @Specialization(guards = "guard(a)") int do1() { return 42; @@ -255,7 +255,7 @@ return true; } - @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.") + @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.") @Specialization(guards = "guard(a)") int do1(int b) { return b; diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -45,7 +45,7 @@ return true; } - @Specialization(guards = "!guard") + @Specialization(guards = "!guard()") int do1() { throw new AssertionError(); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -182,7 +182,7 @@ return false; } - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do2() { return 1; } @@ -206,7 +206,7 @@ } @ExpectError("Specialization is not reachable. It is shadowed by do2().") - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do1() { return 1; } @@ -219,7 +219,7 @@ return false; } - @Specialization(guards = "foo") + @Specialization(guards = "foo()") int do2() { return 1; } @@ -237,106 +237,13 @@ return false; } - @Specialization(guards = "foo") - int do2() { - return 1; - } - - @ExpectError("Specialization is not reachable. It is shadowed by do2().") - @Specialization(guards = "foo") - int do1() { - return 2; - } - - } - - @NodeAssumptions({"a1"}) - static class ReachabilityAssumption1 extends ValueNode { - - @Specialization(assumptions = "a1") - int do2() { - return 1; - } - - @Specialization - int do1() { - return 2; - } - - } - - @NodeAssumptions({"a1"}) - static class ReachabilityAssumption2 extends ValueNode { - - @Specialization(assumptions = "a1") + @Specialization(guards = "foo()") int do2() { return 1; } @ExpectError("Specialization is not reachable. It is shadowed by do2().") - @Specialization(assumptions = "a1") - int do1() { - return 2; - } - - } - - @NodeAssumptions({"a1", "a2"}) - static class ReachabilityAssumption3 extends ValueNode { - - @Specialization(assumptions = {"a1", "a2"}) - int do2() { - return 1; - } - - @Specialization(assumptions = "a1") - int do1() { - return 2; - } - - } - - @NodeAssumptions({"a1", "a2"}) - static class ReachabilityAssumption4 extends ValueNode { - - @Specialization(assumptions = "a1") - int do2() { - return 1; - } - - @Specialization(assumptions = "a2") - int do1() { - return 2; - } - - } - - @NodeAssumptions({"a1", "a2"}) - static class ReachabilityAssumption5 extends ValueNode { - - @Specialization - int do2() { - return 1; - } - - @ExpectError("Specialization is not reachable. It is shadowed by do2().") - @Specialization(assumptions = "a2") - int do1() { - return 2; - } - - } - - @NodeAssumptions({"a1", "a2"}) - static class ReachabilityAssumption6 extends ValueNode { - - @Specialization(assumptions = {"a1"}) - int do2() { - return 1; - } - - @ExpectError("Specialization is not reachable. It is shadowed by do2().") - @Specialization(assumptions = {"a1", "a2"}) + @Specialization(guards = "foo()") int do1() { return 2; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -119,7 +119,7 @@ return false; } - @Specialization(guards = "guard") + @Specialization(guards = "guard(a, hasB, b)") int doIt(int a, boolean hasB, int b) { return a + b; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -74,29 +74,17 @@ @NodeChild("a") static class SourceSection0 extends ValueNode { - boolean isOne(int a) { - return a == 1; - } - - boolean isTwo(int a) { - return a == 2; - } - - boolean isThree(int a) { - return a == 3; - } - - @Specialization(guards = "isOne") + @Specialization(guards = "a == 1") int do1(int a) { return a; } - @Specialization(guards = "isTwo") + @Specialization(guards = "a == 2") int do2(int a) { return a; } - @Specialization(guards = "isThree") + @Specialization(guards = "a == 3") int do3(int a) { return a; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -212,7 +212,7 @@ return a == 1; } - @Specialization(guards = "guard0") + @Specialization(guards = "guard0(a)") int do2(int a) { return a; } @@ -309,7 +309,7 @@ static int fallthrough1; - @Specialization(guards = "isDo1", rewriteOn = ArithmeticException.class) + @Specialization(guards = "isDo1(a)", rewriteOn = ArithmeticException.class) int do1(int a) throws ArithmeticException { if (a == 0) { fallthrough1++; @@ -322,7 +322,7 @@ return a == 0 || a == 1; } - @Specialization(guards = "isDo1") + @Specialization(guards = "isDo1(a)") int do2(int a) { return a; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -28,9 +28,6 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug1Factory; import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug2Factory; -import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestGroupingFactory; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.SimpleTypes; -import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -43,119 +40,6 @@ public class SpecializationGroupingTest { @Test - public void testGrouping() { - MockAssumption a1 = new MockAssumption(true); - MockAssumption a3 = new MockAssumption(true); - - TestRootNode root = TestHelper.createRoot(TestGroupingFactory.getInstance(), a1, a3); - - SimpleTypes.intCast = 0; - SimpleTypes.intCheck = 0; - TestGrouping.true1 = 0; - TestGrouping.false1 = 0; - TestGrouping.true2 = 0; - TestGrouping.false2 = 0; - TestGrouping.true3 = 0; - - Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21)); - Assert.assertEquals(4, TestGrouping.true1); - Assert.assertEquals(0, TestGrouping.false1); - Assert.assertEquals(4, TestGrouping.true2); - Assert.assertEquals(5, TestGrouping.false2); - Assert.assertEquals(5, TestGrouping.true3); - Assert.assertEquals(10, SimpleTypes.intCheck); - Assert.assertEquals(8, SimpleTypes.intCast); - Assert.assertEquals(4, a1.checked); - Assert.assertEquals(4, a3.checked); - - Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21)); - Assert.assertEquals(5, TestGrouping.true1); - Assert.assertEquals(0, TestGrouping.false1); - Assert.assertEquals(5, TestGrouping.true2); - Assert.assertEquals(6, TestGrouping.false2); - Assert.assertEquals(6, TestGrouping.true3); - - Assert.assertEquals(5, a1.checked); - Assert.assertEquals(5, a3.checked); - Assert.assertEquals(10, SimpleTypes.intCheck); - Assert.assertEquals(8, SimpleTypes.intCast); - - } - - @SuppressWarnings("unused") - @NodeChildren({@NodeChild, @NodeChild}) - @NodeAssumptions({"a1", "a3"}) - public abstract static class TestGrouping extends ValueNode { - - private static int true1; - private static int false1; - private static int true2; - private static int false2; - private static int true3; - - protected boolean true1(int value) { - true1++; - return true; - } - - protected boolean false1(int value, int value2) { - false1++; - return false; - } - - protected boolean true2(int value) { - true2++; - return true; - } - - protected boolean false2(int value) { - false2++; - return false; - } - - protected boolean true3(int value) { - true3++; - return true; - } - - @Specialization - public int fail(int value1, String value2) { - throw new AssertionError(); - } - - @Specialization(guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class) - public int throwRewrite(int value1, int value2) { - throw new RuntimeException(); - } - - @Specialization(guards = {"true1", "true2", "!false2", "true3"}, contains = "throwRewrite", assumptions = {"a1", "a3"}) - public int success(int value1, int value2) { - return value1 + value2; - } - - @Specialization(guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"}) - public int fail5(int value1, int value2) { - throw new AssertionError(); - } - - @Specialization(guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"}) - public int fail4(int value1, int value2) { - throw new AssertionError(); - } - - @Specialization(guards = {"true1", "true2"}, assumptions = {"a1", "a3"}) - public int fail2break(int value1, int value2) { - throw new AssertionError(); - } - - @Specialization(guards = {"true1", "false1"}) - public int fail1(int value1, int value2) { - throw new AssertionError(); - } - - } - - @Test public void testElseConnectionBug1() { CallTarget target = TestHelper.createCallTarget(TestElseConnectionBug1Factory.create(new GenericInt())); Assert.assertEquals(42, target.call()); @@ -165,17 +49,17 @@ @NodeChild(value = "genericChild", type = GenericInt.class) public abstract static class TestElseConnectionBug1 extends ValueNode { - @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized") + @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized(value)") public int do1(int value) throws SlowPathException { throw new SlowPathException(); } - @Specialization(contains = "do1", guards = "isInitialized") + @Specialization(contains = "do1", guards = "isInitialized(value)") public int do2(int value) { return value == 42 ? value : 0; } - @Specialization(guards = "!isInitialized") + @Specialization(guards = "!isInitialized(value)") public Object do3(int value) { throw new AssertionError(); } @@ -208,17 +92,17 @@ @NodeChild public abstract static class TestElseConnectionBug2 extends ValueNode { - @Specialization(guards = "guard0") + @Specialization(guards = "guard0(value)") public int do1(int value) { throw new AssertionError(); } - @Specialization(guards = "guard1") + @Specialization(guards = "guard1(value)") public int do2(int value) { throw new AssertionError(); } - @Specialization(guards = "!guard0") + @Specialization(guards = "!guard0(value)") public int do3(int value) { return value; } @@ -232,36 +116,4 @@ } } - private static class MockAssumption implements Assumption { - - int checked; - - private final boolean valid; - - public MockAssumption(boolean valid) { - this.valid = valid; - } - - public void check() throws InvalidAssumptionException { - checked++; - if (!valid) { - throw new InvalidAssumptionException(); - } - } - - public boolean isValid() { - checked++; - return valid; - } - - public void invalidate() { - throw new UnsupportedOperationException(); - } - - public String getName() { - throw new UnsupportedOperationException(); - } - - } - } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Sat Feb 21 19:55:33 2015 +0100 @@ -84,6 +84,22 @@ return Truffle.getRuntime().createCallTarget(node); } + static RootCallTarget createCallTarget(NodeFactory factory, Object... constants) { + return Truffle.getRuntime().createCallTarget(createRoot(factory, constants)); + } + + static boolean assertionsEnabled() { + boolean assertOn = false; + // *assigns* true if assertions are on. + assert (assertOn = true) == true; + return assertOn; + } + + @SuppressWarnings("unchecked") + static T getNode(CallTarget target) { + return ((TestRootNode) ((RootCallTarget) target).getRootNode()).getNode(); + } + static Object executeWith(TestRootNode node, Object... values) { return createCallTarget(node).call(values); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,123 @@ +/* + * 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.truffle.api.dsl.test.examples; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.internal.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +@TypeSystemReference(ExampleTypes.class) +@NodeChild(value = "args", type = ExampleNode[].class) +public abstract class ExampleNode extends Node { + + public Object execute(@SuppressWarnings("unused") VirtualFrame frame) { + // will get implemented by the DSL. + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + if (this instanceof SpecializedNode) { + return ((SpecializedNode) this).getSpecializationNode().toString(); + } else { + return super.toString(); + } + } + + public static CallTarget createTarget(ExampleNode node) { + return Truffle.getRuntime().createCallTarget(new ExampleRootNode(node)); + } + + @SuppressWarnings("unchecked") + public static T getNode(CallTarget target) { + return (T) ((ExampleRootNode) ((RootCallTarget) target).getRootNode()).child; + } + + public static ExampleNode[] createArguments(int count) { + ExampleNode[] nodes = new ExampleNode[count]; + for (int i = 0; i < count; i++) { + nodes[i] = new ExampleArgumentNode(i); + } + return nodes; + } + + private static class ExampleRootNode extends RootNode { + + @Child ExampleNode child; + + public ExampleRootNode(ExampleNode child) { + this.child = child; + } + + @Override + public Object execute(VirtualFrame frame) { + return child.execute(frame); + } + + } + + private static class ExampleArgumentNode extends ExampleNode { + + private final int index; + + public ExampleArgumentNode(int index) { + this.index = index; + } + + @Override + public Object execute(VirtualFrame frame) { + Object[] arguments = frame.getArguments(); + if (index < arguments.length) { + return arguments[index]; + } + return null; + } + } + + public static CallTarget createDummyTarget(int argumentIndex) { + return Truffle.getRuntime().createCallTarget(new DummyCallRootNode(argumentIndex)); + } + + private static class DummyCallRootNode extends RootNode { + + private final int argumentIndex; + + public DummyCallRootNode(int argumentIndex) { + this.argumentIndex = argumentIndex; + } + + @Override + public Object execute(VirtualFrame frame) { + return frame.getArguments()[argumentIndex]; + } + + @Override + public String toString() { + return "DummyRootNode[arg = " + argumentIndex + "]"; + } + + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleTypes.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,40 @@ +/* + * 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.truffle.api.dsl.test.examples; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.examples.FunctionCall.Function; +import com.oracle.truffle.api.dsl.test.examples.Interop.TruffleObject; +import com.oracle.truffle.api.dsl.test.examples.RubyCall.InternalMethod; +import com.oracle.truffle.api.dsl.test.examples.RubyCall.RubyObject; +import com.oracle.truffle.api.dsl.test.examples.StableDispatch.SLFunction; + +@TypeSystem({int.class, double.class, boolean.class, TruffleObject.class, SLFunction.class, RubyObject.class, Function.class, InternalMethod.class, int[].class, double[].class, Object[].class}) +public class ExampleTypes { + + @ImplicitCast + public static double castInt(int intValue) { + return intValue; + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/FunctionCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/FunctionCall.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,151 @@ +/* + * 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.truffle.api.dsl.test.examples; + +import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.examples.FunctionCallFactory.FunctionCallNodeGen; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * This example illustrates how {@link Cached} can be used to implement function calls that use + * local state for its guards. If there are always distinct Function objects with distinct + * CallTargets then we can use the directCallFunctionGuard specialization. If there are two Function + * instances cached with the same CallTarget then we use the directCall cache. We do this because + * the directCallFunctionGuard specialization can use a faster guard. + */ +@SuppressWarnings("unused") +public class FunctionCall { + + @Test + public void testFunctionCall() { + assertEquals(2, FunctionCallNode.CACHE_SIZE); + + CallTarget dummyTarget1 = createDummyTarget(0); + CallTarget dummyTarget2 = createDummyTarget(0); + CallTarget dummyTarget3 = createDummyTarget(0); + + Function dummyFunction1 = new Function(dummyTarget1); + Function dummyFunction2 = new Function(dummyTarget2); + Function dummyFunction3 = new Function(dummyTarget2); // same target as dummyFunction2 + Function dummyFunction4 = new Function(dummyTarget3); + + FunctionCallNode node = FunctionCallNodeGen.create(createArguments(2)); + CallTarget target = createTarget(node); + assertEquals(42, target.call(dummyFunction1, 42)); + assertEquals(43, target.call(dummyFunction2, 43)); + assertEquals(44, target.call(dummyFunction3, 44)); // transition to directCall + assertEquals(2, node.directCallFunctionGuard); + assertEquals(1, node.directCall); + + assertEquals(42, target.call(dummyFunction1, 42)); + assertEquals(43, target.call(dummyFunction2, 43)); + assertEquals(2, node.directCallFunctionGuard); + assertEquals(3, node.directCall); + + assertEquals(44, target.call(dummyFunction4, 44)); // transition to indirectCall + assertEquals(2, node.directCallFunctionGuard); + assertEquals(3, node.directCall); + assertEquals(1, node.indirectCall); + + assertEquals(42, target.call(dummyFunction1, 42)); + assertEquals(43, target.call(dummyFunction2, 43)); + assertEquals(44, target.call(dummyFunction3, 44)); + assertEquals(2, node.directCallFunctionGuard); + assertEquals(3, node.directCall); + assertEquals(4, node.indirectCall); + } + + public static class FunctionCallNode extends ExampleNode { + + public static final int CACHE_SIZE = 2; + + private Function[] cachedFunctions = new Function[CACHE_SIZE]; + + private int directCallFunctionGuard; + private int directCall; + private int indirectCall; + + @Specialization(limit = "CACHE_SIZE", guards = {"function == cachedFunction", "cacheFunctionTarget(cachedFunction)"}) + public Object directCallFunctionGuard(VirtualFrame frame, Function function, Object argument, // + @Cached("function") Function cachedFunction, // + @Cached("create(cachedFunction.getTarget())") DirectCallNode callNode) { + directCallFunctionGuard++; + return callNode.call(frame, new Object[]{argument}); + } + + protected final boolean cacheFunctionTarget(Function function) { + CompilerAsserts.neverPartOfCompilation(); + if (cachedFunctions != null) { + for (int i = 0; i < cachedFunctions.length; i++) { + Function cachedFunction = cachedFunctions[i]; + if (cachedFunction == null) { + cachedFunctions[i] = function; + return true; + } else if (cachedFunction == function) { + return true; + } else if (cachedFunction.getTarget() == function.getTarget()) { + cachedFunctions = null; + return false; + } + } + } + return false; + } + + @Specialization(limit = "CACHE_SIZE", contains = "directCallFunctionGuard", guards = {"function.getTarget() == cachedTarget"}) + protected Object directCall(VirtualFrame frame, Function function, Object argument, // + @Cached("function.getTarget()") CallTarget cachedTarget, // + @Cached("create(cachedTarget)") DirectCallNode callNode) { + directCall++; + return callNode.call(frame, new Object[]{argument}); + } + + @Specialization(contains = "directCall") + protected Object indirectCall(VirtualFrame frame, Function function, Object argument, // + @Cached("create()") IndirectCallNode callNode) { + indirectCall++; + return callNode.call(frame, function.getTarget(), new Object[]{argument}); + } + } + + public static class Function { + + private final CallTarget target; + + public Function(CallTarget target) { + this.target = target; + } + + public CallTarget getTarget() { + return target; + } + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/Interop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/Interop.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,109 @@ +/* + * 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.truffle.api.dsl.test.examples; + +import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.examples.InteropFactory.UseInteropNodeGen; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * This example aims to illustrate how the {@link Cached} annotation can be used to implement a + * cache for a simplified language interoperability pattern. + */ +public class Interop { + + @Test + public void testInterop() { + UseInterop node = UseInteropNodeGen.create(createArguments(2)); + CallTarget target = createTarget(node); + TruffleObject o1 = new TruffleObject(); + TruffleObject o2 = new TruffleObject(); + TruffleObject o3 = new TruffleObject(); + TruffleObject o4 = new TruffleObject(); + assertEquals(42, target.call(o1, 42)); + assertEquals(43, target.call(o2, 43)); + assertEquals(44, target.call(o3, 44)); + assertEquals(3, node.cached); + assertEquals(0, node.generic); + assertEquals(45, target.call(o4, 45)); // operation gets generic + assertEquals(42, target.call(o1, 42)); + assertEquals(43, target.call(o2, 43)); + assertEquals(44, target.call(o3, 44)); + assertEquals(3, node.cached); + assertEquals(4, node.generic); + } + + public static class UseInterop extends ExampleNode { + + int cached = 0; + int generic = 0; + + @Specialization(guards = "operation.accept(target)") + protected Object interopCached(VirtualFrame frame, TruffleObject target, Object value, // + @Cached("target.createOperation()") TruffleObjectOperation operation) { + cached++; + return operation.execute(frame, target, value); + } + + @Specialization(contains = "interopCached") + protected Object interopGeneric(VirtualFrame frame, TruffleObject target, Object value) { + generic++; + return target.createOperation().execute(frame, target, value); + } + } + + public abstract static class TruffleObjectOperation extends Node { + + public abstract boolean accept(TruffleObject object); + + public abstract Object execute(VirtualFrame frame, Object target, Object value); + + } + + public static class TruffleObject { + + @TruffleBoundary + public TruffleObjectOperation createOperation() { + return new TruffleObjectOperation() { + @Override + public Object execute(VirtualFrame frame, Object target, Object value) { + return value; + } + + @Override + public boolean accept(TruffleObject object) { + return TruffleObject.this == object; + } + }; + } + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/MathPow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/MathPow.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,144 @@ +/* + * 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.truffle.api.dsl.test.examples; + +import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.examples.MathPowFactory.MathPowNodeGen; +import com.oracle.truffle.api.nodes.*; + +/** + * This example shows possible specializations for a simplified math pow node. It demonstrates how + * multiple caches can coexist within in the same node. This example does not show the best possible + * specializations for math.pow. + * + * Note: int values are implicitly casted to double values. + */ +@SuppressWarnings("unused") +public class MathPow extends Node { + + @Test + public void testPow() { + MathPowNode node = MathPowNodeGen.create(createArguments(2)); + CallTarget target = createTarget(node); + + // start with doPowCached + assertEquals(1D, target.call(1D, 1)); + assertEquals(2D, target.call(2D, 1)); + assertEquals(3D, target.call(3D, 1)); + assertEquals(3, node.doPowCached); + assertEquals(0, node.doPowCachedExponent); + + // transition to doPowCachedExponent + assertEquals(4D, target.call(4D, 1)); + assertEquals(5D, target.call(5D, 1)); + assertEquals(6D, target.call(6D, 1)); + assertEquals(16D, target.call(4D, 2)); + assertEquals(125D, target.call(5D, 3)); + assertEquals(5, node.doPowCachedExponent); + assertEquals(0, node.doPowDoubleInt); + + // transition to doPowDoubleInt + assertEquals(4D * 4D * 4D * 4D, target.call(4D, 4)); + assertEquals(5D * 5D * 5D * 5D * 5D, target.call(5D, 5)); + assertEquals(5, node.doPowCachedExponent); + assertEquals(2, node.doPowDoubleInt); + + // transition to doPow + assertEquals(5D, target.call(5D, 1D)); + assertEquals(2D, target.call(2D, 1D)); + + assertEquals(3, node.doPowCached); + assertEquals(5, node.doPowCachedExponent); + assertEquals(2, node.doPowDoubleInt); + assertEquals(2, node.doPow); + } + + public static class MathPowNode extends ExampleNode { + + // test flags + int doPowCached; + int doPowCachedExponent; + int doPowDoubleInt; + int doPow; + + @Specialization(guards = {"base == cachedBase", "exponent == cachedExponent"}) + double doPowCached(double base, int exponent, // + @Cached("base") double cachedBase, // + @Cached("exponent") int cachedExponent, // + @Cached("cachePow(cachedBase, cachedExponent)") double cachedResult) { + doPowCached++; + return cachedResult; + } + + /* + * We could just use the doPow specialization instead. But this makes the number of doPow + * calls more difficult to assert. + */ + protected static double cachePow(double base, int exponent) { + return Math.pow(base, exponent); + } + + @Specialization(contains = "doPowCached", guards = {"exponent == cachedExponent", "cachedExponent <= 10"}) + @ExplodeLoop + double doPowCachedExponent(double base, int exponent, @Cached("exponent") int cachedExponent) { + doPowCachedExponent++; + double result = 1.0; + for (int i = 0; i < cachedExponent; i++) { + result *= base; + } + return result; + } + + @Specialization(contains = "doPowCachedExponent", guards = "exponent >= 0") + double doPowDoubleInt(double base, int exponent) { + doPowDoubleInt++; + // Uses binary decomposition to limit the number of + // multiplications; see the discussion in "Hacker's Delight" by Henry + // S. Warren, Jr., figure 11-6, page 213. + double b = base; + int e = exponent; + double result = 1; + while (e > 0) { + if ((e & 1) == 1) { + result *= b; + } + e >>= 1; + b *= b; + } + return result; + } + + @Specialization(contains = {"doPowCached", "doPowDoubleInt"}) + double doPow(double base, double exponent) { + doPow++; + return Math.pow(base, exponent); + } + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/RubyCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/RubyCall.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,302 @@ +/* + * 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.truffle.api.dsl.test.examples; + +import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*; +import static org.junit.Assert.*; + +import java.util.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.internal.*; +import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyDispatchNodeGen; +import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyHeadNodeGen; +import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyLookupNodeGen; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; + +/** + * This example illustrates a simplified version of a Ruby function call semantics (RubyHeadNode). + * The example usage shows how methods can be redefined in this implementation. + */ +@SuppressWarnings("unused") +public class RubyCall { + + @Test + public void testCall() { + RubyHeadNode node = RubyHeadNodeGen.create(createArguments(4)); + CallTarget nodeTarget = createTarget(node); + final Object firstArgument = "someArgument"; + + // dummyMethod is just going to return the some argument of the function + final Object testMethodName = "getSomeArgument"; + // implementation returns first argument + InternalMethod aClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(3)); + // implementation returns second argument + InternalMethod bClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(4)); + // implementation returns third argument + InternalMethod cClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(5)); + + // defines hierarchy C extends B extends A + RubyClass aClass = new RubyClass("A", null); + RubyClass bClass = new RubyClass("B", aClass); + RubyClass cClass = new RubyClass("C", bClass); + + RubyObject aInstance = new RubyObject(aClass); + RubyObject bInstance = new RubyObject(bClass); + RubyObject cInstance = new RubyObject(cClass); + + // undefined method call + assertEquals(RubyObject.NIL, nodeTarget.call(cInstance, testMethodName, null, new Object[]{firstArgument})); + + // method defined in a + aClass.addMethod(testMethodName, aClassTestMethod); + assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument})); + assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{firstArgument})); + assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{firstArgument})); + + // method redefined in b + bClass.addMethod(testMethodName, bClassTestMethod); + assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument})); + assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{null, firstArgument})); + assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{null, firstArgument})); + + // method redefined in c + cClass.addMethod(testMethodName, cClassTestMethod); + assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument})); + assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{null, firstArgument})); + assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{null, null, firstArgument})); + + } + + public static class RubyHeadNode extends ExampleNode { + + @Child private RubyLookupNode lookup = RubyLookupNodeGen.create(null); + @Child private RubyDispatchNode dispatch = RubyDispatchNodeGen.create(null); + + @Specialization + public Object doCall(VirtualFrame frame, Object receiverObject, Object methodName, Object blockObject, Object... argumentsObjects) { + InternalMethod method = lookup.executeLookup(frame, receiverObject, methodName); + + Object[] packedArguments = new Object[argumentsObjects.length + 3]; + packedArguments[0] = method; + packedArguments[1] = receiverObject; + packedArguments[2] = blockObject; + System.arraycopy(argumentsObjects, 0, packedArguments, 3, argumentsObjects.length); + + return dispatch.executeDispatch(frame, method, packedArguments); + } + } + + public abstract static class RubyLookupNode extends ExampleNode { + + public abstract InternalMethod executeLookup(VirtualFrame frame, Object receiverObject, Object methodName); + + @Specialization(guards = "receiver.getRubyClass() == cachedClass", assumptions = "cachedClass.getDependentAssumptions()") + protected static InternalMethod cachedLookup(RubyObject receiver, Object name, // + @Cached("receiver.getRubyClass()") RubyClass cachedClass, // + @Cached("genericLookup(receiver, name)") InternalMethod cachedLookup) { + return cachedLookup; + } + + @Specialization(contains = "cachedLookup") + protected static InternalMethod genericLookup(RubyObject receiver, Object name) { + return receiver.getRubyClass().lookup(name); + } + + } + + @ImportStatic(InternalMethod.class) + public abstract static class RubyDispatchNode extends ExampleNode { + + public abstract Object executeDispatch(VirtualFrame frame, InternalMethod function, Object[] packedArguments); + + /* + * Please note that cachedMethod != METHOD_MISSING is invoked once at specialization + * instantiation. It is never executed on the fast path. + */ + @Specialization(guards = {"method == cachedMethod", "cachedMethod != METHOD_MISSING"}) + protected static Object directCall(VirtualFrame frame, InternalMethod method, Object[] arguments, // + @Cached("method") InternalMethod cachedMethod, // + @Cached("create(cachedMethod.getTarget())") DirectCallNode callNode) { + return callNode.call(frame, arguments); + } + + /* + * The method == METHOD_MISSING can fold if the RubyLookup results just in a single entry + * returning the constant METHOD_MISSING. + */ + @Specialization(guards = "method == METHOD_MISSING") + protected static Object methodMissing(VirtualFrame frame, InternalMethod method, Object[] arguments) { + // a real implementation would do a call to a method named method_missing here + return RubyObject.NIL; + } + + @Specialization(contains = "directCall", guards = "method != METHOD_MISSING") + protected static Object indirectCall(VirtualFrame frame, InternalMethod method, Object[] arguments, // + @Cached("create()") IndirectCallNode callNode) { + return callNode.call(frame, method.getTarget(), arguments); + } + + @Override + public String toString() { + return ((SpecializedNode) this).getSpecializationNode().toString(); + } + } + + public static final class RubyObject { + + public static final RubyObject NIL = new RubyObject(null); + + private final RubyClass rubyClass; + + public RubyObject(RubyClass rubyClass) { + this.rubyClass = rubyClass; + } + + public RubyClass getRubyClass() { + return rubyClass; + } + + @Override + public String toString() { + return "RubyObject[class=" + rubyClass + "]"; + } + + } + + public static final class RubyClass /* this would extend RubyModule */{ + + private final String name; + private final RubyClass parent; // this would be a RubyModule + private final CyclicAssumption unmodified; + private final Map methods = new HashMap<>(); + private Assumption[] cachedDependentAssumptions; + private final int depth; + + public RubyClass(String name, RubyClass parent) { + this.name = name; + this.parent = parent; + this.unmodified = new CyclicAssumption("unmodified class " + name); + + // lookup depth for array allocation + RubyClass clazz = parent; + int currentDepth = 1; + while (clazz != null) { + currentDepth++; + clazz = clazz.parent; + } + this.depth = currentDepth; + } + + @TruffleBoundary + public InternalMethod lookup(Object methodName) { + InternalMethod method = methods.get(methodName); + if (method == null) { + if (parent != null) { + return parent.lookup(methodName); + } else { + return InternalMethod.METHOD_MISSING; + } + } else { + return method; + } + } + + @TruffleBoundary + public void addMethod(Object methodName, InternalMethod method) { + // check for existing method omitted for simplicity + this.methods.put(methodName, method); + this.unmodified.invalidate(); + } + + /* + * Method collects all unmodified assumptions in the class hierarchy. The result is cached + * per class to void recreation per call site. + */ + @TruffleBoundary + public Assumption[] getDependentAssumptions() { + Assumption[] dependentAssumptions = cachedDependentAssumptions; + if (dependentAssumptions != null) { + // we can use the cached dependent assumptions only if they are still valid + for (Assumption assumption : cachedDependentAssumptions) { + if (!assumption.isValid()) { + dependentAssumptions = null; + break; + } + } + } + if (dependentAssumptions == null) { + cachedDependentAssumptions = dependentAssumptions = createDependentAssumptions(); + } + return dependentAssumptions; + } + + @Override + public String toString() { + return "RubyClass[name=" + name + "]"; + } + + private Assumption[] createDependentAssumptions() { + Assumption[] dependentAssumptions; + RubyClass clazz = this; + dependentAssumptions = new Assumption[depth]; + + // populate array + int index = 0; + do { + dependentAssumptions[index] = clazz.unmodified.getAssumption(); + index++; + clazz = clazz.parent; + } while (clazz != null); + return dependentAssumptions; + } + } + + public static final class InternalMethod { + + public static final InternalMethod METHOD_MISSING = new InternalMethod(null); + + private final CallTarget target; + + public InternalMethod(CallTarget target) { + this.target = target; + } + + public CallTarget getTarget() { + return target; + } + + @Override + public String toString() { + return "InternalMethod[target=" + getTarget() + "]"; + } + + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/StableDispatch.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/StableDispatch.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,80 @@ +/* + * 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.truffle.api.dsl.test.examples; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; + +/** + * This example is based on the SLDispatchNode of SimpleLanguage. It shows how to implement a simple + * inline cache with an assumption that needs to be checked. + * + * Note that if an assumption is invalidated the specialization instantiation is removed. + */ +@SuppressWarnings("unused") +@NodeChildren({@NodeChild("function"), @NodeChild("arguments")}) +public class StableDispatch { + + public static class StableDispatchNode extends ExampleNode { + + @Specialization(guards = "function == cachedFunction", assumptions = "cachedFunction.getCallTargetStable()") + protected static Object directDispatch(VirtualFrame frame, SLFunction function, Object[] arguments, // + @Cached("function") SLFunction cachedFunction, // + @Cached("create(cachedFunction.getCallTarget())") DirectCallNode callNode) { + return callNode.call(frame, arguments); + } + + @Specialization(contains = "directDispatch") + protected static Object indirectDispatch(VirtualFrame frame, SLFunction function, Object[] arguments, // + @Cached("create()") IndirectCallNode callNode) { + return callNode.call(frame, function.getCallTarget(), arguments); + } + } + + public static final class SLFunction { + + private CallTarget callTarget; + private final CyclicAssumption callTargetStable; + + protected SLFunction(String name) { + this.callTargetStable = new CyclicAssumption(name); + } + + protected void setCallTarget(CallTarget callTarget) { + this.callTarget = callTarget; + this.callTargetStable.invalidate(); + } + + public CallTarget getCallTarget() { + return callTarget; + } + + public Assumption getCallTargetStable() { + return callTargetStable.getAssumption(); + } + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,235 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; + +/** + *

    + * A parameter annotated with {@link Cached} in a {@link Specialization} refers to a cached + * value of a specialization instance. A cached parameter value is initialized once using the + * initializer expression at specialization instantiation. For each call of the specialization + * method the cached value is provided by using the annotated parameter from the method body. Cache + * initializers are potentially executed before guard expressions declared in + * {@link Specialization#guards()}. + *

    + *

    + * A typical specialization may define multiple dynamic and multiple cached parameters. Dynamic + * parameter values are typically provided by executing child nodes of the operation. Cached + * parameters are initialized and stored once per specialization instantiation. Cached parameters + * are always constant at compile time. You may verify this by invoking + * {@link CompilerAsserts#compilationConstant(Object)} on any cached parameter. For consistency + * between specialization declarations cached parameters must be declared last in a specialization + * method. + *

    + *

    + * The initializer expression of a cached parameter is defined using a subset of Java. This subset + * includes field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=, + * >, >=) and integer literals. The return type of the initializer expression must be assignable to + * the parameter type. If the annotated parameter type is derived from {@link Node} then the + * {@link Node} instance is allowed to use the {@link Node#replace(Node)} method to replace itself. + * Bound elements without receivers are resolved using the following order: + *

      + *
    1. Dynamic and cached parameters of the enclosing specialization.
    2. + *
    3. Fields defined using {@link NodeField} for the enclosing node.
    4. + *
    5. Public constructors of the type of the annotated parameter using the new keyword + * as method name.
    6. + *
    7. Public and static methods or fields of the type of the annotated parameter.
    8. + *
    9. Non-private, static or virtual methods or fields of enclosing node.
    10. + *
    11. Non-private, static or virtual methods or fields of super types of the enclosing node.
    12. + *
    13. Public and static methods or fields imported using {@link ImportStatic}.
    14. + *
    + * + * The following examples explain the intended use of the {@link Cached} annotation. All of the + * examples have to be enclosed in the following node declaration: + *

    + * + *
    + * @NodeChild("operand")
    + * abstract TestNode extends Node {
    + *   abstract void execute(Object operandValue);
    + *   // ... example here ...
    + * }
    + * 
    + * + *
      + *
    1. + * This example defines one dynamic and one cached parameter. The operand parameter is representing + * the dynamic value of the operand while the cachedOperand is initialized once at first execution + * of the specialization (specialization instantiation time). + * + *
      + *  @Specialization
      + *  void doCached(int operand, @Local("operand") int cachedOperand) {
      + *      CompilerAsserts.compilationConstant(cachedOperand);
      + *      ...
      + *  }
      + *
      + *  Example executions:
      + *  execute(1) => doCached(1, 1) // new instantiation, localOperand is bound to 1
      + *  execute(0) => doCached(0, 1)
      + *  execute(2) => doCached(2, 1)
      + *
      + * 
      + * + *
    2. + *
    3. + * We extend the previous example by a guard for the cachedOperand value to be equal to the dynamic + * operand value. This specifies that the specialization is instantiated for each individual operand + * value that is provided. There are a lot of individual int values and for each + * individual int value a new specialization would get instantiated. The + * {@link Specialization#limit()} property defines a limit for the number of specializations that + * can get instantiated. If the specialization instantiation limit is reached then no further + * specializations are instantiated. Like for other specializations if there are no more + * specializations defined an {@link UnsupportedSpecializationException} is thrown. The default + * specialization instantiation limit is 3. + * + *
      + * @Specialization(guards = "==(operand, cachedOperand)")
      + * void doCached(int operand, @Cached("operand") int cachedOperand) {
      + *    CompilerAsserts.compilationConstant(cachedOperand);
      + *    ...
      + * }
      + *
      + * Example executions:
      + * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
      + * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
      + * execute(1) => doCached(1, 1)
      + * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
      + * execute(3) => throws UnsupportedSpecializationException // instantiation limit overflows
      + *
      + * 
      + * + *
    4. + *
    5. + * To handle the limit overflow we extend our example by an additional specialization named + * doNormal. This specialization has the same type restrictions but does not have local + * state nor the operand identity guard. It is also declared after doCached therefore + * it is only instantiated if the limit of the doCached specialization has been + * reached. In other words doNormal is more generic than doCached . The + * doNormal specialization uses contains="doCached" to specify + * that all instantiations of doCached get removed if doNormal is + * instantiated. Alternatively if the contains relation is omitted then all + * doCached instances remain but no new instances are created. + * + * + * @Specialization(guards = "==(operand, cachedOperand)") + * void doCached(int operand, @Cached("operand") int cachedOperand) { + * CompilerAsserts.compilationConstant(cachedOperand); + * ... + * } + * + * @Specialization(contains = "doCached") + * void doNormal(int operand) {...} + * + * Example executions with contains = "doCached": + * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0 + * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1 + * execute(1) => doCached(1, 1) + * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2 + * execute(3) => doNormal(3) // new instantiation of doNormal due to limit overflow; doCached gets removed. + * execute(1) => doNormal(1) + * + * Example executions without contains = "doCached": + * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0 + * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1 + * execute(1) => doCached(1, 1) + * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2 + * execute(3) => doNormal(3) // new instantiation of doNormal due to limit overflow + * execute(1) => doCached(1, 1) + * + * + * + *
    6. + *
    7. + * This next example shows how methods from the enclosing node can be used to initialize cached + * parameters. Please note that the visibility of transformLocal must not be private. + * + *
      + * @Specialization
      + * void s(int operand, @Cached("transformLocal(operand)") int cachedOperand) {
      + * }
      + *
      + * int transformLocal(int operand) {
      + *     return operand & 0x42;
      + * }
      + *
      + * 
    8. + *
  14. + *
  15. + * The new keyword can be used to initialize a cached parameter using a constructor of + * the parameter type. + * + *
    + * @Specialization
    + * void s(Object operand, @Cached("new()") OtherNode someNode) {
    + *     someNode.execute(operand);
    + * }
    + *
    + * static class OtherNode extends Node {
    + *
    + *     public String execute(Object value) {
    + *         throw new UnsupportedOperationException();
    + *     }
    + * }
    + *
    + * 
    + * + *
  16. + *
  17. + * Java types without public constructor but with a static factory methods can be initialized by + * just referencing its static factory method and its parameters. In this case + * {@link BranchProfile#create()} is used to instantiate the {@link BranchProfile} instance. + * + *
    + * @Specialization
    + * void s(int operand, @Local("create()") BranchProfile profile) {
    + * }
    + * 
    + * + *
  18. + *
+ * + * @see Specialization#guards() + * @see Specialization#contains() + * @see Specialization#limit() + * @see ImportStatic + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PARAMETER}) +public @interface Cached { + + /** + * Defines the initializer expression of the cached parameter value. + * + * @see Cached + */ + String value(); + +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,11 +26,14 @@ import java.lang.annotation.*; -/* +/** * Experimental API. + * + * @deprecated annotation has no effect anymore. */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD}) +@Deprecated public @interface Implies { String[] value(); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportGuards.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportGuards.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.dsl; - -import java.lang.annotation.*; - -/** - * Imports all public static methods usable as guards for {@link Specialization} annotations to the - * current class. Using this annotation common guards can be shared across nodes. Imported guards - * are derived from super classes. Guards declared in the node type hierarchy are always preferred - * to imported guards. Imported guards for a more concrete type are preferred to guards imported in - * the base class. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface ImportGuards { - - Class[] value(); - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportStatic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportStatic.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +/** + * Imports all public and static methods and fields of the provided + * classes for the use in DSL expressions of the annotated class or its subclasses. + * + * @see Specialization#guards() + * @see Specialization#assumptions() + * @see Specialization#limit() + * @see Cached + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface ImportStatic { + + Class[] value(); + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java Sat Feb 21 19:55:33 2015 +0100 @@ -26,13 +26,14 @@ import java.lang.annotation.*; +import com.oracle.truffle.api.*; + /** - * Declares one or multiple assumptions for use inside a source code generation enabled node. - * Declared assumptions must be passed to the {@link NodeFactory#createNode(Object...)} method as - * parameters. + * @deprecated use {@link NodeField} with type {@link Assumption} instead. */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.TYPE}) +@Deprecated public @interface NodeAssumptions { String[] value(); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Sat Feb 21 19:55:33 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 @@ -26,6 +26,91 @@ import java.lang.annotation.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + *

+ * Defines a method of a node subclass to represent one specialization of an operation. Multiple + * specializations can be defined in a node representing an operation. A specialization defines + * which kind of input is expected using the method signature and the annotation attributes. The + * specialized semantics of the operation are defined using the body of the annotated Java method. A + * specialization method must be declared in a class that is derived from {@link Node} that + * references a {@link TypeSystem}. At least one specialization must be defined per operation. If no + * specialization is valid for the given set of input values then an + * {@link UnsupportedSpecializationException} is thrown instead of invoking any specialization + * method. + *

+ *

+ * A specialization must have at least as many parameters as there are {@link NodeChild} annotations + * declared for the enclosing operation node. These parameters are declared in the same order as the + * {@link NodeChild} annotations (linear execution order). We call such parameters dynamic input + * parameters. Every specialization that is declared within an operation must have an equal number + * of dynamic input parameters. + *

+ *

+ * The supported kind of input values for a specialization are declared using guards. A + * specialization may provide declarative specifications for four kinds of guards: + *

    + *
  • Type guards optimistically assume the type of an input value. A value that matches the + * type is cast to its expected type automatically. Type guards are modeled using the parameter type + * of the specialization method. Types used for type guards must be defined in the + * {@link TypeSystem}. If the type of the parameter is {@link Object} then no type guard is used for + * the dynamic input parameter.
  • + * + *
  • Expression guards optimistically assume the return value of a user-defined expression + * to be true. Expression guards are modeled using Java expressions that return a + * boolean value. If the guard expression returns false, the + * specialization is no longer applicable and the operation is re-specialized. Guard expressions are + * declared using the {@link #guards()} attribute.
  • + * + *
  • Event guards trigger re-specialization in case an exception is thrown in the + * specialization body. The {@link #rewriteOn()} attribute can be used to declare a list of such + * exceptions. Guards of this kind are useful to avoid calculating a value twice when it is used in + * the guard and its specialization.
  • + * + *
  • Assumption guards optimistically assume that the state of an {@link Assumption} + * remains true. Assumptions can be assigned to specializations using the + * {@link #assumptions()} attribute.
  • + *
+ *

+ *

+ * The enclosing {@link Node} of a specialization method must have at least one public + * and non-final execute method. An execute method is a method that starts with + * 'execute'. If all execute methods declare the first parameter type as {@link Frame}, + * {@link VirtualFrame} or {@link MaterializedFrame} then the same frame type can be used as + * optional first parameter of the specialization. This parameter does not count to the number of + * dynamic parameters. + *

+ *

+ * A specialization method may declare multiple parameters annotated with {@link Cached}. Cached + * parameters are initialized and stored once per specialization instantiation. For consistency + * between specialization declarations cached parameters must be declared last in a specialization + * method. + *

+ *

+ * If the operation is re-specialized or if it is executed for the first time then all declared + * specializations of the operation are tried in declaration order until the guards of the first + * specialization accepts the current input values. The new specialization is then added to the + * chain of current specialization instances which might consist of one (monomorph) or multiple + * instances (polymorph). If an assumption of an instantiated specialization is violated then + * re-specialization is triggered again. + *

+ *

+ * With guards in combination with cached parameters it is possible that multiple instances of the + * same specialization are created. The {@link #limit()} attribute can be used to limit the number + * of instantiations per specialization. + *

+ * + * @see NodeChild + * @see ShortCircuit + * @see Fallback + * @see Cached + * @see TypeSystem + * @see TypeSystemReference + * @see UnsupportedSpecializationException + */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Specialization { @@ -36,39 +121,234 @@ @Deprecated int DEFAULT_ORDER = -1; /** - * The order has no effect anymore. The declaration order specialization methods is used - * instead. - * * @deprecated use declaration order instead. Will get removed in the next release. */ @Deprecated int order() default DEFAULT_ORDER; /** - * Inserts this and all specializations that are declared after this specialization before a - * specialization in the superclass. By default all specializations of the subclass are appended - * to the specializations of the superclass. + * References a specialization of a super class by its method name where this specialization is + * inserted before. The declaration order of a specialization is not usable for nodes where + * specializations are partly declared in the super class and partly declared in a derived + * class. By default all specializations declared in the derived class are appended to those in + * the super class. This attribute can be used to override the default behavior. */ String insertBefore() default ""; + /** + *

+ * Declares an event guards that trigger re-specialization in case an exception is thrown in the + * specialization body. This attribute can be used to declare a list of such exceptions. Guards + * of this kind are useful to avoid calculating a value twice when it is used in the guard and + * its specialization. + *

+ * + *

+ * If an event guard exception is triggered then all instantiations of this specialization are + * removed. If one of theses exceptions is thrown once then no further instantiations of this + * specialization are going to be created for this node. A specialization that rewrites on an + * exception must ensure that no non-repeatable side-effect is caused until the rewrite is + * triggered. + *

+ * + * Example usage: + * + *
+     * @Specialization(rewriteOn = ArithmeticException.class)
+     * int doAddNoOverflow(int a, int b) {
+     *     return ExactMath.addExact(a, b);
+     * }
+     * @Specialization
+     * long doAddWithOverflow(int a, int b) {
+     *     return a + b;
+     * }
+     * ...
+     * Example executions:
+     *   execute(Integer.MAX_VALUE - 1, 1) => doAddNoOverflow(Integer.MAX_VALUE - 1, 1)
+     *   execute(Integer.MAX_VALUE, 1)     => doAddNoOverflow(Integer.MAX_VALUE, 1)
+     *                                     => throws ArithmeticException
+     *                                     => doAddWithOverflow(Integer.MAX_VALUE, 1)
+     *   execute(Integer.MAX_VALUE - 1, 1) => doAddWithOverflow(Integer.MAX_VALUE - 1, 1)
+     * 
+ * + *

+ * + * @see ExactMath#addExact(int, int) + */ Class[] rewriteOn() default {}; /** - * The contains attribute declares all specializations that are contained by this - * specialization. A containing specialization must be strictly generic as the contained - * specialization. + *

+ * Declares other specializations of the same node to be contained by this specialization. Other + * specializations are references using their unique method name. If this specialization is + * instantiated then all contained specialization instances are removed and never instantiated + * again for this node instance. Therefore this specialization should handle strictly more + * inputs than which were handled by the contained specialization, otherwise the removal of the + * contained specialization will lead to unspecialized types of input values. The contains + * declaration is transitive for multiple involved specializations. + *

+ * Example usage: + * + *
+     * @Specialization(guards = "b == 2")
+     * void doDivPowerTwo(int a, int b) {
+     *     return a >> 1;
+     * }
+     * @Specialization(contains ="doDivPowerTwo", guards = "b > 0")
+     * void doDivPositive(int a, int b) {
+     *     return a / b;
+     * }
+     * ...
+     * Example executions with contains="doDivPowerTwo":
+     *   execute(4, 2) => doDivPowerTwo(4, 2)
+     *   execute(9, 3) => doDivPositive(9, 3) // doDivPowerTwo instances get removed
+     *   execute(4, 2) => doDivPositive(4, 2)
+     * Same executions without contains="doDivPowerTwo"
+     *   execute(4, 2) => doDivPowerTwo(4, 2)
+     *   execute(9, 3) => doDivPositive(9, 3)
+     *   execute(4, 2) => doDivPowerTwo(4, 2)
+     * 
+ * + *

+ * + * @see #guards() */ String[] contains() default {}; + /** + *

+ * Declares boolean expressions that define whether or not input values are + * applicable to this specialization instance. Guard expressions must always return the same + * result for each combination of the enclosing node instance and the bound input values. + *

+ *

+ * If a guard expression does not bind any dynamic input parameters then the DSL assumes that + * the result will not change for this node after specialization instantiation. The DSL asserts + * this assumption if assertions are enabled (-ea). + *

+ *

+ * Guard expressions are defined using a subset of Java. This subset includes field/parameter + * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical + * negation (!), logical disjunction (||) and integer literals. The return type of guard + * expressions must be boolean. Bound elements without receivers are resolved using + * the following order: + *

    + *
  1. Dynamic and cached parameters of the enclosing specialization.
  2. + *
  3. Fields defined using {@link NodeField} for the enclosing node.
  4. + *
  5. Non-private, static or virtual methods or fields of enclosing node.
  6. + *
  7. Non-private, static or virtual methods or fields of super types of the enclosing node.
  8. + *
  9. Public and static methods or fields imported using {@link ImportStatic}.
  10. + *
+ *

+ *

+ * Example usage: + * + *

+     * static boolean acceptOperand(int operand) {
+     *     assert operand <= 42;
+     *     return operand & 1 == 1;
+     * }
+     * @Specialization(guards = {"operand <= 42", "acceptOperand(operand)"})
+     * void doSpecialization(int operand) {...}
+     * 
+ * + *

+ * + * @see Cached + * @see ImportStatic + */ String[] guards() default {}; /** - * Defines the assumptions to check for this specialization. When the specialization method is - * invoked it is guaranteed that these assumptions still hold. It is not guaranteed that they - * are checked before the {@link #guards()} methods. They may be checked before after or in - * between {@link #guards()}. To declare assumptions use the {@link NodeAssumptions} annotation - * at class level. + *

+ * Declares assumption guards that optimistically assume that the state of an {@link Assumption} + * remains valid. Assumption expressions are cached once per specialization instantiation. If + * one of the returned assumptions gets invalidated then the specialization instance is removed. + * If the assumption expression returns an array of assumptions then all assumptions of the + * array are checked. This is limited to one-dimensional arrays. + *

+ *

+ * Assumption expressions are defined using a subset of Java. This subset includes + * field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, + * >=), logical negation (!), logical disjunction (||) and integer literals. The return type of + * the expression must be {@link Assumption} or an array of {@link Assumption} instances. + * Assumption expressions are not allowed to bind to dynamic parameter values of the + * specialization. Bound elements without receivers are resolved using the following order: + *

    + *
  1. Cached parameters of the enclosing specialization.
  2. + *
  3. Fields defined using {@link NodeField} for the enclosing node.
  4. + *
  5. Non-private, static or virtual methods or fields of enclosing node.
  6. + *
  7. Non-private, static or virtual methods or fields of super types of the enclosing node.
  8. + *
  9. Public and static methods or fields imported using {@link ImportStatic}.
  10. + *
+ *

+ * + *

+ * Example usage: + * + *

+     * static abstract class DynamicObject() {
+     *      abstract Shape getShape();
+     *      ...
+     * }
+     * static abstract class Shape() {
+     *      abstract Assumption getUnmodifiedAssuption();
+     *      ...
+     * }
+     * @Specialization(guards = "operand.getShape() == cachedShape", assumptions = "cachedShape.getUnmodifiedAssumption()")
+     * void doAssumeUnmodifiedShape(DynamicObject operand, @Cached("operand.getShape()") Shape cachedShape) {...}
+     * 
+ * + *

+ * + * @see Cached + * @see ImportStatic */ String[] assumptions() default {}; + /** + *

+ * Declares the expression that limits the number of specialization instantiations. The default + * limit for specialization instantiations is defined as "3". If the limit is + * exceeded no more instantiations of the enclosing specialization method are created. Please + * note that the existing specialization instantiations are not removed from the + * specialization chain. You can use {@link #contains()} to remove unnecessary specializations + * instances. + *

+ *

+ * The limit expression is defined using a subset of Java. This subset includes field/parameter + * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical + * negation (!), logical disjunction (||) and integer literals. The return type of the limit + * expression must be int. Limit expressions are not allowed to bind to dynamic + * parameter values of the specialization. Bound elements without receivers are resolved using + * the following order: + *

    + *
  1. Cached parameters of the enclosing specialization.
  2. + *
  3. Fields defined using {@link NodeField} for the enclosing node.
  4. + *
  5. Non-private, static or virtual methods or fields of enclosing node.
  6. + *
  7. Non-private, static or virtual methods or fields of super types of the enclosing node.
  8. + *
  9. Public and static methods or fields imported using {@link ImportStatic}.
  10. + *
+ *

+ * + *

+ * Example usage: + * + *

+     * static int getCacheLimit() {
+     *     return Integer.parseInt(System.getProperty("language.cacheLimit"));
+     * }
+     * @Specialization(guards = "operand == cachedOperand", limit = "getCacheLimit()")
+     * void doCached(Object operand, @Cached("operand") Object cachedOperand) {...}
+     * 
+ * + *

+ * + * @see #guards() + * @see #contains() + * @see Cached + * @see ImportStatic + */ + String limit() default ""; + } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java Sat Feb 21 19:55:33 2015 +0100 @@ -34,8 +34,9 @@ @Target({ElementType.TYPE}) public @interface DSLOptions { - /** Enable the new DSL generation layout. */ - boolean useNewLayout() default false; + /** Flag has no effect anymore. Is going to be removed soon. */ + @Deprecated + boolean useNewLayout() default true; /** * Lazy class loading ensures that all generated specialization classes are loaded lazily. diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -25,6 +25,7 @@ package com.oracle.truffle.api.dsl.internal; import java.lang.reflect.*; +import java.util.*; import java.util.concurrent.*; import com.oracle.truffle.api.*; @@ -64,6 +65,14 @@ return NodeCost.NONE; } + public void reset() { + SpecializationNode start = findStart(); + SpecializationNode end = findEnd(); + if (start != end) { + start.replace(end, "reset specialization"); + } + } + public static Node updateRoot(Node node) { updateRootImpl(((SpecializedNode) node).getSpecializationNode(), node); return node; @@ -86,7 +95,7 @@ protected final SpecializationNode polymorphicMerge(SpecializationNode newNode) { SpecializationNode merged = next.merge(newNode); if (merged == newNode && !isSame(newNode) && count() <= 2) { - return removeSame(new RewriteEvent0(findParentNode(), "merged polymorphic to monomorphic")); + return removeSame(new RewriteEvent0(findRoot(), "merged polymorphic to monomorphic")); } return merged; } @@ -112,6 +121,22 @@ return next != null ? next.merge(newNode) : newNode; } + protected SpecializationNode mergeNoSame(SpecializationNode newNode) { + return next != null ? next.merge(newNode) : newNode; + } + + protected final int countSame(SpecializationNode node) { + return findStart().countSameImpl(node); + } + + private int countSameImpl(SpecializationNode node) { + if (next != null) { + return next.countSameImpl(node) + (isSame(node) ? 1 : 0); + } else { + return 0; + } + } + @Override public final boolean equals(Object obj) { if (obj instanceof SpecializationNode) { @@ -133,10 +158,51 @@ return next != null ? next.count() + 1 : 1; } + private SpecializationNode findEnd() { + SpecializationNode node = this; + while (node.next != null) { + node = node.next; + } + return node; + } + + protected final Object removeThis(final CharSequence reason, Frame frame) { + return removeThisImpl(reason).acceptAndExecute(frame); + } + + protected final Object removeThis(final CharSequence reason, Frame frame, Object o1) { + return removeThisImpl(reason).acceptAndExecute(frame, o1); + } + + protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2) { + return removeThisImpl(reason).acceptAndExecute(frame, o1, o2); + } + + protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3) { + return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3); + } + + protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4) { + return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4); + } + + protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) { + return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4, o5); + } + + protected final Object removeThis(final CharSequence reason, Frame frame, Object... args) { + return removeThisImpl(reason).acceptAndExecute(frame, args); + } + + private SpecializationNode removeThisImpl(final CharSequence reason) { + this.replace(this.next, reason); + return findEnd().findStart(); + } + protected final SpecializationNode removeSame(final CharSequence reason) { return atomic(new Callable() { public SpecializationNode call() throws Exception { - return removeImpl(SpecializationNode.this, reason); + return removeSameImpl(SpecializationNode.this, reason); } }); } @@ -156,11 +222,11 @@ return node; } - private Node findParentNode() { + private Node findRoot() { return findStart().getParent(); } - private SpecializationNode removeImpl(SpecializationNode toRemove, CharSequence reason) { + private SpecializationNode removeSameImpl(SpecializationNode toRemove, CharSequence reason) { SpecializationNode start = findStart(); SpecializationNode current = start; while (current != null) { @@ -172,7 +238,7 @@ } current = current.next; } - return start; + return findEnd().findStart(); } public Object acceptAndExecute(Frame frame) { @@ -248,7 +314,7 @@ if (nextSpecialization == null) { return unsupported(frame); } - return insertSpecialization(nextSpecialization, new RewriteEvent0(findParentNode(), "inserted new specialization")).acceptAndExecute(frame); + return insertSpecialization(nextSpecialization, new RewriteEvent0(findRoot(), "inserted new specialization")).acceptAndExecute(frame); } protected final Object uninitialized(Frame frame, Object o1) { @@ -260,7 +326,7 @@ if (nextSpecialization == null) { return unsupported(frame, o1); } - return insertSpecialization(nextSpecialization, new RewriteEvent1(findParentNode(), "inserted new specialization", o1)).acceptAndExecute(frame, o1); + return insertSpecialization(nextSpecialization, new RewriteEvent1(findRoot(), "inserted new specialization", o1)).acceptAndExecute(frame, o1); } protected final Object uninitialized(Frame frame, Object o1, Object o2) { @@ -272,7 +338,7 @@ if (nextSpecialization == null) { return unsupported(frame, o1, o2); } - return insertSpecialization(nextSpecialization, new RewriteEvent2(findParentNode(), "inserted new specialization", o1, o2)).acceptAndExecute(frame, o1, o2); + return insertSpecialization(nextSpecialization, new RewriteEvent2(findRoot(), "inserted new specialization", o1, o2)).acceptAndExecute(frame, o1, o2); } protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3) { @@ -284,7 +350,7 @@ if (nextSpecialization == null) { return unsupported(frame, o1, o2, o3); } - return insertSpecialization(nextSpecialization, new RewriteEvent3(findParentNode(), "inserted new specialization", o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3); + return insertSpecialization(nextSpecialization, new RewriteEvent3(findRoot(), "inserted new specialization", o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3); } protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3, Object o4) { @@ -296,7 +362,7 @@ if (nextSpecialization == null) { return unsupported(frame, o1, o2, o3, o4); } - return insertSpecialization(nextSpecialization, new RewriteEvent4(findParentNode(), "inserts new specialization", o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4); + return insertSpecialization(nextSpecialization, new RewriteEvent4(findRoot(), "inserts new specialization", o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4); } protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) { @@ -308,7 +374,7 @@ if (nextSpecialization == null) { unsupported(frame, o1, o2, o3, o4, o5); } - return insertSpecialization(nextSpecialization, new RewriteEventN(findParentNode(), "inserts new specialization", o1, o2, o3, o4, o5)).acceptAndExecute(frame, o1, o2, o3, o4, o5); + return insertSpecialization(nextSpecialization, new RewriteEventN(findRoot(), "inserts new specialization", o1, o2, o3, o4, o5)).acceptAndExecute(frame, o1, o2, o3, o4, o5); } protected final Object uninitialized(Frame frame, Object... args) { @@ -320,7 +386,7 @@ if (nextSpecialization == null) { unsupported(frame, args); } - return insertSpecialization(nextSpecialization, new RewriteEventN(findParentNode(), "inserts new specialization", args)).acceptAndExecute(frame, args); + return insertSpecialization(nextSpecialization, new RewriteEventN(findRoot(), "inserts new specialization", args)).acceptAndExecute(frame, args); } private boolean needsPolymorphic() { @@ -328,59 +394,59 @@ } protected final Object remove(String reason, Frame frame) { - return removeSame(new RewriteEvent0(findParentNode(), reason)).acceptAndExecute(frame); + return removeSame(new RewriteEvent0(findRoot(), reason)).acceptAndExecute(frame); } protected final Object remove(String reason, Frame frame, Object o1) { - return removeSame(new RewriteEvent1(findParentNode(), reason, o1)).acceptAndExecute(frame, o1); + return removeSame(new RewriteEvent1(findRoot(), reason, o1)).acceptAndExecute(frame, o1); } protected final Object remove(String reason, Frame frame, Object o1, Object o2) { - return removeSame(new RewriteEvent2(findParentNode(), reason, o1, o2)).acceptAndExecute(frame, o1, o2); + return removeSame(new RewriteEvent2(findRoot(), reason, o1, o2)).acceptAndExecute(frame, o1, o2); } protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3) { - return removeSame(new RewriteEvent3(findParentNode(), reason, o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3); + return removeSame(new RewriteEvent3(findRoot(), reason, o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3); } protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) { - return removeSame(new RewriteEvent4(findParentNode(), reason, o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4); + return removeSame(new RewriteEvent4(findRoot(), reason, o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4); } protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) { - return removeSame(new RewriteEventN(findParentNode(), reason, o1, o2, o3, o4, o5)).acceptAndExecute(frame, o1, o2, o3, o4, o5); + return removeSame(new RewriteEventN(findRoot(), reason, o1, o2, o3, o4, o5)).acceptAndExecute(frame, o1, o2, o3, o4, o5); } protected final Object remove(String reason, Frame frame, Object... args) { - return removeSame(new RewriteEventN(findParentNode(), reason, args)).acceptAndExecute(frame, args); + return removeSame(new RewriteEventN(findRoot(), reason, args)).acceptAndExecute(frame, args); } protected Object unsupported(Frame frame) { - throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren()); + throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren()); } protected Object unsupported(Frame frame, Object o1) { - throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1); + throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1); } protected Object unsupported(Frame frame, Object o1, Object o2) { - throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2); + throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2); } protected Object unsupported(Frame frame, Object o1, Object o2, Object o3) { - throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3); + throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3); } protected Object unsupported(Frame frame, Object o1, Object o2, Object o3, Object o4) { - throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3, o4); + throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3, o4); } protected Object unsupported(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) { - throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3, o4, o5); + throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3, o4, o5); } protected Object unsupported(Frame frame, Object... args) { - throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), args); + throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), args); } private SpecializationNode insertSpecialization(final SpecializationNode generated, final CharSequence message) { @@ -412,8 +478,8 @@ return insertBefore(insertBefore, generated, message); } else { // existing node - merged.replace(merged, new RewriteEvent0(merged.findParentNode(), "merged specialization")); - return merged; + merged.replace(merged, new RewriteEvent0(merged.findRoot(), "merged specialization")); + return start; } } @@ -438,7 +504,7 @@ appendFields(b, clazz); if (next != null) { - b.append(" -> ").append(next.toString()); + b.append("\n -> ").append(next.toString()); } return b.toString(); } @@ -449,25 +515,69 @@ return; } b.append("("); + String sep = ""; for (Field field : fields) { if (Modifier.isStatic(field.getModifiers())) { continue; } + b.append(sep); String name = field.getName(); if (name.equals("root")) { continue; } b.append(field.getName()); + b.append(" = "); try { field.setAccessible(true); - b.append(field.get(this)); + Object value = field.get(this); + if (value instanceof Object[]) { + b.append(Arrays.toString((Object[]) field.get(this))); + } else { + b.append(field.get(this)); + } } catch (IllegalArgumentException e) { b.append(e.toString()); } catch (IllegalAccessException e) { b.append(e.toString()); } + sep = ", "; } b.append(")"); } + // utilities for generated code + protected static void check(Assumption assumption) throws InvalidAssumptionException { + if (assumption != null) { + assumption.check(); + } + } + + @ExplodeLoop + protected static void check(Assumption[] assumptions) throws InvalidAssumptionException { + if (assumptions != null) { + CompilerAsserts.compilationConstant(assumptions.length); + for (Assumption assumption : assumptions) { + check(assumption); + } + } + } + + protected static boolean isValid(Assumption assumption) { + if (assumption != null) { + return assumption.isValid(); + } + return true; + } + + protected static boolean isValid(Assumption[] assumptions) { + if (assumptions != null) { + for (Assumption assumption : assumptions) { + if (!isValid(assumption)) { + return false; + } + } + } + return true; + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java --- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java Sat Feb 21 19:55:33 2015 +0100 @@ -27,11 +27,11 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.interop.*; -public interface DynamicObject extends TypedObject, TruffleObject { +public abstract class DynamicObject implements TypedObject, TruffleObject { /** * Get the object's current shape. */ - Shape getShape(); + public abstract Shape getShape(); /** * Get property value. @@ -40,7 +40,7 @@ * @param defaultValue return value if property is not found * @return property value or defaultValue if object has no such property */ - Object get(Object key, Object defaultValue); + public abstract Object get(Object key, Object defaultValue); /** * Set value of existing property. @@ -49,7 +49,7 @@ * @param value value to be set * @return {@code true} if successful or {@code false} if property not found */ - boolean set(Object key, Object value); + public abstract boolean set(Object key, Object value); /** * Define new property or redefine existing property. @@ -58,7 +58,7 @@ * @param value value to be set * @param flags flags to be set */ - void define(Object key, Object value, int flags); + public abstract void define(Object key, Object value, int flags); /** * Define new property with a static location or change existing property. @@ -68,7 +68,7 @@ * @param flags flags to be set * @param locationFactory factory function that creates a location for a given shape and value */ - void define(Object key, Object value, int flags, LocationFactory locationFactory); + public abstract void define(Object key, Object value, int flags, LocationFactory locationFactory); /** * Change property flags. @@ -77,7 +77,7 @@ * @param newFlags flags to be set * @return {@code true} if successful or {@code false} if property not found */ - boolean changeFlags(Object key, int newFlags); + public abstract boolean changeFlags(Object key, int newFlags); /** * Change property flags. @@ -86,7 +86,7 @@ * @param flagsUpdateFunction function updating old flags to new flags * @return {@code true} if successful or {@code false} if property not found */ - boolean changeFlags(Object key, FlagsFunction flagsUpdateFunction); + public abstract boolean changeFlags(Object key, FlagsFunction flagsUpdateFunction); /** * Delete property. @@ -94,17 +94,17 @@ * @param key property identifier * @return {@code true} if successful or {@code false} if property not found */ - boolean delete(Object key); + public abstract boolean delete(Object key); /** * Returns the number of properties in this object. */ - int size(); + public abstract int size(); /** * Returns {@code true} if this object contains no properties. */ - boolean isEmpty(); + public abstract boolean isEmpty(); /** * Set object shape and grow storage if necessary. @@ -112,7 +112,7 @@ * @param oldShape the object's current shape (must equal {@link #getShape()}) * @param newShape the new shape to be set */ - void setShapeAndGrow(Shape oldShape, Shape newShape); + public abstract void setShapeAndGrow(Shape oldShape, Shape newShape); /** * Set object shape and resize storage if necessary. @@ -120,14 +120,14 @@ * @param oldShape the object's current shape (must equal {@link #getShape()}) * @param newShape the new shape to be set */ - void setShapeAndResize(Shape oldShape, Shape newShape); + public abstract void setShapeAndResize(Shape oldShape, Shape newShape); /** * Ensure object shape is up-to-date. * * @return {@code true} if shape has changed */ - boolean updateShape(); + public abstract boolean updateShape(); public interface FlagsFunction { int apply(int t); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Sat Feb 21 19:55:33 2015 +0100 @@ -318,11 +318,11 @@ // Use the "lite-probing" option, limited to a single pass of // probing and a single Instrument at each probed node. This - // particular test uses a shared event receiver at every + // particular test uses a shared event listener at every // lite-probed node. - final TestEventReceiver receiver = new TestEventReceiver(); + final TestEventListener listener = new TestEventListener(); - TestASTLiteProber astLiteProber = new TestASTLiteProber(receiver); + TestASTLiteProber astLiteProber = new TestASTLiteProber(listener); Probe.registerASTProber(astLiteProber); // Create a simple addition AST @@ -337,9 +337,9 @@ final CallTarget callTarget = runtime.createCallTarget(rootNode); // Check that the instrument is working as expected. - assertEquals(0, receiver.counter); + assertEquals(0, listener.counter); callTarget.call(); - assertEquals(2, receiver.counter); + assertEquals(2, listener.counter); // Check that you can't probe a node that's already received a probeLite() call try { @@ -409,7 +409,7 @@ } // Use reflection to check that each WrapperNode has a ProbeLiteNode with a - // SimpleEventReceiver + // SimpleEventListener try { java.lang.reflect.Field probeNodeField = leftWrapper.getClass().getDeclaredField("probeNode"); @@ -420,15 +420,15 @@ // hack: Since ProbeLiteNode is not visible, we do a string compare here assertTrue(probeNode.getClass().toString().endsWith("ProbeLiteNode")); - // Now we do the same to check the type of the eventReceiver in ProbeLiteNode - java.lang.reflect.Field eventReceiverField = probeNode.getClass().getDeclaredField("eventReceiver"); - eventReceiverField.setAccessible(true); - TruffleEventReceiver eventReceiver = (TruffleEventReceiver) eventReceiverField.get(probeNode); - assertTrue(eventReceiver instanceof SimpleEventReceiver); + // Now we do the same to check the type of the eventListener in ProbeLiteNode + java.lang.reflect.Field eventListenerField = probeNode.getClass().getDeclaredField("eventListener"); + eventListenerField.setAccessible(true); + TruffleEventListener eventListener = (TruffleEventListener) eventListenerField.get(probeNode); + assertTrue(eventListener instanceof SimpleEventListener); // Reset accessibility probeNodeField.setAccessible(false); - eventReceiverField.setAccessible(false); + eventListenerField.setAccessible(false); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { fail(); @@ -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 @@ -588,15 +588,15 @@ public final Instrument instrument; public TestCounter() { - instrument = Instrument.create(new SimpleEventReceiver() { + 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"); @@ -641,19 +641,19 @@ } /** - * "lite-probes" every value node with a shared event receiver. + * "lite-probes" every value node with a shared event listener. */ private static final class TestASTLiteProber implements NodeVisitor, ASTProber { - private final TruffleEventReceiver eventReceiver; + private final TruffleEventListener eventListener; - public TestASTLiteProber(SimpleEventReceiver simpleEventReceiver) { - this.eventReceiver = simpleEventReceiver; + public TestASTLiteProber(SimpleEventListener simpleEventListener) { + this.eventListener = simpleEventListener; } public boolean visit(Node node) { if (node instanceof TestValueNode) { final TestLanguageNode testNode = (TestValueNode) node; - testNode.probeLite(eventReceiver); + testNode.probeLite(eventListener); } return true; } @@ -667,7 +667,7 @@ * Counts the number of "enter" events at probed nodes. * */ - static final class TestEventReceiver extends SimpleEventReceiver { + static final class TestEventListener extends SimpleEventListener { public int counter = 0; @@ -692,10 +692,10 @@ // where we want to count executions. // it will get copied when ASTs cloned, so // keep the count in this outer class. - probe.attach(Instrument.create(new SimpleEventReceiver() { + 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/.checkstyle_checks.xml --- a/graal/com.oracle.truffle.api/.checkstyle_checks.xml Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/.checkstyle_checks.xml Sat Feb 21 19:55:33 2015 +0100 @@ -198,6 +198,11 @@ + + + + + diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java Sat Feb 21 19:55:33 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,29 @@ * 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; - } - - /** - * 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. - * - * @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 compilationConstant(Object value) { + if (!CompilerDirectives.isCompilationConstant(value)) { + neverPartOfCompilation("Value is not compilation constant"); + } } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Sat Feb 21 19:55:33 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,11 +25,8 @@ package com.oracle.truffle.api; import java.lang.annotation.*; -import java.lang.reflect.*; import java.util.concurrent.*; -import sun.misc.*; - /** * Directives that influence the optimizations of the Truffle compiler. All of the operations have * no effect when executed in the Truffle interpreter. @@ -42,22 +39,6 @@ public static final double SLOWPATH_PROBABILITY = 0.0001; public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY; - 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); - } - } - /** * Directive for the compiler to discontinue compilation at this code position and instead * insert a transfer to the interpreter. @@ -99,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(); } /** @@ -203,464 +171,6 @@ } /** - * Casts the given value to the value of the given type without any checks. The class must - * evaluate to a constant. The condition parameter gives a hint to the compiler under which - * circumstances this cast can be moved to an earlier location in the program. - * - * @param value the value that is known to have the specified type - * @param type the specified new type of the value - * @param condition the condition that makes this cast safe also at an earlier location of the - * program - * @return the value to be casted to the new type - */ - @Deprecated - public static T unsafeCast(Object value, Class type, boolean condition) { - return unsafeCast(value, type, condition, false); - } - - /** - * Casts the given value to the value of the given type without any checks. The class must - * evaluate to a constant. The condition parameter gives a hint to the compiler under which - * circumstances this cast can be moved to an earlier location in the program. - * - * @param value the value that is known to have the specified type - * @param type the specified new type of the value - * @param condition the condition that makes this cast safe also at an earlier location of the - * program - * @param nonNull whether value is known to never be null - * @return the value to be casted to the new type - */ - @Deprecated - @SuppressWarnings("unchecked") - public static T unsafeCast(Object value, Class type, boolean condition, boolean nonNull) { - return (T) value; - } - - /** - * Unsafe access to a boolean value within an object. The condition parameter gives a hint to - * the compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getBoolean(receiver, offset); - } - - /** - * Unsafe access to a byte value within an object. The condition parameter gives a hint to the - * compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getByte(receiver, offset); - } - - /** - * Unsafe access to a short value within an object. The condition parameter gives a hint to the - * compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static short unsafeGetShort(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getShort(receiver, offset); - } - - /** - * Unsafe access to an int value within an object. The condition parameter gives a hint to the - * compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getInt(receiver, offset); - } - - /** - * Unsafe access to a long value within an object. The condition parameter gives a hint to the - * compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getLong(receiver, offset); - } - - /** - * Unsafe access to a float value within an object. The condition parameter gives a hint to the - * compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getFloat(receiver, offset); - } - - /** - * Unsafe access to a double value within an object. The condition parameter gives a hint to the - * compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getDouble(receiver, offset); - } - - /** - * Unsafe access to an Object value within an object. The condition parameter gives a hint to - * the compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getObject(receiver, offset); - } - - /** - * Write a boolean value within an object. The location identity gives a hint to the compiler - * for improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity) { - UNSAFE.putBoolean(receiver, offset, value); - } - - /** - * Write a byte value within an object. The location identity gives a hint to the compiler for - * improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity) { - UNSAFE.putByte(receiver, offset, value); - } - - /** - * Write a short value within an object. The location identity gives a hint to the compiler for - * improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutShort(Object receiver, long offset, short value, Object locationIdentity) { - UNSAFE.putShort(receiver, offset, value); - } - - /** - * Write an int value within an object. The location identity gives a hint to the compiler for - * improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity) { - UNSAFE.putInt(receiver, offset, value); - } - - /** - * Write a long value within an object. The location identity gives a hint to the compiler for - * improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity) { - UNSAFE.putLong(receiver, offset, value); - } - - /** - * Write a float value within an object. The location identity gives a hint to the compiler for - * improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity) { - UNSAFE.putFloat(receiver, offset, value); - } - - /** - * Write a double value within an object. The location identity gives a hint to the compiler for - * improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity) { - UNSAFE.putDouble(receiver, offset, value); - } - - /** - * Write an Object value within an object. The location identity gives a hint to the compiler - * for improved global value numbering. - * - * @param receiver the object that is written to - * @param offset the offset at which to write to the object in bytes - * @param value the value to be written - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - */ - @Deprecated - public static void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity) { - UNSAFE.putObject(receiver, offset, value); - } - - /** - * Unsafe access to a final boolean value within an object. The condition parameter gives a hint - * to the compiler under which circumstances this access can be moved to an earlier location in - * the program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static boolean unsafeGetFinalBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getBoolean(receiver, offset); - } - - /** - * Unsafe access to a final byte value within an object. The condition parameter gives a hint to - * the compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static byte unsafeGetFinalByte(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getByte(receiver, offset); - } - - /** - * Unsafe access to a final short value within an object. The condition parameter gives a hint - * to the compiler under which circumstances this access can be moved to an earlier location in - * the program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static short unsafeGetFinalShort(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getShort(receiver, offset); - } - - /** - * Unsafe access to a final int value within an object. The condition parameter gives a hint to - * the compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static int unsafeGetFinalInt(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getInt(receiver, offset); - } - - /** - * Unsafe access to a final long value within an object. The condition parameter gives a hint to - * the compiler under which circumstances this access can be moved to an earlier location in the - * program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static long unsafeGetFinalLong(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getLong(receiver, offset); - } - - /** - * Unsafe access to a final float value within an object. The condition parameter gives a hint - * to the compiler under which circumstances this access can be moved to an earlier location in - * the program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static float unsafeGetFinalFloat(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getFloat(receiver, offset); - } - - /** - * Unsafe access to a final double value within an object. The condition parameter gives a hint - * to the compiler under which circumstances this access can be moved to an earlier location in - * the program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static double unsafeGetFinalDouble(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getDouble(receiver, offset); - } - - /** - * Unsafe access to a final Object value within an object. The condition parameter gives a hint - * to the compiler under which circumstances this access can be moved to an earlier location in - * the program. The location identity gives a hint to the compiler for improved global value - * numbering. - * - * @param receiver the object that is accessed - * @param offset the offset at which to access the object in bytes - * @param condition the condition that makes this access safe also at an earlier location in the - * program - * @param locationIdentity the location identity token that can be used for improved global - * value numbering or null - * @return the accessed value - */ - @Deprecated - public static Object unsafeGetFinalObject(Object receiver, long offset, boolean condition, Object locationIdentity) { - return UNSAFE.getObject(receiver, offset); - } - - /** * Marks a method that it is considered as a boundary for Truffle partial evaluation. */ @Retention(RetentionPolicy.RUNTIME) diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Sat Feb 21 19:55:33 2015 +0100 @@ -38,14 +38,14 @@ *

* Can be set with {@code -Dtruffle.ForceInterpreter=true}. */ - public static boolean ForceInterpreter = Boolean.getBoolean("truffle.ForceInterpreter"); + public static final boolean ForceInterpreter = Boolean.getBoolean("truffle.ForceInterpreter"); /** * Enables/disables the rewriting of traces in the Truffle runtime to stdout. *

* Can be set with {@code -Dtruffle.TraceRewrites=true}. */ - public static boolean TraceRewrites; + public static final boolean TraceRewrites; /** * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead @@ -97,20 +97,20 @@ } static { - final boolean[] values = {false, false}; + final boolean[] values = new boolean[3]; AccessController.doPrivileged(new PrivilegedAction() { public Void run() { - TraceRewrites = Boolean.getBoolean("truffle.TraceRewrites"); + values[0] = Boolean.getBoolean("truffle.TraceRewrites"); TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass"); TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost")); TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost")); - values[0] = Boolean.getBoolean("truffle.DetailedRewriteReasons"); - values[1] = Boolean.getBoolean("truffle.TraceASTJSON"); + values[1] = Boolean.getBoolean("truffle.DetailedRewriteReasons"); + values[2] = Boolean.getBoolean("truffle.TraceASTJSON"); return null; } }); - - DetailedRewriteReasons = values[0]; - TraceASTJSON = values[1]; + TraceRewrites = values[0]; + DetailedRewriteReasons = values[1]; + TraceASTJSON = values[2]; } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java Sat Feb 21 19:55:33 2015 +0100 @@ -33,4 +33,10 @@ Float, Boolean, Byte; + + public final byte tag; + + private FrameSlotKind() { + this.tag = (byte) ordinal(); + } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Sat Feb 21 19:55:33 2015 +0100 @@ -29,6 +29,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.unsafe.*; /** * Default implementation of the Truffle runtime if the virtual machine does not provide a better @@ -147,6 +148,9 @@ } public T getCapability(Class capability) { + if (capability == UnsafeAccessFactory.class) { + return capability.cast(new UnsafeAccessFactoryImpl()); + } return null; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/UnsafeAccessFactoryImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/UnsafeAccessFactoryImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,112 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.impl; + +import sun.misc.*; + +import com.oracle.truffle.api.unsafe.*; + +final class UnsafeAccessFactoryImpl implements UnsafeAccessFactory { + public UnsafeAccess createUnsafeAccess(final Unsafe unsafe) { + return new UnsafeAccessImpl(unsafe); + } + + private static final class UnsafeAccessImpl implements UnsafeAccess { + private final Unsafe unsafe; + + private UnsafeAccessImpl(Unsafe unsafe) { + this.unsafe = unsafe; + } + + @SuppressWarnings("unchecked") + public T uncheckedCast(Object value, Class type, boolean condition, boolean nonNull) { + return (T) value; + } + + public void putShort(Object receiver, long offset, short value, Object locationIdentity) { + unsafe.putShort(receiver, offset, value); + } + + public void putObject(Object receiver, long offset, Object value, Object locationIdentity) { + unsafe.putObject(receiver, offset, value); + } + + public void putLong(Object receiver, long offset, long value, Object locationIdentity) { + unsafe.putLong(receiver, offset, value); + } + + public void putInt(Object receiver, long offset, int value, Object locationIdentity) { + unsafe.putInt(receiver, offset, value); + } + + public void putFloat(Object receiver, long offset, float value, Object locationIdentity) { + unsafe.putFloat(receiver, offset, value); + } + + public void putDouble(Object receiver, long offset, double value, Object locationIdentity) { + unsafe.putDouble(receiver, offset, value); + } + + public void putByte(Object receiver, long offset, byte value, Object locationIdentity) { + unsafe.putByte(receiver, offset, value); + } + + public void putBoolean(Object receiver, long offset, boolean value, Object locationIdentity) { + unsafe.putBoolean(receiver, offset, value); + } + + public short getShort(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getShort(receiver, offset); + } + + public Object getObject(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getObject(receiver, offset); + } + + public long getLong(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getLong(receiver, offset); + } + + public int getInt(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getInt(receiver, offset); + } + + public float getFloat(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getFloat(receiver, offset); + } + + public double getDouble(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getDouble(receiver, offset); + } + + public byte getByte(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getByte(receiver, offset); + } + + public boolean getBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) { + return unsafe.getBoolean(receiver, offset); + } + } +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Sat Feb 21 19:55:33 2015 +0100 @@ -33,37 +33,37 @@ // TODO (mlvdv) migrate some of this to external documentation. /** * A dynamically added/removed binding between a {@link Probe}, which provides notification of - * {@linkplain TruffleEventReceiver execution events} taking place at a {@link Node} in a Guest - * Language (GL) Truffle AST, and a {@linkplain TruffleEventReceiver receiver}, which consumes + * {@linkplain TruffleEventListener execution events} taking place at a {@link Node} in a Guest + * Language (GL) Truffle AST, and a {@linkplain TruffleEventListener listener}, which consumes * notifications on behalf of an external tool. *

*

Summary: How to "instrument" an AST location:

*
    - *
  1. Create an implementation of {@link TruffleEventReceiver} that responds to events on behalf of + *
  2. Create an implementation of {@link TruffleEventListener} that responds to events on behalf of * a tool.
  3. - *
  4. Create an Instrument via factory method {@link Instrument#create(TruffleEventReceiver)}.
  5. + *
  6. Create an Instrument via factory method {@link Instrument#create(TruffleEventListener)}.
  7. *
  8. "Attach" the Instrument to a Probe via {@link Probe#attach(Instrument)}, at which point event - * notifications begin to arrive at the receiver.
  9. + * notifications begin to arrive at the listener. *
  10. When no longer needed, "detach" the Instrument via {@link Instrument#dispose()}, at which - * point event notifications to the receiver cease, and the Instrument becomes unusable.
  11. + * point event notifications to the listener cease, and the Instrument becomes unusable. *
*

- *

Options for creating receivers:

+ *

Options for creating listeners:

*

*

    - *
  1. Implement the interface {@link TruffleEventReceiver}. The event handling methods account for + *
  2. Implement the interface {@link TruffleEventListener}. The event handling methods account for * both the entry into an AST node (about to call) and several possible kinds of exit from an AST * node (just returned).
  3. - *
  4. Extend {@link DefaultEventReceiver}, which provides a no-op implementation of every - * {@link TruffleEventReceiver} method; override the methods of interest.
  5. - *
  6. Extend {@link SimpleEventReceiver}, where return values are ignored so only two methods (for + *
  7. Extend {@link DefaultEventListener}, which provides a no-op implementation of every + * {@link TruffleEventListener} method; override the methods of interest.
  8. + *
  9. Extend {@link SimpleEventListener}, where return values are ignored so only two methods (for * "enter" and "return") will notify all events.
  10. *
*

- *

General guidelines for receiver implementation:

+ *

General guidelines for listener implementation:

*

- * When an Instrument is attached to a Probe, the receiver effectively becomes part of the executing - * GL program; performance can be affected by the receiver's implementation. + * When an Instrument is attached to a Probe, the listener effectively becomes part of the executing + * GL program; performance can be affected by the listener's implementation. *

    *
  • Do not store {@link Frame} or {@link Node} references in fields.
  • *
  • Prefer {@code final} fields and (where performance is important) short methods.
  • @@ -71,7 +71,7 @@ * possible through code that is expected to be inlined, since this incurs no runtime overhead. When * access to frame data is needed, substitute a more expensive {@linkplain Frame#materialize() * materialized} representation of the frame. - *
  • If a receiver calls back to its tool during event handling, and if performance is an issue, + *
  • If a listener calls back to its tool during event handling, and if performance is an issue, * then this should be through a final "callback" field in the instrument, and the called methods * should be minimal.
  • *
  • On the other hand, implementations should prevent Truffle from inlining beyond a reasonable @@ -85,14 +85,14 @@ *

    *

    Allowing for AST cloning:

    *

    - * Truffle routinely clones ASTs, which has consequences for receiver implementation. + * Truffle routinely clones ASTs, which has consequences for listener implementation. *

      *
    • Even though a {@link Probe} is uniquely associated with a particular location in the * executing Guest Language program, execution events at that location will in general be * implemented by different {@link Node} instances, i.e. clones of the originally probed * node.
    • *
    • Because of cloning the {@link Node} supplied with notifications to a particular - * receiver will vary, but because they all represent the same GL program location the events should + * listener will vary, but because they all represent the same GL program location the events should * be treated as equivalent for most purposes.
    • *
    *

    @@ -107,8 +107,8 @@ *

*
  • Some global information is available, for example the execution * {@linkplain TruffleRuntime#iterateFrames(FrameInstanceVisitor) stack}.
  • - *
  • Additional information needed by a receiver could be stored when created, preferably - * {@code final} of course. For example, a reference to the {@link Probe} to which the receiver's + *
  • Additional information needed by a listener could be stored when created, preferably + * {@code final} of course. For example, a reference to the {@link Probe} to which the listener's * Instrument has been attached would give access to its corresponding * {@linkplain Probe#getProbedSourceSection() source location} or to the collection of * {@linkplain SyntaxTag tags} currently applied to the Probe.
  • @@ -129,43 +129,43 @@ * which can trigger deoptimization. * *

    - *

    Sharing receivers:

    + *

    Sharing listeners:

    *

    - * Although an Instrument may only be attached to a single Probe, a receiver can be shared among + * Although an Instrument may only be attached to a single Probe, a listener can be shared among * multiple Instruments. This can be useful for observing events that might happen at different * locations in a single AST, for example all assignments to a particular variable. In this case a * new Instrument would be created and attached at each assignment node, but all the Instruments - * would be created with the same receiver. + * would be created with the same listener. *

    * Disclaimer: experimental; under development. * * @see Probe - * @see TruffleEventReceiver + * @see TruffleEventListener */ public final class Instrument { /** - * Creates an instrument that will route execution events to a receiver. + * Creates an instrument that will route execution events to a listener. * - * @param receiver a receiver for event generated by the instrument + * @param listener a listener for event generated by the instrument * @param instrumentInfo optional description of the instrument's role * @return a new instrument, ready for attachment at a probe */ - public static Instrument create(TruffleEventReceiver receiver, String instrumentInfo) { - return new Instrument(receiver, instrumentInfo); + public static Instrument create(TruffleEventListener listener, String instrumentInfo) { + return new Instrument(listener, instrumentInfo); } /** - * Creates an instrument that will route execution events to a receiver. + * Creates an instrument that will route execution events to a listener. */ - public static Instrument create(TruffleEventReceiver receiver) { - return new Instrument(receiver, null); + public static Instrument create(TruffleEventListener listener) { + return new Instrument(listener, null); } /** - * Tool-supplied receiver of events. + * Tool-supplied listener for events. */ - private final TruffleEventReceiver toolEventreceiver; + private final TruffleEventListener toolEventListener; /** * Optional documentation, mainly for debugging. @@ -179,8 +179,8 @@ private Probe probe = null; - private Instrument(TruffleEventReceiver receiver, String instrumentInfo) { - this.toolEventreceiver = receiver; + private Instrument(TruffleEventListener listener, String instrumentInfo) { + this.toolEventListener = listener; this.instrumentInfo = instrumentInfo; } @@ -240,7 +240,7 @@ } @NodeInfo(cost = NodeCost.NONE) - final class InstrumentNode extends Node implements TruffleEventReceiver, InstrumentationNode { + final class InstrumentNode extends Node implements TruffleEventListener, InstrumentationNode { @Child private InstrumentNode nextInstrument; @@ -286,31 +286,31 @@ return nextInstrument.removeFromChain(instrument); } - public void enter(Node node, VirtualFrame frame) { - Instrument.this.toolEventreceiver.enter(node, frame); + public void enter(Node node, VirtualFrame vFrame) { + Instrument.this.toolEventListener.enter(node, vFrame); if (nextInstrument != null) { - nextInstrument.enter(node, frame); + nextInstrument.enter(node, vFrame); } } - public void returnVoid(Node node, VirtualFrame frame) { - Instrument.this.toolEventreceiver.returnVoid(node, frame); + public void returnVoid(Node node, VirtualFrame vFrame) { + Instrument.this.toolEventListener.returnVoid(node, vFrame); if (nextInstrument != null) { - nextInstrument.returnVoid(node, frame); + nextInstrument.returnVoid(node, vFrame); } } - public void returnValue(Node node, VirtualFrame frame, Object result) { - Instrument.this.toolEventreceiver.returnValue(node, frame, result); + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + Instrument.this.toolEventListener.returnValue(node, vFrame, result); if (nextInstrument != null) { - nextInstrument.returnValue(node, frame, result); + nextInstrument.returnValue(node, vFrame, result); } } - public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { - Instrument.this.toolEventreceiver.returnExceptional(node, frame, exception); + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + Instrument.this.toolEventListener.returnExceptional(node, vFrame, exception); if (nextInstrument != null) { - nextInstrument.returnExceptional(node, frame, exception); + nextInstrument.returnExceptional(node, vFrame, exception); } } @@ -318,7 +318,7 @@ if (Instrument.this.instrumentInfo != null) { return Instrument.this.instrumentInfo; } - return toolEventreceiver.getClass().getSimpleName(); + return toolEventListener.getClass().getSimpleName(); } } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Sat Feb 21 19:55:33 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.*; @@ -40,7 +41,7 @@ * is intended to persist at the location, even if the specific node instance is * {@linkplain Node#replace(Node) replaced}. *

    - * The effect of a binding is to intercept {@linkplain TruffleEventReceiver execution events} + * The effect of a binding is to intercept {@linkplain TruffleEventListener execution events} * arriving at the node and notify each attached {@link Instrument} before execution is allowed to * proceed to the child. *

    @@ -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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Sat Feb 21 19:55:33 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.*; @@ -35,7 +34,7 @@ /** * Implementation interfaces and classes for attaching {@link Probe}s to {@link WrapperNode}s. */ -public abstract class ProbeNode extends Node implements TruffleEventReceiver, InstrumentationNode { +public abstract class ProbeNode extends Node implements TruffleEventListener, InstrumentationNode { /** * A node that can be inserted into a Truffle AST, and which enables {@linkplain Instrument @@ -85,14 +84,14 @@ /** * Gets the node being "wrapped", i.e. the AST node for which - * {@linkplain TruffleEventReceiver execution events} will be reported through the + * {@linkplain TruffleEventListener execution events} will be reported through the * Instrumentation Framework. */ Node getChild(); /** * Gets the {@link Probe} responsible for installing this wrapper; none if the wrapper - * installed via {@linkplain Node#probeLite(TruffleEventReceiver) "lite-Probing"}. + * installed via {@linkplain Node#probeLite(TruffleEventListener) "lite-Probing"}. */ Probe getProbe(); @@ -120,8 +119,8 @@ * Creates a new {@link ProbeLiteNode} associated with, and attached to, a Guest Language * specific instance of {@link WrapperNode}. */ - public static void insertProbeLite(WrapperNode wrapper, TruffleEventReceiver eventReceiver) { - final ProbeLiteNode probeLiteNode = new ProbeLiteNode(eventReceiver); + public static void insertProbeLite(WrapperNode wrapper, TruffleEventListener eventListener) { + final ProbeLiteNode probeLiteNode = new ProbeLiteNode(eventListener); wrapper.insertProbe(probeLiteNode); } @@ -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,57 +216,55 @@ } } - 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"; } - } /** * Implementation of a probe that only ever has a single "instrument" associated with it. No * {@link Instrument} is ever created; instead this method simply delegates the various enter - * and return events to a {@link TruffleEventReceiver} passed in during construction. + * and return events to a {@link TruffleEventListener} passed in during construction. */ @NodeInfo(cost = NodeCost.NONE) private static final class ProbeLiteNode extends ProbeNode { - private final TruffleEventReceiver eventReceiver; + private final TruffleEventListener eventListener; - private ProbeLiteNode(TruffleEventReceiver eventReceiver) { - this.eventReceiver = eventReceiver; + private ProbeLiteNode(TruffleEventListener eventListener) { + this.eventListener = eventListener; } @Override @@ -305,20 +284,20 @@ throw new IllegalStateException("Instruments may not be removed at a \"lite-probed\" location"); } - public void enter(Node node, VirtualFrame frame) { - eventReceiver.enter(node, frame); + public void enter(Node node, VirtualFrame vFrame) { + eventListener.enter(node, vFrame); } - public void returnVoid(Node node, VirtualFrame frame) { - eventReceiver.returnVoid(node, frame); + public void returnVoid(Node node, VirtualFrame vFrame) { + eventListener.returnVoid(node, vFrame); } - public void returnValue(Node node, VirtualFrame frame, Object result) { - eventReceiver.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) { - eventReceiver.returnExceptional(node, frame, exception); + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + eventListener.returnExceptional(node, vFrame, exception); } public String instrumentationInfo() { diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventListener.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,57 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A listener of Truffle AST runtime execution events that can collect information and possibly + * intervene on behalf of an external tool. + */ +public interface TruffleEventListener { + + /** + * Receive notification that an AST node's execute method is about to be called. + */ + 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 vFrame); + + /** + * Receive notification that an AST Node'sexecute method has just returned a value (boxed if + * primitive). + */ + 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 vFrame, Exception exception); + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventReceiver.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleEventReceiver.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.instrument; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -/** - * A receiver of Truffle AST runtime execution events that can collect information and possibly - * intervene on behalf of an external tool. - */ -public interface TruffleEventReceiver { - - /** - * Receive notification that an AST node's execute method is about to be called. - */ - void enter(Node node, VirtualFrame frame); - - /** - * Receive notification that an AST Node's {@code void}-valued execute method has just returned. - */ - void returnVoid(Node node, VirtualFrame frame); - - /** - * Receive notification that an AST Node'sexecute method has just returned a value (boxed if - * primitive). - */ - void returnValue(Node node, VirtualFrame frame, Object result); - - /** - * Receive notification that an AST Node's execute method has just thrown an exception. - */ - void returnExceptional(Node node, VirtualFrame frame, Exception exception); - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventListener.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,49 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A listener for AST {@linkplain TruffleEventListener execution events} that provides a no-op + * implementation of every event. + */ +public class DefaultEventListener implements TruffleEventListener { + + public void enter(Node node, VirtualFrame vFrame) { + } + + public void returnVoid(Node node, VirtualFrame vFrame) { + } + + public void returnValue(Node node, VirtualFrame vFrame, Object result) { + } + + public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) { + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventReceiver.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultEventReceiver.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.instrument.impl; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; - -/** - * A receiver for AST {@linkplain TruffleEventReceiver execution events} that provides a no-op - * implementation of every event. - */ -public class DefaultEventReceiver implements TruffleEventReceiver { - - public void enter(Node node, VirtualFrame frame) { - } - - public void returnVoid(Node node, VirtualFrame frame) { - } - - public void returnValue(Node node, VirtualFrame frame, Object result) { - } - - public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { - } - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventListener.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,66 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.instrument.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * An abstract listener for AST {@linkplain TruffleEventListener execution events} that ignores + * return values and supports handling all events by overriding only two methods: + *

      + *
    • {@link #enter(Node, VirtualFrame)}, and
    • + *
    • {@link #returnAny(Node, VirtualFrame)}.
    • + *
    + */ +public abstract class SimpleEventListener implements TruffleEventListener { + + public void enter(Node node, VirtualFrame vFrame) { + } + + /** + * Receive notification that one of an AST Node's execute methods has just returned by any + * means: with or without a return value (ignored) or via exception (ignored). + * + * @param node + * @param vFrame + */ + public void returnAny(Node node, VirtualFrame vFrame) { + } + + public final void returnVoid(Node node, VirtualFrame vFrame) { + returnAny(node, vFrame); + } + + public final void returnValue(Node node, VirtualFrame vFrame, Object result) { + returnAny(node, vFrame); + } + + public final void returnExceptional(Node node, VirtualFrame vFrame, Exception e) { + returnAny(node, vFrame); + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventReceiver.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/SimpleEventReceiver.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.api.instrument.impl; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; - -/** - * An abstract receiver for AST {@linkplain TruffleEventReceiver execution events} that ignores - * return values and supports handling all events by overriding only two methods: - *
      - *
    • {@link #enter(Node, VirtualFrame)}, and
    • - *
    • {@link #returnAny(Node, VirtualFrame)}.
    • - *
    - */ -public abstract class SimpleEventReceiver implements TruffleEventReceiver { - - public void enter(Node node, VirtualFrame frame) { - } - - /** - * Receive notification that one of an AST Node's execute methods has just returned by any - * means: with or without a return value (ignored) or via exception (ignored). - * - * @param node - * @param frame - */ - public void returnAny(Node node, VirtualFrame frame) { - } - - public final void returnVoid(Node node, VirtualFrame frame) { - returnAny(node, frame); - } - - public final void returnValue(Node node, VirtualFrame frame, Object result) { - returnAny(node, frame); - } - - public final void returnExceptional(Node node, VirtualFrame frame, Exception e) { - returnAny(node, frame); - } - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -181,4 +181,8 @@ return String.format("%s(target=%s)", getClass().getSimpleName(), getCurrentCallTarget()); } + public static DirectCallNode create(CallTarget target) { + return Truffle.getRuntime().createDirectCallNode(target); + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -48,4 +48,8 @@ */ public abstract Object call(VirtualFrame frame, CallTarget target, Object[] arguments); + public static IndirectCallNode create() { + return Truffle.getRuntime().createIndirectCallNode(); + } + } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Sat Feb 21 19:55:33 2015 +0100 @@ -504,16 +504,16 @@ * its parent; the wrapper node must be provided by implementations of * {@link #createWrapperNode()}. *

    - * Unlike {@link #probe()}, once {@link #probeLite(TruffleEventReceiver)} is called at a node, + * Unlike {@link #probe()}, once {@link #probeLite(TruffleEventListener)} is called at a node, * no additional probing can be added and no additional instrumentation can be attached. *

    * This restricted form of instrumentation is intended for special cases where only one kind of * instrumentation is desired, and for which performance is a concern * - * @param eventReceiver + * @param eventListener * @throws ProbeException (unchecked) when a probe cannot be created, leaving the AST unchanged */ - public final void probeLite(TruffleEventReceiver eventReceiver) { + public final void probeLite(TruffleEventListener eventListener) { if (this instanceof WrapperNode) { throw new ProbeException(ProbeFailure.Reason.WRAPPER_NODE, null, this, null); @@ -545,7 +545,7 @@ } // Connect it to a Probe - ProbeNode.insertProbeLite(wrapper, eventReceiver); + ProbeNode.insertProbeLite(wrapper, eventListener); // Replace this node in the AST with the wrapper this.replace(wrapperNode); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Sat Feb 21 19:55:33 2015 +0100 @@ -29,7 +29,6 @@ import java.util.Map.Entry; import java.util.concurrent.atomic.*; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.instrument.impl.*; @@ -52,7 +51,7 @@ *

    *

      *
    • "Execution call" on a node is is defined as invocation of a node method that is instrumented - * to produce the event {@link TruffleEventReceiver#enter(Node, VirtualFrame)};
    • + * to produce the event {@link TruffleEventListener#enter(Node, VirtualFrame)}; *
    • Execution calls are tabulated only at instrumented nodes, i.e. those for which * {@linkplain Node#isInstrumentable() isInstrumentable() == true};
    • *
    • Execution calls are tabulated only at nodes present in the AST when originally created; @@ -75,13 +74,13 @@ public final class CoverageTracker extends InstrumentationTool { /** Counting data. */ - private final Map counters = new HashMap<>(); + private final Map coverageMap = new HashMap<>(); - /** For disposal. */ + /** Needed for disposal. */ private final List instruments = new ArrayList<>(); /** - * Counting is restricted to nodes holding this tag. + * Coverage counting is restricted to nodes holding this tag. */ private final SyntaxTag countingTag; @@ -112,7 +111,7 @@ @Override protected void internalReset() { - counters.clear(); + coverageMap.clear(); } @Override @@ -142,22 +141,21 @@ * every line associated with an appropriately tagged AST node; iterable in order of source * name, then line number. */ - final TreeSet> entries = new TreeSet<>(new LineLocationEntryComparator()); + final TreeSet> entries = new TreeSet<>(new LineLocationEntryComparator()); - final Map results = new HashMap<>(); - - for (Entry entry : counters.entrySet()) { + for (Entry entry : coverageMap.entrySet()) { entries.add(entry); } + final Map result = new HashMap<>(); Source curSource = null; Long[] curLineTable = null; - for (Entry entry : entries) { + for (Entry entry : entries) { final LineLocation key = entry.getKey(); final Source source = key.getSource(); final int lineNo = key.getLineNumber(); if (source != curSource) { if (curSource != null) { - results.put(curSource, curLineTable); + result.put(curSource, curLineTable); } curSource = source; curLineTable = new Long[source.getLineCount()]; @@ -165,9 +163,9 @@ curLineTable[lineNo - 1] = entry.getValue().count.longValue(); } if (curSource != null) { - results.put(curSource, curLineTable); + result.put(curSource, curLineTable); } - return results; + return result; } /** @@ -183,14 +181,14 @@ * every line associated with an appropriately tagged AST node; iterable in order of source * name, then line number. */ - final TreeSet> entries = new TreeSet<>(new LineLocationEntryComparator()); + final TreeSet> entries = new TreeSet<>(new LineLocationEntryComparator()); - for (Entry entry : counters.entrySet()) { + for (Entry entry : coverageMap.entrySet()) { entries.add(entry); } Source curSource = null; int curLineNo = 1; - for (Entry entry : entries) { + for (Entry entry : entries) { final LineLocation key = entry.getKey(); final Source source = key.getSource(); final int lineNo = key.getLineNumber(); @@ -228,9 +226,9 @@ } /** - * A receiver for events at each instrumented AST location. This receiver counts - * "execution calls" to the instrumented node and is stateful. State in receivers must - * be considered carefully since ASTs, along with all instrumentation (including event receivers + * 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. @@ -238,7 +236,7 @@ * In contrast, a primitive field would not be shared among clones and resulting counts * would not be accurate. */ - private final class CoverageEventReceiver extends DefaultEventReceiver { + private final class CoverageEventListener extends DefaultEventListener { /** * Shared by all clones of the associated instrument and by the table of counters for the @@ -246,22 +244,21 @@ */ private final AtomicLong count; - CoverageEventReceiver(AtomicLong count) { + CoverageEventListener(AtomicLong count) { this.count = count; } @Override - @TruffleBoundary - public void enter(Node node, VirtualFrame frame) { + public void enter(Node node, VirtualFrame vFrame) { if (isEnabled()) { count.getAndIncrement(); } } } - private static final class LineLocationEntryComparator implements Comparator> { + private static final class LineLocationEntryComparator implements Comparator> { - public int compare(Entry e1, Entry e2) { + public int compare(Entry e1, Entry e2) { return LineLocation.COMPARATOR.compare(e1.getKey(), e2.getKey()); } } @@ -279,35 +276,37 @@ if (srcSection == null) { // TODO (mlvdv) report this? } else { + // Get the source line where the final LineLocation lineLocation = srcSection.getLineLocation(); - CoverageCounter counter = counters.get(lineLocation); - if (counter != null) { + CoverageRecord record = coverageMap.get(lineLocation); + if (record != null) { // Another node starts on same line; count only the first (textually) - if (srcSection.getCharIndex() > counter.srcSection.getCharIndex()) { - // Counter already in place, corresponds to code earlier on line + if (srcSection.getCharIndex() > record.srcSection.getCharIndex()) { + // Record already in place, corresponds to code earlier on line return; } else { - // Counter already in place, corresponds to later code; replace it - counter.instrument.dispose(); + // Record already in place, corresponds to later code; replace it + record.instrument.dispose(); } } final AtomicLong count = new AtomicLong(); - final CoverageEventReceiver eventReceiver = new CoverageEventReceiver(count); - final Instrument instrument = Instrument.create(eventReceiver, CoverageTracker.class.getSimpleName()); + final CoverageEventListener eventListener = new CoverageEventListener(count); + final Instrument instrument = Instrument.create(eventListener, CoverageTracker.class.getSimpleName()); instruments.add(instrument); probe.attach(instrument); - counters.put(lineLocation, new CoverageCounter(srcSection, instrument, count)); + coverageMap.put(lineLocation, new CoverageRecord(srcSection, instrument, count)); } } } } - private class CoverageCounter { - final SourceSection srcSection; - final Instrument instrument; + 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; - CoverageCounter(SourceSection srcSection, Instrument instrument, AtomicLong count) { + CoverageRecord(SourceSection srcSection, Instrument instrument, AtomicLong count) { this.srcSection = srcSection; this.instrument = instrument; this.count = count; diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java Sat Feb 21 19:55:33 2015 +0100 @@ -49,7 +49,7 @@ *

      *

        *
      • "Execution call" on a node is is defined as invocation of a node method that is instrumented - * to produce the event {@link TruffleEventReceiver#enter(Node, VirtualFrame)};
      • + * to produce the event {@link TruffleEventListener#enter(Node, VirtualFrame)}; *
      • Execution calls are tabulated only at instrumented nodes, i.e. those for which * {@linkplain Node#isInstrumentable() isInstrumentable() == true};
      • *
      • Execution calls are tabulated only at nodes present in the AST when originally created; @@ -92,26 +92,38 @@ } /** - * Receiver for events at instrumented nodes. Counts are maintained in a shared table, so the - * receiver is stateless and can be shared by every {@link Instrument}. + * Listener for events at instrumented nodes. Counts are maintained in a shared table, so the + * listener is stateless and can be shared by every {@link Instrument}. */ - private final TruffleEventReceiver eventReceiver = new DefaultEventReceiver() { + private final TruffleEventListener eventListener = new DefaultEventListener() { @Override - public void enter(Node node, VirtualFrame frame) { - internalReceive(node); + public void enter(Node node, VirtualFrame vFrame) { + if (isEnabled()) { + final Class nodeClass = node.getClass(); + /* + * Everything up to here is inlined by Truffle compilation. Delegate the next part + * to a method behind an inlining boundary. + * + * Note that it is not permitted to pass a {@link VirtualFrame} across an inlining + * boundary; they are truly virtual in inlined code. + */ + AtomicLong nodeCounter = getCounter(nodeClass); + nodeCounter.getAndIncrement(); + } } + /** + * Mark this method as a boundary that will stop Truffle inlining, which should not be + * allowed to inline the hash table method or any other complex library code. + */ @TruffleBoundary - private void internalReceive(Node node) { - if (isEnabled()) { - final Class nodeClass = node.getClass(); - AtomicLong nodeCounter = counters.get(nodeClass); - if (nodeCounter == null) { - nodeCounter = new AtomicLong(); - counters.put(nodeClass, nodeCounter); - } - nodeCounter.getAndIncrement(); + private AtomicLong getCounter(Class nodeClass) { + AtomicLong nodeCounter = counters.get(nodeClass); + if (nodeCounter == null) { + nodeCounter = new AtomicLong(); + counters.put(nodeClass, nodeCounter); } + return nodeCounter; } }; @@ -268,7 +280,7 @@ if (node.isInstrumentable()) { try { - final Instrument instrument = Instrument.create(eventReceiver, "NodeExecCounter"); + final Instrument instrument = Instrument.create(eventListener, "NodeExecCounter"); instruments.add(instrument); node.probe().attach(instrument); } catch (ProbeException ex) { @@ -292,7 +304,7 @@ @Override public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) { if (countingTag == tag) { - final Instrument instrument = Instrument.create(eventReceiver, NodeExecCounter.class.getSimpleName()); + final Instrument instrument = Instrument.create(eventListener, NodeExecCounter.class.getSimpleName()); instruments.add(instrument); probe.attach(instrument); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccess.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,266 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.unsafe; + +public interface UnsafeAccess { + + /** + * Casts the given value to the value of the given type without any checks. The class must + * evaluate to a constant. The condition parameter gives a hint to the compiler under which + * circumstances this cast can be moved to an earlier location in the program. + * + * @param value the value that is known to have the specified type + * @param type the specified new type of the value + * @param condition the condition that makes this cast safe also at an earlier location of the + * program + * @param nonNull whether value is known to never be null + * @return the value to be casted to the new type + */ + T uncheckedCast(Object value, Class type, boolean condition, boolean nonNull); + + /** + * Unsafe access to a boolean value within an object. The condition parameter gives a hint to + * the compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + boolean getBoolean(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Unsafe access to a byte value within an object. The condition parameter gives a hint to the + * compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + byte getByte(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Unsafe access to a short value within an object. The condition parameter gives a hint to the + * compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + short getShort(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Unsafe access to an int value within an object. The condition parameter gives a hint to the + * compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + int getInt(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Unsafe access to a long value within an object. The condition parameter gives a hint to the + * compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + long getLong(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Unsafe access to a float value within an object. The condition parameter gives a hint to the + * compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + float getFloat(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Unsafe access to a double value within an object. The condition parameter gives a hint to the + * compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + double getDouble(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Unsafe access to an Object value within an object. The condition parameter gives a hint to + * the compiler under which circumstances this access can be moved to an earlier location in the + * program. The location identity gives a hint to the compiler for improved global value + * numbering. + * + * @param receiver the object that is accessed + * @param offset the offset at which to access the object in bytes + * @param condition the condition that makes this access safe also at an earlier location in the + * program + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + Object getObject(Object receiver, long offset, boolean condition, Object locationIdentity); + + /** + * Write a boolean value within an object. The location identity gives a hint to the compiler + * for improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putBoolean(Object receiver, long offset, boolean value, Object locationIdentity); + + /** + * Write a byte value within an object. The location identity gives a hint to the compiler for + * improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putByte(Object receiver, long offset, byte value, Object locationIdentity); + + /** + * Write a short value within an object. The location identity gives a hint to the compiler for + * improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putShort(Object receiver, long offset, short value, Object locationIdentity); + + /** + * Write an int value within an object. The location identity gives a hint to the compiler for + * improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putInt(Object receiver, long offset, int value, Object locationIdentity); + + /** + * Write a long value within an object. The location identity gives a hint to the compiler for + * improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putLong(Object receiver, long offset, long value, Object locationIdentity); + + /** + * Write a float value within an object. The location identity gives a hint to the compiler for + * improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putFloat(Object receiver, long offset, float value, Object locationIdentity); + + /** + * Write a double value within an object. The location identity gives a hint to the compiler for + * improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putDouble(Object receiver, long offset, double value, Object locationIdentity); + + /** + * Write an Object value within an object. The location identity gives a hint to the compiler + * for improved global value numbering. + * + * @param receiver the object that is written to + * @param offset the offset at which to write to the object in bytes + * @param value the value to be written + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + */ + void putObject(Object receiver, long offset, Object value, Object locationIdentity); +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccessFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccessFactory.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,31 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.unsafe; + +import sun.misc.*; + +public interface UnsafeAccessFactory { + UnsafeAccess createUnsafeAccess(Unsafe unsafe); +} diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Sat Feb 21 19:55:33 2015 +0100 @@ -44,8 +44,6 @@ */ public final class TruffleTypes { - public static final String OPTION_DETAILED_REWRITE_REASONS = "DetailedRewriteReasons"; - private final DeclaredType node; private final ArrayType nodeArray; private final TypeMirror unexpectedValueException; @@ -68,7 +66,6 @@ private final DeclaredType nodeFactory; private final DeclaredType nodeFactoryBase; private final DeclaredType dslMetadata; - private final DeclaredType implies; private final DeclaredType generateNodeFactory; private final TypeElement expectError; @@ -97,7 +94,6 @@ nodeFactory = getRequired(context, NodeFactory.class); nodeFactoryBase = getRequired(context, NodeFactoryBase.class); dslMetadata = getRequired(context, DSLMetadata.class); - implies = getRequired(context, Implies.class); expectError = (TypeElement) getRequired(context, ExpectError.class).asElement(); generateNodeFactory = getRequired(context, GenerateNodeFactory.class); } @@ -106,10 +102,6 @@ return generateNodeFactory; } - public DeclaredType getImplies() { - return implies; - } - public DeclaredType getDslMetadata() { return dslMetadata; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,24 @@ +/* + * 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. + */ + +// The content of this file is automatically generated. DO NOT EDIT. diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,431 @@ +/* + * 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.truffle.dsl.processor.expression; + +import java.util.*; +import java.util.concurrent.atomic.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public abstract class DSLExpression { + + private TypeMirror resolvedTargetType; + + private DSLExpression() { + } + + public static DSLExpression parse(String input) { + return Parser.parse(input); + } + + public final Set findBoundVariableElements() { + final Set variables = new HashSet<>(); + this.accept(new AbstractDSLExpressionVisitor() { + + @Override + public void visitVariable(Variable variable) { + if (variable.getReceiver() == null) { + variables.add(variable.getResolvedVariable()); + } + } + + }); + return variables; + } + + public final Set findBoundVariables() { + final Set variables = new HashSet<>(); + this.accept(new AbstractDSLExpressionVisitor() { + + @Override + public void visitVariable(Variable variable) { + if (variable.getReceiver() == null) { + variables.add(variable); + } + } + + }); + return variables; + } + + public boolean containsComparisons() { + final AtomicBoolean found = new AtomicBoolean(); + this.accept(new AbstractDSLExpressionVisitor() { + @Override + public void visitBinary(Binary binary) { + if (binary.isComparison()) { + found.set(true); + } + } + }); + return found.get(); + } + + public void setResolvedTargetType(TypeMirror resolvedTargetType) { + this.resolvedTargetType = resolvedTargetType; + } + + public TypeMirror getResolvedTargetType() { + return resolvedTargetType; + } + + public abstract TypeMirror getResolvedType(); + + public abstract void accept(DSLExpressionVisitor visitor); + + public static final class Negate extends DSLExpression { + + private final DSLExpression receiver; + + public Negate(DSLExpression receiver) { + this.receiver = receiver; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + receiver.accept(visitor); + visitor.visitNegate(this); + } + + public DSLExpression getReceiver() { + return receiver; + } + + @Override + public TypeMirror getResolvedType() { + return receiver.getResolvedType(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Negate) { + return receiver.equals(((Negate) obj).receiver); + } + return false; + } + + @Override + public int hashCode() { + return receiver.hashCode(); + } + } + + public static final class Binary extends DSLExpression { + + private final String operator; + private final DSLExpression left; + private final DSLExpression right; + + private TypeMirror resolvedType; + + public Binary(String operator, DSLExpression left, DSLExpression right) { + this.operator = operator; + this.left = left; + this.right = right; + } + + public boolean isComparison() { + return DSLExpressionResolver.COMPARABLE_OPERATORS.contains(operator) || DSLExpressionResolver.IDENTITY_OPERATORS.contains(operator); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Binary) { + Binary other = (Binary) obj; + return operator.equals(other.operator) && left.equals(other.left) && right.equals(other.right); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(operator, left, right); + } + + public String getOperator() { + return operator; + } + + public DSLExpression getLeft() { + return left; + } + + public DSLExpression getRight() { + return right; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + left.accept(visitor); + right.accept(visitor); + visitor.visitBinary(this); + } + + @Override + public TypeMirror getResolvedType() { + return resolvedType; + } + + public void setResolvedType(TypeMirror resolvedType) { + this.resolvedType = resolvedType; + } + + @Override + public String toString() { + return "Binary [left=" + left + ", operator=" + operator + ", right=" + right + ", resolvedType=" + resolvedType + "]"; + } + + } + + public static final class Call extends DSLExpression { + + private final DSLExpression receiver; + private final String name; + private final List parameters; + + private ExecutableElement resolvedMethod; + + public Call(DSLExpression receiver, String name, List parameters) { + this.receiver = receiver; + this.name = name; + this.parameters = parameters; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Call) { + Call other = (Call) obj; + return Objects.equals(receiver, other.receiver) && name.equals(other.name) && parameters.equals(other.parameters); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(receiver, name, parameters); + } + + public DSLExpression getReceiver() { + return receiver; + } + + public String getName() { + return name; + } + + public List getParameters() { + return parameters; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + if (receiver != null) { + receiver.accept(visitor); + } + for (DSLExpression parameter : getParameters()) { + parameter.accept(visitor); + } + visitor.visitCall(this); + } + + @Override + public TypeMirror getResolvedType() { + if (resolvedMethod == null) { + return null; + } + if (resolvedMethod.getKind() == ElementKind.CONSTRUCTOR) { + return resolvedMethod.getEnclosingElement().asType(); + } else { + return resolvedMethod.getReturnType(); + } + } + + public ExecutableElement getResolvedMethod() { + return resolvedMethod; + } + + public void setResolvedMethod(ExecutableElement resolvedMethod) { + this.resolvedMethod = resolvedMethod; + } + + @Override + public String toString() { + return "Call [receiver=" + receiver + ", name=" + name + ", parameters=" + parameters + ", resolvedMethod=" + resolvedMethod + "]"; + } + + } + + public static final class Variable extends DSLExpression { + + private final DSLExpression receiver; + private final String name; + + private VariableElement resolvedVariable; + + public Variable(DSLExpression receiver, String name) { + this.receiver = receiver; + this.name = name; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Variable) { + Variable other = (Variable) obj; + return Objects.equals(receiver, other.receiver) && name.equals(other.name); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(receiver, name); + } + + public DSLExpression getReceiver() { + return receiver; + } + + public String getName() { + return name; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + if (receiver != null) { + receiver.accept(visitor); + } + visitor.visitVariable(this); + } + + @Override + public TypeMirror getResolvedType() { + return resolvedVariable != null ? resolvedVariable.asType() : null; + } + + public void setResolvedVariable(VariableElement resolvedVariable) { + this.resolvedVariable = resolvedVariable; + } + + public VariableElement getResolvedVariable() { + return resolvedVariable; + } + + @Override + public String toString() { + return "Variable [receiver=" + receiver + ", name=" + name + ", resolvedVariable=" + resolvedVariable + "]"; + } + + } + + public static final class IntLiteral extends DSLExpression { + + private final String literal; + + private int resolvedValueInt; + private TypeMirror resolvedType; + + public IntLiteral(String literal) { + this.literal = literal; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof IntLiteral) { + IntLiteral other = (IntLiteral) obj; + return resolvedValueInt == other.resolvedValueInt; + } + return false; + } + + @Override + public int hashCode() { + return resolvedValueInt; + } + + public String getLiteral() { + return literal; + } + + public int getResolvedValueInt() { + return resolvedValueInt; + } + + public void setResolvedValueInt(int resolved) { + this.resolvedValueInt = resolved; + } + + @Override + public TypeMirror getResolvedType() { + return resolvedType; + } + + public void setResolvedType(TypeMirror resolvedType) { + this.resolvedType = resolvedType; + } + + @Override + public void accept(DSLExpressionVisitor visitor) { + visitor.visitIntLiteral(this); + } + + @Override + public String toString() { + return "IntLiteral [literal=" + literal + ", resolvedValueInt=" + resolvedValueInt + ", resolvedType=" + resolvedType + "]"; + } + + } + + public abstract class AbstractDSLExpressionVisitor implements DSLExpressionVisitor { + + public void visitBinary(Binary binary) { + } + + public void visitCall(Call binary) { + } + + public void visitIntLiteral(IntLiteral binary) { + } + + public void visitNegate(Negate negate) { + } + + public void visitVariable(Variable binary) { + } + } + + public interface DSLExpressionVisitor { + + void visitBinary(Binary binary); + + void visitNegate(Negate negate); + + void visitCall(Call binary); + + void visitVariable(Variable binary); + + void visitIntLiteral(IntLiteral binary); + + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,235 @@ +/* + * 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.truffle.dsl.processor.expression; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; + +public class DSLExpressionResolver implements DSLExpressionVisitor { + + private static final List LOGIC_OPERATORS = Arrays.asList("||"); + public static final List COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">="); + public static final List IDENTITY_OPERATORS = Arrays.asList("==", "!="); + private static final String CONSTRUCTOR_KEYWORD = "new"; + + private final List variables = new ArrayList<>(); + private final List methods = new ArrayList<>(); + private final ProcessorContext context; + + private DSLExpressionResolver(ProcessorContext context) { + this.context = context; + } + + public DSLExpressionResolver(ProcessorContext context, List lookupElements) { + this(context); + lookup(lookupElements); + } + + public DSLExpressionResolver copy(List prefixElements) { + DSLExpressionResolver resolver = new DSLExpressionResolver(context); + resolver.lookup(prefixElements); + resolver.variables.addAll(variables); + resolver.methods.addAll(methods); + return resolver; + } + + private void lookup(List lookupElements) { + variablesIn(variables, lookupElements, false); + methodsIn(lookupElements); + } + + private void methodsIn(List lookupElements) { + for (Element variable : lookupElements) { + ElementKind kind = variable.getKind(); + if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) { + methods.add((ExecutableElement) variable); + } + } + } + + private static void variablesIn(List variables, List lookupElements, boolean publicOnly) { + for (Element variable : lookupElements) { + ElementKind kind = variable.getKind(); + if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER || kind == ElementKind.FIELD || kind == ElementKind.ENUM_CONSTANT) { + VariableElement variableElement = (VariableElement) variable; + if (!publicOnly || variableElement.getModifiers().contains(Modifier.PUBLIC)) { + variables.add(variableElement); + } + } + } + } + + private static String getMethodName(ExecutableElement method) { + if (method.getKind() == ElementKind.CONSTRUCTOR) { + return CONSTRUCTOR_KEYWORD; + } else { + return method.getSimpleName().toString(); + } + } + + public void visitBinary(Binary binary) { + String operator = binary.getOperator(); + TypeMirror leftType = binary.getLeft().getResolvedType(); + TypeMirror rightType = binary.getRight().getResolvedType(); + if (!ElementUtils.typeEquals(leftType, rightType)) { + throw new InvalidExpressionException(String.format("Incompatible operand types %s and %s.", ElementUtils.getSimpleName(leftType), ElementUtils.getSimpleName(rightType))); + } + + TypeMirror booleanType = context.getType(boolean.class); + boolean valid; + if (LOGIC_OPERATORS.contains(operator)) { + valid = ElementUtils.typeEquals(leftType, booleanType); + } else if (COMPARABLE_OPERATORS.contains(operator)) { + valid = ElementUtils.isPrimitive(leftType); + } else if (IDENTITY_OPERATORS.contains(operator)) { + valid = leftType.getKind().isPrimitive() || leftType.getKind() == TypeKind.DECLARED || leftType.getKind() == TypeKind.ARRAY; + } else { + throw new InvalidExpressionException(String.format("The operator %s is undefined.", operator)); + } + binary.setResolvedType(booleanType); + + if (!valid) { + throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type(s) %s %s.", operator, ElementUtils.getSimpleName(leftType), + ElementUtils.getSimpleName(rightType))); + } + } + + public void visitNegate(Negate negate) { + TypeMirror booleanType = context.getType(boolean.class); + TypeMirror resolvedType = negate.getResolvedType(); + if (!ElementUtils.typeEquals(resolvedType, booleanType)) { + throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type %s.", "!", ElementUtils.getSimpleName(resolvedType))); + } + } + + public void visitCall(Call call) { + List lookupMethods; + DSLExpression receiver = call.getReceiver(); + if (receiver == null) { + lookupMethods = this.methods; + } else { + TypeMirror type = receiver.getResolvedType(); + if (type.getKind() == TypeKind.DECLARED) { + type = context.reloadType(type); // ensure ECJ has the type loaded + lookupMethods = ElementFilter.methodsIn(context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement())); + } else { + lookupMethods = Collections.emptyList(); + } + } + + ExecutableElement foundWithName = null; + outer: for (ExecutableElement method : lookupMethods) { + if (getMethodName(method).equals(call.getName())) { + foundWithName = method; + + List parameters = method.getParameters(); + if (parameters.size() != call.getParameters().size()) { + continue outer; + } + + int parameterIndex = 0; + for (DSLExpression expression : call.getParameters()) { + TypeMirror sourceType = expression.getResolvedType(); + TypeMirror targetType = parameters.get(parameterIndex).asType(); + if (!ElementUtils.isAssignable(sourceType, targetType)) { + continue outer; + } + expression.setResolvedTargetType(targetType); + parameterIndex++; + } + + call.setResolvedMethod(method); + break; + } + } + if (call.getResolvedMethod() == null) { + if (foundWithName == null) { + // parameter mismatch + throw new InvalidExpressionException(String.format("The method %s is undefined for the enclosing scope.", call.getName())); + } else { + StringBuilder arguments = new StringBuilder(); + String sep = ""; + for (DSLExpression expression : call.getParameters()) { + arguments.append(sep).append(ElementUtils.getSimpleName(expression.getResolvedType())); + sep = ", "; + } + // name mismatch + throw new InvalidExpressionException(String.format("The method %s in the type %s is not applicable for the arguments %s.", // + ElementUtils.getReadableSignature(foundWithName), // + ElementUtils.getSimpleName((TypeElement) foundWithName.getEnclosingElement()), arguments.toString())); + } + } + } + + public void visitVariable(Variable variable) { + List lookupVariables; + DSLExpression receiver = variable.getReceiver(); + if (receiver == null) { + lookupVariables = this.variables; + } else { + TypeMirror type = receiver.getResolvedType(); + if (type.getKind() == TypeKind.DECLARED) { + type = context.reloadType(type); // ensure ECJ has the type loaded + lookupVariables = new ArrayList<>(); + variablesIn(lookupVariables, context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()), true); + } else if (type.getKind() == TypeKind.ARRAY) { + lookupVariables = Arrays. asList(new CodeVariableElement(context.getType(int.class), "length")); + } else { + lookupVariables = Collections.emptyList(); + } + } + + for (VariableElement variableElement : lookupVariables) { + if (variableElement.getSimpleName().toString().equals(variable.getName())) { + variable.setResolvedVariable(variableElement); + break; + } + } + if (variable.getResolvedVariable() == null) { + throw new InvalidExpressionException(String.format("%s cannot be resolved.", variable.getName())); + } + } + + public void visitIntLiteral(IntLiteral binary) { + try { + binary.setResolvedType(context.getType(int.class)); + binary.setResolvedValueInt(Integer.parseInt(binary.getLiteral())); + } catch (NumberFormatException e) { + throw new InvalidExpressionException(String.format("Type mismatch: cannot convert from String '%s' to int", binary.getLiteral())); + } + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,125 @@ +/* + * 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. + */ + +/* + * This is the grammar for DSL expressions that is used to automatically generate the Parser.java and Scanner.java + * files. You can download the parser generator Coco/R from http://ssw.jku.at/coco/. Then run + * "java -jar Coco.jar Expression.atg" + */ + +COMPILER Expression + +CHARACTERS + +letter = 'A' .. 'Z' + 'a' .. 'z' + '_' + '$'. +nonZeroDigit = "123456789". +digit = '0' + nonZeroDigit . + +TOKENS + +identifier = letter {letter | digit}. +numericLiteral = "0" | nonZeroDigit { digit }. + +PRAGMAS + +PRODUCTIONS + + +Expression += +LogicFactor +. + + +LogicFactor += +ComparisonFactor +[ + ("||") (. Token op = t; .) + ComparisonFactor (. result = new Binary(op.val, result, right); .) +] +. + +ComparisonFactor += +NegateFactor +[ + ("<" | "<=" | ">" | ">=" | "==" | "!=" ) (. Token op = t; .) + NegateFactor (. result = new Binary(op.val, result, right); .) +] +. + + +NegateFactor += (. boolean negated = false; .) +[ + "!" (. negated = true; .) +] + Factor (. result = negated ? new Negate(result) : result;.) +. + + +Factor += (. result = null; .) + +( + MemberExpression +| + numericLiteral (. result = new IntLiteral(t.val); .) +| + "(" + Expression + ")" + +) +. + +MemberExpression += (. result = null; .) +( + + identifier (. Variable variable = new Variable(receiver, t.val); .) + (. result = variable; .) +[ + + "(" (. List parameters = new ArrayList<>(); + DSLExpression parameter; .) + [ + Expression (. parameters.add(parameter); .) + { + "," + Expression (. parameters.add(parameter); .) + } + ] + ")" (. result = new Call(variable.getReceiver(), variable.getName(), parameters); .) +] + +) +[ + "." MemberExpression +] +. +END Expression. + + + diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,32 @@ +/* + * 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.truffle.dsl.processor.expression; + +public class InvalidExpressionException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public InvalidExpressionException(String message) { + super(message); + } +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,211 @@ +/*------------------------------------------------------------------------- +Compiler Generator Coco/R, +Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +extended by M. Loeberbauer & A. Woess, Univ. of Linz +ported from C# to Java by Wolfgang Ahorner +with improvements by Pat Terry, Rhodes University + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program 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 +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As an exception, it is allowed to write an extension of Coco/R that is +used as a plugin in non-free software. + +If not otherwise stated, any source code generated by Coco/R (other than +Coco/R itself) does not fall under the GNU General Public License. +------------------------------------------------------------------------*/ +-->begin +package com.oracle.truffle.dsl.processor.expression; + +import java.util.*; +import java.io.*; +import java.nio.charset.*; + +import com.oracle.truffle.dsl.processor.expression.DSLExpression.*; + +// Checkstyle: stop +// @formatter:off +class Parser { +-->constants + static final boolean _T = true; + static final boolean _x = false; + static final int minErrDist = 2; + + public Token t; // last recognized token + public Token la; // lookahead token + int errDist = minErrDist; + + public final Scanner scanner; + public final Errors errors; + + -->declarations + public Parser(InputStream input) { + this.scanner = new Scanner(input); + errors = new Errors(); + } + + void SynErr(int n) { + if (errDist >= minErrDist) + errors.SynErr(la.line, la.col, n); + errDist = 0; + } + + public void SemErr(String msg) { + if (errDist >= minErrDist) + errors.SemErr(t.line, t.col, msg); + errDist = 0; + } + + void Get() { + for (;;) { + t = la; + la = scanner.Scan(); + if (la.kind <= maxT) { + ++errDist; + break; + } +-->pragmas + la = t; + } + } + + void Expect(int n) { + if (la.kind == n) + Get(); + else { + SynErr(n); + } + } + + boolean StartOf(int s) { + return set[s][la.kind]; + } + + void ExpectWeak(int n, int follow) { + if (la.kind == n) + Get(); + else { + SynErr(n); + while (!StartOf(follow)) + Get(); + } + } + + boolean WeakSeparator(int n, int syFol, int repFol) { + int kind = la.kind; + if (kind == n) { + Get(); + return true; + } else if (StartOf(repFol)) + return false; + else { + SynErr(n); + while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) { + Get(); + kind = la.kind; + } + return StartOf(syFol); + } + } + +-->productions + + private DSLExpression parseImpl() { + la = new Token(); + la.val = ""; + Get(); + DSLExpression result = -->parseRoot + return result; + } + + private static final boolean[][] set = { +-->initialization + }; + + public static DSLExpression parse(InputStream input) { + Parser parser = new Parser(input); + DSLExpression result = parser.parseImpl(); + if (parser.errors.errors.size() > 0) { + StringBuilder msg = new StringBuilder(); + for (String error : parser.errors.errors) { + msg.append(error).append("\n"); + } + throw new InvalidExpressionException(msg.toString()); + } + return result; + } + + public static DSLExpression parse(String s) { + return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))); + } +} // end Parser + +class Errors { + + protected final List errors = new ArrayList<>(); + public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text + + protected void printMsg(int line, int column, String msg) { + StringBuffer b = new StringBuffer(errMsgFormat); + int pos = b.indexOf("{0}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, line); + } + pos = b.indexOf("{1}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, column); + } + pos = b.indexOf("{2}"); + if (pos >= 0) + b.replace(pos, pos + 3, msg); + errors.add(b.toString()); + } + + public void SynErr(int line, int col, int n) { + String s; + switch (n) {-->errors + default: + s = "error " + n; + break; + } + printMsg(line, col, s); + } + + public void SemErr(int line, int col, String s) { + printMsg(line, col, s); + } + + public void SemErr(String s) { + errors.add(s); + } + + public void Warning(int line, int col, String s) { + printMsg(line, col, s); + } + + public void Warning(String s) { + errors.add(s); + } +} // Errors + +class FatalError extends RuntimeException { + + public static final long serialVersionUID = 1L; + + public FatalError(String s) { + super(s); + } +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,346 @@ +/* + * 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. + */ + +// The content of this file is automatically generated. DO NOT EDIT. + +package com.oracle.truffle.dsl.processor.expression; + +import java.util.*; +import java.io.*; +import java.nio.charset.*; + +import com.oracle.truffle.dsl.processor.expression.DSLExpression.*; + +// Checkstyle: stop +// @formatter:off +class Parser { + public static final int _EOF = 0; + public static final int _identifier = 1; + public static final int _numericLiteral = 2; + public static final int maxT = 15; + + static final boolean _T = true; + static final boolean _x = false; + static final int minErrDist = 2; + + public Token t; // last recognized token + public Token la; // lookahead token + int errDist = minErrDist; + + public final Scanner scanner; + public final Errors errors; + + + public Parser(InputStream input) { + this.scanner = new Scanner(input); + errors = new Errors(); + } + + void SynErr(int n) { + if (errDist >= minErrDist) + errors.SynErr(la.line, la.col, n); + errDist = 0; + } + + public void SemErr(String msg) { + if (errDist >= minErrDist) + errors.SemErr(t.line, t.col, msg); + errDist = 0; + } + + void Get() { + for (;;) { + t = la; + la = scanner.Scan(); + if (la.kind <= maxT) { + ++errDist; + break; + } + + la = t; + } + } + + void Expect(int n) { + if (la.kind == n) + Get(); + else { + SynErr(n); + } + } + + boolean StartOf(int s) { + return set[s][la.kind]; + } + + void ExpectWeak(int n, int follow) { + if (la.kind == n) + Get(); + else { + SynErr(n); + while (!StartOf(follow)) + Get(); + } + } + + boolean WeakSeparator(int n, int syFol, int repFol) { + int kind = la.kind; + if (kind == n) { + Get(); + return true; + } else if (StartOf(repFol)) + return false; + else { + SynErr(n); + while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) { + Get(); + kind = la.kind; + } + return StartOf(syFol); + } + } + + DSLExpression Expression() { + DSLExpression result; + result = LogicFactor(); + return result; + } + + DSLExpression LogicFactor() { + DSLExpression result; + result = ComparisonFactor(); + if (la.kind == 3) { + Get(); + Token op = t; + DSLExpression right = ComparisonFactor(); + result = new Binary(op.val, result, right); + } + return result; + } + + DSLExpression ComparisonFactor() { + DSLExpression result; + result = NegateFactor(); + if (StartOf(1)) { + switch (la.kind) { + case 4: { + Get(); + break; + } + case 5: { + Get(); + break; + } + case 6: { + Get(); + break; + } + case 7: { + Get(); + break; + } + case 8: { + Get(); + break; + } + case 9: { + Get(); + break; + } + } + Token op = t; + DSLExpression right = NegateFactor(); + result = new Binary(op.val, result, right); + } + return result; + } + + DSLExpression NegateFactor() { + DSLExpression result; + boolean negated = false; + if (la.kind == 10) { + Get(); + negated = true; + } + result = Factor(); + result = negated ? new Negate(result) : result; + return result; + } + + DSLExpression Factor() { + DSLExpression result; + result = null; + if (la.kind == 1) { + result = MemberExpression(result); + } else if (la.kind == 2) { + Get(); + result = new IntLiteral(t.val); + } else if (la.kind == 11) { + Get(); + result = Expression(); + Expect(12); + } else SynErr(16); + return result; + } + + DSLExpression MemberExpression(DSLExpression receiver) { + DSLExpression result; + result = null; + Expect(1); + Variable variable = new Variable(receiver, t.val); + result = variable; + if (la.kind == 11) { + Get(); + List parameters = new ArrayList<>(); + DSLExpression parameter; + if (StartOf(2)) { + parameter = Expression(); + parameters.add(parameter); + while (la.kind == 13) { + Get(); + parameter = Expression(); + parameters.add(parameter); + } + } + Expect(12); + result = new Call(variable.getReceiver(), variable.getName(), parameters); + } + if (la.kind == 14) { + Get(); + result = MemberExpression(result); + } + return result; + } + + + + private DSLExpression parseImpl() { + la = new Token(); + la.val = ""; + Get(); + DSLExpression result = Expression(); + Expect(0); + + return result; + } + + private static final boolean[][] set = { + {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x}, + {_x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x}, + {_x,_T,_T,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x} + + }; + + public static DSLExpression parse(InputStream input) { + Parser parser = new Parser(input); + DSLExpression result = parser.parseImpl(); + if (parser.errors.errors.size() > 0) { + StringBuilder msg = new StringBuilder(); + for (String error : parser.errors.errors) { + msg.append(error).append("\n"); + } + throw new InvalidExpressionException(msg.toString()); + } + return result; + } + + public static DSLExpression parse(String s) { + return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))); + } +} // end Parser + +class Errors { + + protected final List errors = new ArrayList<>(); + public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text + + protected void printMsg(int line, int column, String msg) { + StringBuffer b = new StringBuffer(errMsgFormat); + int pos = b.indexOf("{0}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, line); + } + pos = b.indexOf("{1}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, column); + } + pos = b.indexOf("{2}"); + if (pos >= 0) + b.replace(pos, pos + 3, msg); + errors.add(b.toString()); + } + + public void SynErr(int line, int col, int n) { + String s; + switch (n) { + case 0: s = "EOF expected"; break; + case 1: s = "identifier expected"; break; + case 2: s = "numericLiteral expected"; break; + case 3: s = "\"||\" expected"; break; + case 4: s = "\"<\" expected"; break; + case 5: s = "\"<=\" expected"; break; + case 6: s = "\">\" expected"; break; + case 7: s = "\">=\" expected"; break; + case 8: s = "\"==\" expected"; break; + case 9: s = "\"!=\" expected"; break; + case 10: s = "\"!\" expected"; break; + case 11: s = "\"(\" expected"; break; + case 12: s = "\")\" expected"; break; + case 13: s = "\",\" expected"; break; + case 14: s = "\".\" expected"; break; + case 15: s = "??? expected"; break; + case 16: s = "invalid Factor"; break; + default: + s = "error " + n; + break; + } + printMsg(line, col, s); + } + + public void SemErr(int line, int col, String s) { + printMsg(line, col, s); + } + + public void SemErr(String s) { + errors.add(s); + } + + public void Warning(int line, int col, String s) { + printMsg(line, col, s); + } + + public void Warning(String s) { + errors.add(s); + } +} // Errors + +class FatalError extends RuntimeException { + + public static final long serialVersionUID = 1L; + + public FatalError(String s) { + super(s); + } +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,495 @@ +/*------------------------------------------------------------------------- +Compiler Generator Coco/R, +Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +extended by M. Loeberbauer & A. Woess, Univ. of Linz +ported from C# to Java by Wolfgang Ahorner +with improvements by Pat Terry, Rhodes University + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program 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 +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As an exception, it is allowed to write an extension of Coco/R that is +used as a plugin in non-free software. + +If not otherwise stated, any source code generated by Coco/R (other than +Coco/R itself) does not fall under the GNU General Public License. +------------------------------------------------------------------------*/ +-->begin +package com.oracle.truffle.dsl.processor.expression; + +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.HashMap; + +// Checkstyle: stop +// @formatter:off +class Token { + + public int kind; // token kind + public int pos; // token position in bytes in the source text (starting at 0) + public int charPos; // token position in characters in the source text (starting at 0) + public int col; // token column (starting at 1) + public int line; // token line (starting at 1) + public String val; // token value + public Token next; // ML 2005-03-11 Peek tokens are kept in linked list +} + +// ----------------------------------------------------------------------------------- +// Buffer +// ----------------------------------------------------------------------------------- +class Buffer { + + // This Buffer supports the following cases: + // 1) seekable stream (file) + // a) whole stream in buffer + // b) part of stream in buffer + // 2) non seekable stream (network, console) + + public static final int EOF = Character.MAX_VALUE + 1; + private static final int MIN_BUFFER_LENGTH = 1024; // 1KB + private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB + private byte[] buf; // input buffer + private int bufStart; // position of first byte in buffer relative to input stream + private int bufLen; // length of buffer + private int fileLen; // length of input stream (may change if stream is no file) + private int bufPos; // current position in buffer + private RandomAccessFile file; // input stream (seekable) + private InputStream stream; // growing input stream (e.g.: console, network) + + public Buffer(InputStream s) { + stream = s; + fileLen = bufLen = bufStart = bufPos = 0; + buf = new byte[MIN_BUFFER_LENGTH]; + } + + public Buffer(String fileName) { + try { + file = new RandomAccessFile(fileName, "r"); + fileLen = (int) file.length(); + bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH); + buf = new byte[bufLen]; + bufStart = Integer.MAX_VALUE; // nothing in buffer so far + if (fileLen > 0) + setPos(0); // setup buffer to position 0 (start) + else + bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid + if (bufLen == fileLen) + Close(); + } catch (IOException e) { + throw new FatalError("Could not open file " + fileName); + } + } + + // don't use b after this call anymore + // called in UTF8Buffer constructor + protected Buffer(Buffer b) { + buf = b.buf; + bufStart = b.bufStart; + bufLen = b.bufLen; + fileLen = b.fileLen; + bufPos = b.bufPos; + file = b.file; + stream = b.stream; + // keep finalize from closing the file + b.file = null; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + Close(); + } + + protected void Close() { + if (file != null) { + try { + file.close(); + file = null; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } + } + + public int Read() { + if (bufPos < bufLen) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (getPos() < fileLen) { + setPos(getPos()); // shift buffer start to pos + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (stream != null && ReadNextStreamChunk() > 0) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else { + return EOF; + } + } + + public int Peek() { + int curPos = getPos(); + int ch = Read(); + setPos(curPos); + return ch; + } + + // beg .. begin, zero-based, inclusive, in byte + // end .. end, zero-based, exclusive, in byte + public String GetString(int beg, int end) { + int len = 0; + char[] buffer = new char[end - beg]; + int oldPos = getPos(); + setPos(beg); + while (getPos() < end) + buffer[len++] = (char) Read(); + setPos(oldPos); + return new String(buffer, 0, len); + } + + public int getPos() { + return bufPos + bufStart; + } + + public void setPos(int value) { + if (value >= fileLen && stream != null) { + // Wanted position is after buffer and the stream + // is not seek-able e.g. network or console, + // thus we have to read the stream manually till + // the wanted position is in sight. + while (value >= fileLen && ReadNextStreamChunk() > 0) { + // nothing to do... + } + } + + if (value < 0 || value > fileLen) { + throw new FatalError("buffer out of bounds access, position: " + value); + } + + if (value >= bufStart && value < bufStart + bufLen) { // already in buffer + bufPos = value - bufStart; + } else if (file != null) { // must be swapped in + try { + file.seek(value); + bufLen = file.read(buf); + bufStart = value; + bufPos = 0; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } else { + // set the position to the end of the file, Pos will return fileLen. + bufPos = fileLen - bufStart; + } + } + + // Read the next chunk of bytes from the stream, increases the buffer + // if needed and updates the fields fileLen and bufLen. + // Returns the number of bytes read. + private int ReadNextStreamChunk() { + int free = buf.length - bufLen; + if (free == 0) { + // in the case of a growing input stream + // we can neither seek in the stream, nor can we + // foresee the maximum length, thus we must adapt + // the buffer size on demand. + byte[] newBuf = new byte[bufLen * 2]; + System.arraycopy(buf, 0, newBuf, 0, bufLen); + buf = newBuf; + free = bufLen; + } + + int read; + try { + read = stream.read(buf, bufLen, free); + } catch (IOException ioex) { + throw new FatalError(ioex.getMessage()); + } + + if (read > 0) { + fileLen = bufLen = (bufLen + read); + return read; + } + // end of stream reached + return 0; + } +} + +// ----------------------------------------------------------------------------------- +// UTF8Buffer +// ----------------------------------------------------------------------------------- +class UTF8Buffer extends Buffer { + + UTF8Buffer(Buffer b) { + super(b); + } + + @Override + public int Read() { + int ch; + do { + ch = super.Read(); + // until we find a utf8 start (0xxxxxxx or 11xxxxxx) + } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF)); + if (ch < 128 || ch == EOF) { + // nothing to do, first 127 chars are the same in ascii and utf8 + // 0xxxxxxx or end of file character + } else if ((ch & 0xF0) == 0xF0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x07; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = super.Read(); + int c4 = ch & 0x3F; + ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; + } else if ((ch & 0xE0) == 0xE0) { + // 1110xxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x0F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = (((c1 << 6) | c2) << 6) | c3; + } else if ((ch & 0xC0) == 0xC0) { + // 110xxxxx 10xxxxxx + int c1 = ch & 0x1F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = (c1 << 6) | c2; + } + return ch; + } +} + +// ----------------------------------------------------------------------------------- +// StartStates -- maps characters to start states of tokens +// ----------------------------------------------------------------------------------- +class StartStates { + + private static class Elem { + + public int key, val; + public Elem next; + + public Elem(int key, int val) { + this.key = key; + this.val = val; + } + } + + private Elem[] tab = new Elem[128]; + + public void set(int key, int val) { + Elem e = new Elem(key, val); + int k = key % 128; + e.next = tab[k]; + tab[k] = e; + } + + public int state(int key) { + Elem e = tab[key % 128]; + while (e != null && e.key != key) + e = e.next; + return e == null ? 0 : e.val; + } +} + +// ----------------------------------------------------------------------------------- +// Scanner +// ----------------------------------------------------------------------------------- +@SuppressWarnings({"rawtypes"}) +public class Scanner { + + static final char EOL = '\n'; + static final int eofSym = 0; +-->declarations + + public Buffer buffer; // scanner buffer + + Token t; // current token + int ch; // current input character + int pos; // byte position of current character + int charPos; // position by unicode characters starting with 0 + int col; // column number of current character + int line; // line number of current character + int oldEols; // EOLs that appeared in a comment; + static final StartStates start; // maps initial token character to start state + static final Map literals; // maps literal strings to literal kinds + + Token tokens; // list of tokens already peeked (first token is a dummy) + Token pt; // current peek token + + char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged + int tlen; // length of current token + + static { + start = new StartStates(); + literals = new HashMap(); +-->initialization + } + + public Scanner(String fileName) { + buffer = new Buffer(fileName); + Init(); + } + + public Scanner(InputStream s) { + buffer = new Buffer(s); + Init(); + } + + void Init() { + pos = -1; + line = 1; + col = 0; + charPos = -1; + oldEols = 0; + NextCh(); + if (ch == 0xEF) { // check optional byte order mark for UTF-8 + NextCh(); + int ch1 = ch; + NextCh(); + int ch2 = ch; + if (ch1 != 0xBB || ch2 != 0xBF) { + throw new FatalError("Illegal byte order mark at start of file"); + } + buffer = new UTF8Buffer(buffer); + col = 0; + charPos = -1; + NextCh(); + } + pt = tokens = new Token(); // first token is a dummy + } + + void NextCh() { + if (oldEols > 0) { + ch = EOL; + oldEols--; + } else { + pos = buffer.getPos(); + // buffer reads unicode chars, if UTF8 has been detected + ch = buffer.Read(); + col++; + charPos++; + // replace isolated '\r' by '\n' in order to make + // eol handling uniform across Windows, Unix and Mac + if (ch == '\r' && buffer.Peek() != '\n') + ch = EOL; + if (ch == EOL) { + line++; + col = 0; + } + } +-->casing + } + + void AddCh() { + if (tlen >= tval.length) { + char[] newBuf = new char[2 * tval.length]; + System.arraycopy(tval, 0, newBuf, 0, tval.length); + tval = newBuf; + } + if (ch != Buffer.EOF) { +-->casing2 + NextCh(); + } + } + +-->comments + + void CheckLiteral() { + String val = t.val; +-->casing3 + Object kind = literals.get(val); + if (kind != null) { + t.kind = ((Integer) kind).intValue(); + } + } + + Token NextToken() { + while (ch == ' ' || +-->scan1 + ) NextCh(); +-->scan2 + int recKind = noSym; + int recEnd = pos; + t = new Token(); + t.pos = pos; + t.col = col; + t.line = line; + t.charPos = charPos; + int state = start.state(ch); + tlen = 0; + AddCh(); + + loop: for (;;) { + switch (state) { + case -1: { + t.kind = eofSym; + break loop; + } // NextCh already done + case 0: { + if (recKind != noSym) { + tlen = recEnd - t.pos; + SetScannerBehindT(); + } + t.kind = recKind; + break loop; + } // NextCh already done +-->scan3 + } + } + t.val = new String(tval, 0, tlen); + return t; + } + + private void SetScannerBehindT() { + buffer.setPos(t.pos); + NextCh(); + line = t.line; + col = t.col; + charPos = t.charPos; + for (int i = 0; i < tlen; i++) + NextCh(); + } + + // get the next token (possibly a token already seen during peeking) + public Token Scan() { + if (tokens.next == null) { + return NextToken(); + } else { + pt = tokens = tokens.next; + return tokens; + } + } + + // get the next token, ignore pragmas + public Token Peek() { + do { + if (pt.next == null) { + pt.next = NextToken(); + } + pt = pt.next; + } while (pt.kind > maxT); // skip pragmas + + return pt; + } + + // make sure that peeking starts at current scan position + public void ResetPeek() { + pt = tokens; + } + +} // end Scanner diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,557 @@ +/* + * 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. + */ + +// The content of this file is automatically generated. DO NOT EDIT. + +package com.oracle.truffle.dsl.processor.expression; + +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.HashMap; + +// Checkstyle: stop +// @formatter:off +class Token { + + public int kind; // token kind + public int pos; // token position in bytes in the source text (starting at 0) + public int charPos; // token position in characters in the source text (starting at 0) + public int col; // token column (starting at 1) + public int line; // token line (starting at 1) + public String val; // token value + public Token next; // ML 2005-03-11 Peek tokens are kept in linked list +} + +// ----------------------------------------------------------------------------------- +// Buffer +// ----------------------------------------------------------------------------------- +class Buffer { + + // This Buffer supports the following cases: + // 1) seekable stream (file) + // a) whole stream in buffer + // b) part of stream in buffer + // 2) non seekable stream (network, console) + + public static final int EOF = Character.MAX_VALUE + 1; + private static final int MIN_BUFFER_LENGTH = 1024; // 1KB + private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB + private byte[] buf; // input buffer + private int bufStart; // position of first byte in buffer relative to input stream + private int bufLen; // length of buffer + private int fileLen; // length of input stream (may change if stream is no file) + private int bufPos; // current position in buffer + private RandomAccessFile file; // input stream (seekable) + private InputStream stream; // growing input stream (e.g.: console, network) + + public Buffer(InputStream s) { + stream = s; + fileLen = bufLen = bufStart = bufPos = 0; + buf = new byte[MIN_BUFFER_LENGTH]; + } + + public Buffer(String fileName) { + try { + file = new RandomAccessFile(fileName, "r"); + fileLen = (int) file.length(); + bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH); + buf = new byte[bufLen]; + bufStart = Integer.MAX_VALUE; // nothing in buffer so far + if (fileLen > 0) + setPos(0); // setup buffer to position 0 (start) + else + bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid + if (bufLen == fileLen) + Close(); + } catch (IOException e) { + throw new FatalError("Could not open file " + fileName); + } + } + + // don't use b after this call anymore + // called in UTF8Buffer constructor + protected Buffer(Buffer b) { + buf = b.buf; + bufStart = b.bufStart; + bufLen = b.bufLen; + fileLen = b.fileLen; + bufPos = b.bufPos; + file = b.file; + stream = b.stream; + // keep finalize from closing the file + b.file = null; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + Close(); + } + + protected void Close() { + if (file != null) { + try { + file.close(); + file = null; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } + } + + public int Read() { + if (bufPos < bufLen) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (getPos() < fileLen) { + setPos(getPos()); // shift buffer start to pos + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (stream != null && ReadNextStreamChunk() > 0) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else { + return EOF; + } + } + + public int Peek() { + int curPos = getPos(); + int ch = Read(); + setPos(curPos); + return ch; + } + + // beg .. begin, zero-based, inclusive, in byte + // end .. end, zero-based, exclusive, in byte + public String GetString(int beg, int end) { + int len = 0; + char[] buffer = new char[end - beg]; + int oldPos = getPos(); + setPos(beg); + while (getPos() < end) + buffer[len++] = (char) Read(); + setPos(oldPos); + return new String(buffer, 0, len); + } + + public int getPos() { + return bufPos + bufStart; + } + + public void setPos(int value) { + if (value >= fileLen && stream != null) { + // Wanted position is after buffer and the stream + // is not seek-able e.g. network or console, + // thus we have to read the stream manually till + // the wanted position is in sight. + while (value >= fileLen && ReadNextStreamChunk() > 0) { + // nothing to do... + } + } + + if (value < 0 || value > fileLen) { + throw new FatalError("buffer out of bounds access, position: " + value); + } + + if (value >= bufStart && value < bufStart + bufLen) { // already in buffer + bufPos = value - bufStart; + } else if (file != null) { // must be swapped in + try { + file.seek(value); + bufLen = file.read(buf); + bufStart = value; + bufPos = 0; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } else { + // set the position to the end of the file, Pos will return fileLen. + bufPos = fileLen - bufStart; + } + } + + // Read the next chunk of bytes from the stream, increases the buffer + // if needed and updates the fields fileLen and bufLen. + // Returns the number of bytes read. + private int ReadNextStreamChunk() { + int free = buf.length - bufLen; + if (free == 0) { + // in the case of a growing input stream + // we can neither seek in the stream, nor can we + // foresee the maximum length, thus we must adapt + // the buffer size on demand. + byte[] newBuf = new byte[bufLen * 2]; + System.arraycopy(buf, 0, newBuf, 0, bufLen); + buf = newBuf; + free = bufLen; + } + + int read; + try { + read = stream.read(buf, bufLen, free); + } catch (IOException ioex) { + throw new FatalError(ioex.getMessage()); + } + + if (read > 0) { + fileLen = bufLen = (bufLen + read); + return read; + } + // end of stream reached + return 0; + } +} + +// ----------------------------------------------------------------------------------- +// UTF8Buffer +// ----------------------------------------------------------------------------------- +class UTF8Buffer extends Buffer { + + UTF8Buffer(Buffer b) { + super(b); + } + + @Override + public int Read() { + int ch; + do { + ch = super.Read(); + // until we find a utf8 start (0xxxxxxx or 11xxxxxx) + } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF)); + if (ch < 128 || ch == EOF) { + // nothing to do, first 127 chars are the same in ascii and utf8 + // 0xxxxxxx or end of file character + } else if ((ch & 0xF0) == 0xF0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x07; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = super.Read(); + int c4 = ch & 0x3F; + ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; + } else if ((ch & 0xE0) == 0xE0) { + // 1110xxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x0F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = (((c1 << 6) | c2) << 6) | c3; + } else if ((ch & 0xC0) == 0xC0) { + // 110xxxxx 10xxxxxx + int c1 = ch & 0x1F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = (c1 << 6) | c2; + } + return ch; + } +} + +// ----------------------------------------------------------------------------------- +// StartStates -- maps characters to start states of tokens +// ----------------------------------------------------------------------------------- +class StartStates { + + private static class Elem { + + public int key, val; + public Elem next; + + public Elem(int key, int val) { + this.key = key; + this.val = val; + } + } + + private Elem[] tab = new Elem[128]; + + public void set(int key, int val) { + Elem e = new Elem(key, val); + int k = key % 128; + e.next = tab[k]; + tab[k] = e; + } + + public int state(int key) { + Elem e = tab[key % 128]; + while (e != null && e.key != key) + e = e.next; + return e == null ? 0 : e.val; + } +} + +// ----------------------------------------------------------------------------------- +// Scanner +// ----------------------------------------------------------------------------------- +@SuppressWarnings({"rawtypes"}) +public class Scanner { + + static final char EOL = '\n'; + static final int eofSym = 0; + static final int maxT = 15; + static final int noSym = 15; + + + public Buffer buffer; // scanner buffer + + Token t; // current token + int ch; // current input character + int pos; // byte position of current character + int charPos; // position by unicode characters starting with 0 + int col; // column number of current character + int line; // line number of current character + int oldEols; // EOLs that appeared in a comment; + static final StartStates start; // maps initial token character to start state + static final Map literals; // maps literal strings to literal kinds + + Token tokens; // list of tokens already peeked (first token is a dummy) + Token pt; // current peek token + + char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged + int tlen; // length of current token + + static { + start = new StartStates(); + literals = new HashMap(); + for (int i = 36; i <= 36; ++i) start.set(i, 1); + for (int i = 65; i <= 90; ++i) start.set(i, 1); + for (int i = 95; i <= 95; ++i) start.set(i, 1); + for (int i = 97; i <= 122; ++i) start.set(i, 1); + for (int i = 49; i <= 57; ++i) start.set(i, 2); + start.set(48, 3); + start.set(124, 4); + start.set(60, 15); + start.set(62, 16); + start.set(61, 8); + start.set(33, 17); + start.set(40, 11); + start.set(41, 12); + start.set(44, 13); + start.set(46, 14); + start.set(Buffer.EOF, -1); + + } + + public Scanner(String fileName) { + buffer = new Buffer(fileName); + Init(); + } + + public Scanner(InputStream s) { + buffer = new Buffer(s); + Init(); + } + + void Init() { + pos = -1; + line = 1; + col = 0; + charPos = -1; + oldEols = 0; + NextCh(); + if (ch == 0xEF) { // check optional byte order mark for UTF-8 + NextCh(); + int ch1 = ch; + NextCh(); + int ch2 = ch; + if (ch1 != 0xBB || ch2 != 0xBF) { + throw new FatalError("Illegal byte order mark at start of file"); + } + buffer = new UTF8Buffer(buffer); + col = 0; + charPos = -1; + NextCh(); + } + pt = tokens = new Token(); // first token is a dummy + } + + void NextCh() { + if (oldEols > 0) { + ch = EOL; + oldEols--; + } else { + pos = buffer.getPos(); + // buffer reads unicode chars, if UTF8 has been detected + ch = buffer.Read(); + col++; + charPos++; + // replace isolated '\r' by '\n' in order to make + // eol handling uniform across Windows, Unix and Mac + if (ch == '\r' && buffer.Peek() != '\n') + ch = EOL; + if (ch == EOL) { + line++; + col = 0; + } + } + + } + + void AddCh() { + if (tlen >= tval.length) { + char[] newBuf = new char[2 * tval.length]; + System.arraycopy(tval, 0, newBuf, 0, tval.length); + tval = newBuf; + } + if (ch != Buffer.EOF) { + tval[tlen++] = (char)ch; + + NextCh(); + } + } + + + + void CheckLiteral() { + String val = t.val; + + Object kind = literals.get(val); + if (kind != null) { + t.kind = ((Integer) kind).intValue(); + } + } + + Token NextToken() { + while (ch == ' ' || + false + ) NextCh(); + + int recKind = noSym; + int recEnd = pos; + t = new Token(); + t.pos = pos; + t.col = col; + t.line = line; + t.charPos = charPos; + int state = start.state(ch); + tlen = 0; + AddCh(); + + loop: for (;;) { + switch (state) { + case -1: { + t.kind = eofSym; + break loop; + } // NextCh already done + case 0: { + if (recKind != noSym) { + tlen = recEnd - t.pos; + SetScannerBehindT(); + } + t.kind = recKind; + break loop; + } // NextCh already done + case 1: + recEnd = pos; recKind = 1; + if (ch == '$' || ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} + else {t.kind = 1; break loop;} + case 2: + recEnd = pos; recKind = 2; + if (ch >= '0' && ch <= '9') {AddCh(); state = 2; break;} + else {t.kind = 2; break loop;} + case 3: + {t.kind = 2; break loop;} + case 4: + if (ch == '|') {AddCh(); state = 5; break;} + else {state = 0; break;} + case 5: + {t.kind = 3; break loop;} + case 6: + {t.kind = 5; break loop;} + case 7: + {t.kind = 7; break loop;} + case 8: + if (ch == '=') {AddCh(); state = 9; break;} + else {state = 0; break;} + case 9: + {t.kind = 8; break loop;} + case 10: + {t.kind = 9; break loop;} + case 11: + {t.kind = 11; break loop;} + case 12: + {t.kind = 12; break loop;} + case 13: + {t.kind = 13; break loop;} + case 14: + {t.kind = 14; break loop;} + case 15: + recEnd = pos; recKind = 4; + if (ch == '=') {AddCh(); state = 6; break;} + else {t.kind = 4; break loop;} + case 16: + recEnd = pos; recKind = 6; + if (ch == '=') {AddCh(); state = 7; break;} + else {t.kind = 6; break loop;} + case 17: + recEnd = pos; recKind = 10; + if (ch == '=') {AddCh(); state = 10; break;} + else {t.kind = 10; break loop;} + + } + } + t.val = new String(tval, 0, tlen); + return t; + } + + private void SetScannerBehindT() { + buffer.setPos(t.pos); + NextCh(); + line = t.line; + col = t.col; + charPos = t.charPos; + for (int i = 0; i < tlen; i++) + NextCh(); + } + + // get the next token (possibly a token already seen during peeking) + public Token Scan() { + if (tokens.next == null) { + return NextToken(); + } else { + pt = tokens = tokens.next; + return tokens; + } + } + + // get the next token, ignore pragmas + public Token Peek() { + do { + if (pt.next == null) { + pt.next = NextToken(); + } + pt = pt.next; + } while (pt.kind > maxT); // skip pragmas + + return pt; + } + + // make sure that peeking starts at current scan position + public void ResetPeek() { + pt = tokens; + } + +} // end Scanner diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,158 @@ +/* + * 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.truffle.dsl.processor.generator; + +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable; +import com.oracle.truffle.dsl.processor.java.model.*; + +public class DSLExpressionGenerator implements DSLExpressionVisitor { + + private final Map bindings; + private final CodeTree root; + private final Deque stack = new ArrayDeque<>(); + + public DSLExpressionGenerator(CodeTree root, Map bindings) { + this.bindings = bindings; + this.root = root; + } + + public void visitBinary(Binary binary) { + CodeTree right = stack.pop(); + CodeTree left = stack.pop(); + stack.push(combine(left, string(" " + binary.getOperator() + " "), right)); + } + + public void visitCall(Call call) { + ExecutableElement method = call.getResolvedMethod(); + CodeTree[] parameters = new CodeTree[method.getParameters().size()]; + for (int i = 0; i < parameters.length; i++) { + parameters[parameters.length - i - 1] = pop(); + } + + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + + if (call.getResolvedMethod().getKind() == ElementKind.CONSTRUCTOR) { + builder.startNew(call.getResolvedType()); + } else if (call.getReceiver() == null) { + if (isStatic(method)) { + builder.startStaticCall(method); + } else { + if (root != null) { + builder.tree(root).string("."); + } + builder.startCall(method.getSimpleName().toString()); + } + } else { + if (isStatic(method)) { + throw new AssertionError("Static calls must not have receivers."); + } + builder.startCall(pop(), method.getSimpleName().toString()); + } + for (CodeTree parameter : parameters) { + builder.tree(parameter); + } + builder.end(); + + push(builder.build()); + } + + public void visitIntLiteral(IntLiteral binary) { + push(string(binary.getLiteral())); + } + + public void visitNegate(Negate negate) { + push(combine(string("!"), combine(string("("), pop(), string(")")))); + } + + public void visitVariable(Variable variable) { + VariableElement resolvedVariable = variable.getResolvedVariable(); + CodeTree tree; + if (variable.getReceiver() == null) { + + if (isStatic(resolvedVariable)) { + tree = staticReference(resolvedVariable); + } else { + tree = bindings.get(variable); + boolean bound = true; + if (tree == null) { + tree = string(resolvedVariable.getSimpleName().toString()); + bound = false; + } + if (root != null && !bound) { + tree = combine(root, string("."), tree); + } + } + } else { + if (isStatic(resolvedVariable)) { + throw new AssertionError("Static variables cannot have receivers."); + } + tree = combine(pop(), string("."), string(resolvedVariable.getSimpleName().toString())); + } + push(tree); + } + + private static boolean isStatic(Element element) { + return element.getModifiers().contains(Modifier.STATIC); + } + + private static CodeTree combine(CodeTree tree1, CodeTree tree2) { + return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).end().build(); + } + + private static CodeTree combine(CodeTree tree1, CodeTree tree2, CodeTree tree3) { + return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).tree(tree3).end().build(); + } + + private static CodeTree string(String s) { + return CodeTreeBuilder.singleString(s); + } + + private static CodeTree staticReference(VariableElement var) { + return CodeTreeBuilder.createBuilder().staticReference(var.getEnclosingElement().asType(), var.getSimpleName().toString()).build(); + } + + private void push(CodeTree tree) { + stack.push(tree); + } + + private CodeTree pop() { + return stack.pop(); + } + + public static CodeTree write(DSLExpression expression, CodeTree root, Map bindings) { + DSLExpressionGenerator writer = new DSLExpressionGenerator(root, bindings); + expression.accept(writer); + return combine(string("("), writer.pop(), string(")")); + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java Sat Feb 21 19:55:33 2015 +0100 @@ -35,6 +35,7 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.dsl.internal.DSLOptions.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.model.*; import com.oracle.truffle.dsl.processor.model.*; @@ -148,4 +149,46 @@ return clazz; } + public static List findUserConstructors(TypeMirror nodeType) { + List constructors = new ArrayList<>(); + for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(nodeType).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + continue; + } + constructors.add(constructor); + } + + if (constructors.isEmpty()) { + constructors.add(new CodeExecutableElement(null, ElementUtils.getSimpleName(nodeType))); + } + + return constructors; + } + + public static boolean isCopyConstructor(ExecutableElement element) { + if (element.getParameters().size() != 1) { + return false; + } + VariableElement var = element.getParameters().get(0); + TypeElement enclosingType = ElementUtils.findNearestEnclosingType(var); + if (ElementUtils.typeEquals(var.asType(), enclosingType.asType())) { + return true; + } + List types = ElementUtils.getDirectSuperTypes(enclosingType); + for (TypeElement type : types) { + if (!(type instanceof CodeTypeElement)) { + // no copy constructors which are not generated types + return false; + } + + if (ElementUtils.typeEquals(var.asType(), type.asType())) { + return true; + } + } + return false; + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1976 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.generator; - -import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.*; -import com.oracle.truffle.dsl.processor.java.model.*; -import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror; -import com.oracle.truffle.dsl.processor.model.*; -import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; -import com.oracle.truffle.dsl.processor.parser.*; -import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard; - -class NodeBaseFactory { - - private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; - - static final String EXECUTE_CHAINED = "executeChained0"; - private static final String SPECIALIZE = "specialize0"; - private static final String DSLSHARE_REWRITE = "rewrite"; - private static final String DSLSHARE_FIND_ROOT = "findRoot"; - private static final String DSLSHARE_REWRITE_TO_POLYMORHPIC = "rewriteToPolymorphic"; - static final String EXECUTE_UNINITIALIZED = "executeUninitialized0"; - private static final String REWRITE = "rewrite0"; - private static final String CREATE_INFO = "createInfo0"; - static final String CONTAINS_FALLBACK = "containsFallback"; - - static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY"; - - static final String METADATA_FIELD_NAME = "METADATA"; - - protected final ProcessorContext context; - protected final NodeData node; - protected final SpecializationData specialization; - - public NodeBaseFactory(ProcessorContext context, NodeData node, SpecializationData specialization) { - this.context = context; - this.node = node; - this.specialization = specialization; - } - - public CodeTypeElement create() { - CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(PRIVATE, ABSTRACT), baseClassName(node), node.getNodeType()); - clazz.getImplements().add(context.getTruffleTypes().getDslNode()); - - for (NodeChildData child : node.getChildren()) { - clazz.add(createChildField(child)); - - if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { - ExecutableElement getter = (ExecutableElement) child.getAccessElement(); - CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), getter); - method.getModifiers().remove(Modifier.ABSTRACT); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn().string("this.").string(child.getName()).end(); - clazz.add(method); - } - } - - for (NodeFieldData field : node.getFields()) { - if (!field.isGenerated()) { - continue; - } - - clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName())); - if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) { - CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), field.getGetter()); - method.getModifiers().remove(Modifier.ABSTRACT); - method.createBuilder().startReturn().string("this.").string(field.getName()).end(); - clazz.add(method); - } - } - - for (String assumption : node.getAssumptions()) { - clazz.add(createAssumptionField(assumption)); - } - - createConstructors(clazz); - - SpecializationGroup rootGroup = createSpecializationGroups(node); - - if (node.needsRewrites(context)) { - if (node.isPolymorphic(context)) { - - CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0"); - var.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getTruffleTypes().getChildAnnotation())); - clazz.add(var); - - CodeExecutableElement genericCachedExecute = createCachedExecute(node.getPolymorphicSpecialization()); - clazz.add(genericCachedExecute); - - } - - for (CodeExecutableElement method : createImplicitChildrenAccessors()) { - clazz.add(method); - } - clazz.add(createInfoMessage()); - clazz.add(createMonomorphicRewrite()); - clazz.add(createCreateSpecializationMethod(rootGroup)); - } - - clazz.add(createAdoptChildren0()); - clazz.add(createGetMetadata0(true)); - clazz.add(createUpdateTypes0()); - clazz.add(createGetNext()); - - return clazz; - } - - public static List findUserConstructors(TypeMirror nodeType) { - TypeElement type = ElementUtils.fromTypeMirror(nodeType); - List constructors = new ArrayList<>(); - for (ExecutableElement constructor : ElementFilter.constructorsIn(type.getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - if (isCopyConstructor(constructor)) { - continue; - } - constructors.add(constructor); - } - - if (constructors.isEmpty()) { - CodeExecutableElement executable = new CodeExecutableElement(null, ElementUtils.getSimpleName(nodeType)); - ElementUtils.setVisibility(executable.getModifiers(), ElementUtils.getVisibility(type.getModifiers())); - constructors.add(executable); - } - - return constructors; - } - - public static boolean isCopyConstructor(ExecutableElement element) { - if (element.getParameters().size() != 1) { - return false; - } - VariableElement var = element.getParameters().get(0); - TypeElement enclosingType = ElementUtils.findNearestEnclosingType(var); - if (ElementUtils.typeEquals(var.asType(), enclosingType.asType())) { - return true; - } - List types = ElementUtils.getDirectSuperTypes(enclosingType); - for (TypeElement type : types) { - if (!(type instanceof CodeTypeElement)) { - // no copy constructors which are not generated types - return false; - } - - if (ElementUtils.typeEquals(var.asType(), type.asType())) { - return true; - } - } - return false; - } - - public SpecializationData getSpecialization() { - return specialization; - } - - private Element createGetNext() { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0"); - CodeTreeBuilder builder = method.createBuilder(); - - if (node.isPolymorphic(context)) { - builder.startReturn().string("next0").end(); - } else { - builder.returnNull(); - } - - return method; - } - - protected final CodeExecutableElement createUpdateTypes0() { - ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0"); - method.getParameters().add(new CodeVariableElement(classArray, "types")); - - if (getSpecialization().isPolymorphic()) { - CodeTreeBuilder builder = method.createBuilder(); - - int index = 0; - for (NodeExecutionData execution : getSpecialization().getNode().getChildExecutions()) { - String fieldName = polymorphicTypeName(execution); - - builder.startStatement(); - builder.string(fieldName).string(" = ").string("types[").string(String.valueOf(index)).string("]"); - builder.end(); - index++; - } - } - - return method; - } - - protected final CodeExecutableElement createGetMetadata0(boolean empty) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getDslMetadata(), "getMetadata0"); - if (empty) { - method.createBuilder().startReturn().staticReference(context.getTruffleTypes().getDslMetadata(), "NONE").end(); - } else { - method.createBuilder().startReturn().string(METADATA_FIELD_NAME).end(); - } - return method; - } - - private CodeExecutableElement createAdoptChildren0() { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0"); - method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other")); - method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext")); - CodeTreeBuilder builder = method.createBuilder(); - List executions = node.getChildExecutions(); - - if (executions.size() > 0) { - builder.startIf().string("other == null").end().startBlock(); - for (NodeExecutionData execution : executions) { - builder.startStatement().tree(createAccessChild(execution, "this")).string(" = null").end(); - } - builder.end().startElseBlock(); - - String access; - if (executions.size() > 1) { - builder.declaration(baseClassName(node), "otherCast", builder.create().cast(baseClassName(node)).string("other")); - access = "otherCast"; - } else { - assert executions.size() == 1; - access = "((" + baseClassName(node) + ") other)"; - } - for (NodeExecutionData execution : executions) { - builder.startStatement().tree(createAccessChild(execution, "this")).string(" = ").tree(createAccessChild(execution, access)).end(); - } - - builder.end(); - } - - if (getSpecialization().getNode().isPolymorphic(context)) { - builder.startIf().string("newNext == null").end().startBlock(); - builder.statement("this.next0 = null"); - builder.end().startElseBlock(); - builder.statement("this.next0 = (" + baseClassName(getSpecialization().getNode()) + ") newNext"); - builder.end(); - } - - return method; - } - - private List createImplicitChildrenAccessors() { - List> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null); - List> expectTypes = new ArrayList<>(prototype); - - for (ExecutableTypeData executableType : node.getExecutableTypes()) { - for (int i = 0; i < executableType.getEvaluatedCount(); i++) { - Parameter parameter = executableType.getSignatureParameter(i); - if (i >= expectTypes.size()) { - break; - } - Set types = expectTypes.get(i); - if (types == null) { - types = new TreeSet<>(); - expectTypes.set(i, types); - } - types.add(parameter.getTypeSystemType()); - } - } - - List methods = new ArrayList<>(); - List> visitedList = new ArrayList<>(prototype); - for (SpecializationData spec : node.getSpecializations()) { - int signatureIndex = -1; - for (Parameter param : spec.getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - signatureIndex++; - Set visitedTypeData = visitedList.get(signatureIndex); - if (visitedTypeData == null) { - visitedTypeData = new TreeSet<>(); - visitedList.set(signatureIndex, visitedTypeData); - } - - if (visitedTypeData.contains(param.getTypeSystemType())) { - continue; - } - visitedTypeData.add(param.getTypeSystemType()); - - Set expect = expectTypes.get(signatureIndex); - if (expect == null) { - expect = Collections.emptySet(); - } - - methods.addAll(createExecuteChilds(param, expect)); - } - } - return methods; - } - - private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) { - CodeTreeBuilder builder = parent.create(); - builder.staticReference(context.getTruffleTypes().getTruffleOptions(), name); - return builder.build(); - } - - private void addInternalValueParameters(CodeExecutableElement executableMethod, TemplateMethod method, boolean forceFrame, boolean disableFrame, boolean evaluated) { - if (forceFrame && !disableFrame && method.getSpecification().findParameterSpec("frame") != null) { - executableMethod.addParameter(new CodeVariableElement(context.getTruffleTypes().getFrame(), "frameValue")); - } - for (Parameter parameter : method.getParameters()) { - ParameterSpec spec = parameter.getSpecification(); - if ((disableFrame || forceFrame) && spec.getName().equals("frame")) { - continue; - } - if (spec.isLocal()) { - continue; - } - - String name = valueName(parameter); - if (evaluated && spec.isSignature()) { - name = valueNameEvaluated(parameter); - } - - executableMethod.addParameter(new CodeVariableElement(parameter.getType(), name)); - } - } - - private Element createInfoMessage() { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), context.getType(String.class), CREATE_INFO); - method.addParameter(new CodeVariableElement(context.getType(String.class), "message")); - addInternalValueParameters(method, node.getGenericSpecialization(), false, false, false); - - CodeTreeBuilder builder = method.createBuilder(); - - builder.startIf().tree(truffleBooleanOption(builder, TruffleTypes.OPTION_DETAILED_REWRITE_REASONS)).end(); - builder.startBlock(); - - builder.startStatement().string("StringBuilder builder = new StringBuilder(message)").end(); - builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end(); - - String sep = null; - for (Parameter parameter : node.getGenericSpecialization().getSignatureParameters()) { - builder.startStatement(); - builder.string("builder"); - if (sep != null) { - builder.startCall(".append").doubleQuote(sep).end(); - } - builder.startCall(".append").doubleQuote(parameter.getLocalName()).end(); - builder.startCall(".append").doubleQuote(" = ").end(); - builder.startCall(".append").string(parameter.getLocalName()).end(); - builder.end(); - - if (!ElementUtils.isPrimitive(parameter.getType())) { - builder.startIf().string(parameter.getLocalName() + " != null").end(); - builder.startBlock(); - } - builder.startStatement(); - if (ElementUtils.isPrimitive(parameter.getType())) { - builder.startCall("builder.append").doubleQuote(" (" + ElementUtils.getSimpleName(parameter.getType()) + ")").end(); - } else { - builder.startCall("builder.append").doubleQuote(" (").end(); - builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end(); - builder.startCall(".append").doubleQuote(")").end(); - } - builder.end(); - if (!ElementUtils.isPrimitive(parameter.getType())) { - builder.end(); - } - - sep = ", "; - } - - builder.startStatement().startCall("builder", "append").doubleQuote(")").end().end(); - builder.startReturn().string("builder.toString()").end(); - - builder.end(); - builder.startElseBlock(); - builder.startReturn().string("message").end(); - builder.end(); - - return method; - } - - private CodeExecutableElement createCachedExecute(SpecializationData polymorph) { - CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED); - addInternalValueParameters(cachedExecute, polymorph, true, false, false); - - ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0); - boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(context); - if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) { - sourceThrowsUnexpected = false; - } - if (sourceThrowsUnexpected) { - cachedExecute.getThrownTypes().add(context.getType(UnexpectedResultException.class)); - } - return cachedExecute; - - } - - private void createConstructors(CodeTypeElement clazz) { - List constructors = findUserConstructors(node.getNodeType()); - ExecutableElement sourceSectionConstructor = null; - if (constructors.isEmpty()) { - clazz.add(createUserConstructor(clazz, null)); - } else { - for (ExecutableElement constructor : constructors) { - clazz.add(createUserConstructor(clazz, constructor)); - if (NodeParser.isSourceSectionConstructor(context, constructor)) { - sourceSectionConstructor = constructor; - } - } - } - if (node.needsRewrites(context)) { - ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType()); - clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor)); - } - } - - private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) { - CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - - if (superConstructor != null) { - ElementUtils.setVisibility(method.getModifiers(), ElementUtils.getVisibility(superConstructor.getModifiers())); - for (VariableElement param : superConstructor.getParameters()) { - method.getParameters().add(CodeVariableElement.clone(param)); - } - builder.startStatement().startSuperCall(); - for (VariableElement param : superConstructor.getParameters()) { - builder.string(param.getSimpleName().toString()); - } - builder.end().end(); - } - - for (VariableElement var : type.getFields()) { - if (var.getModifiers().contains(STATIC)) { - continue; - } - NodeChildData child = node.findChild(var.getSimpleName().toString()); - - if (child != null) { - method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); - } else { - method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); - } - - builder.startStatement(); - String fieldName = var.getSimpleName().toString(); - - CodeTree init = createStaticCast(builder, child, fieldName); - - builder.string("this.").string(fieldName).string(" = ").tree(init); - builder.end(); - } - return method; - } - - private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) { - NodeData parentNode = getSpecialization().getNode(); - if (child != null) { - CreateCastData createCast = parentNode.findCast(child.getName()); - if (createCast != null) { - return createTemplateMethodCall(parent, null, parentNode.getGenericSpecialization(), createCast, null, fieldName); - } - } - return CodeTreeBuilder.singleString(fieldName); - } - - private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) { - CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); - CodeTreeBuilder builder = method.createBuilder(); - method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); - - if (superConstructor != null) { - builder.startStatement().startSuperCall().string("copy").end().end(); - } else if (sourceSectionConstructor != null) { - builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end(); - } - - for (VariableElement var : type.getFields()) { - if (var.getModifiers().contains(STATIC) || !var.getModifiers().contains(FINAL)) { - continue; - } - final String varName = var.getSimpleName().toString(); - final TypeMirror varType = var.asType(); - if (ElementUtils.isAssignable(varType, context.getTruffleTypes().getNodeArray())) { - CodeTree size = builder.create().string("copy.", varName, ".length").build(); - builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end(); - } else { - builder.startStatement().string("this.", varName, " = copy.", varName).end(); - } - } - - return method; - } - - private CodeVariableElement createAssumptionField(String assumption) { - CodeVariableElement var = new CodeVariableElement(context.getTruffleTypes().getAssumption(), assumption); - var.getModifiers().add(Modifier.FINAL); - return var; - } - - private CodeVariableElement createChildField(NodeChildData child) { - TypeMirror type = child.getNodeType(); - CodeVariableElement var = new CodeVariableElement(type, child.getName()); - var.getModifiers().add(Modifier.PROTECTED); - - DeclaredType annotationType; - if (child.getCardinality() == Cardinality.MANY) { - var.getModifiers().add(Modifier.FINAL); - annotationType = context.getTruffleTypes().getChildrenAnnotation(); - } else { - annotationType = context.getTruffleTypes().getChildAnnotation(); - } - - var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); - return var; - } - - private static SpecializationGroup createSpecializationGroups(final NodeData node) { - List specializations = node.getSpecializations(); - List filteredSpecializations = new ArrayList<>(); - for (SpecializationData current : specializations) { - if (current.isUninitialized() || current.isPolymorphic() || !current.isReachable()) { - continue; - } - filteredSpecializations.add(current); - } - - return SpecializationGroup.create(filteredSpecializations); - } - - protected final CodeExecutableElement createExecuteUninitialized() { - SpecializationData generic = node.getGenericSpecialization(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED); - addInternalValueParameters(method, generic, true, false, false); - CodeTreeBuilder builder = method.createBuilder(); - - boolean needsFrame = node.isFrameUsedByAnyGuard(); - CodeTreeBuilder createSpecializationCall = builder.create(); - createSpecializationCall.startCall(SPECIALIZE); - addInternalValueParameterNames(createSpecializationCall, generic, generic, null, needsFrame, !needsFrame, null); - createSpecializationCall.end(); - builder.declaration(baseClassName(node), "newNode", createSpecializationCall); - - if (generic.isReachable()) { - builder.startIf().string("newNode == null").end().startBlock(); - - builder.startIf().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "inInterpreter").end().end().startBlock(); - builder.statement("containsFallback = true"); - builder.end(); - builder.tree(createGenericInvoke(builder, generic, generic)); - builder.end(); - builder.startElseBlock(); - builder.tree(createDeoptimize(builder)); - builder.end(); - } - - builder.startReturn(); - builder.startStaticCall(context.getTruffleTypes().getDslShare(), "rewriteUninitialized").string("this").string("newNode").end(); - builder.string(".").startCall(EXECUTE_CHAINED); - addInternalValueParameterNames(builder, generic, generic, null, true, false, null); - builder.end(); - builder.end(); - - if (generic.isReachable()) { - builder.end(); - } - - return method; - } - - private static CodeTree createInfoCall(CodeTreeBuilder parent, SpecializationData specialization, String reason) { - CodeTreeBuilder builder = parent.create(); - builder.startCall(CREATE_INFO).string(reason); - addInternalValueParameterNames(builder, specialization, specialization, null, false, false, null); - builder.end(); - return builder.build(); - } - - private CodeExecutableElement createMonomorphicRewrite() { - SpecializationData generic = node.getGenericSpecialization(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE); - addInternalValueParameters(method, generic, true, false, false); - method.addParameter(new CodeVariableElement(context.getType(String.class), "reason")); - - boolean needsFrame = node.isFrameUsedByAnyGuard(); - CodeTreeBuilder builder = method.createBuilder(); - - builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end(); - String baseClassName = baseClassName(getSpecialization().getNode()); - CodeTreeBuilder createSpecializationCall = builder.create(); - createSpecializationCall.startCall(SPECIALIZE); - addInternalValueParameterNames(createSpecializationCall, generic, generic, null, needsFrame, !needsFrame, null); - createSpecializationCall.end(); - builder.declaration(baseClassName, "newNode", createSpecializationCall); - - builder.startIf().string("newNode == null").end().startBlock(); - builder.startStatement(); - String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization()); - builder.string("newNode = ").startNew(uninitializedName).string("this").end(); - builder.end(); - if (node.isFallbackReachable()) { - builder.startStatement().string("((", uninitializedName, ") newNode).containsFallback = true").end(); - } - builder.end(); - - builder.startStatement(); - builder.type(context.getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason")); - builder.end(); - - builder.declaration(baseClassName, "returnNode", - builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().build()); - builder.startIf().string("returnNode == null").end().startBlock(); - builder.tree(createRewritePolymorphic(builder, "this")); - builder.end(); - - builder.startReturn(); - builder.startCall("returnNode", EXECUTE_CHAINED); - addInternalValueParameterNames(builder, node.getGenericSpecialization(), node.getGenericSpecialization(), null, true, false, null); - builder.end(); - builder.end(); - - return method; - } - - private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, String currentNode) { - String polyClassName = nodePolymorphicClassName(node); - CodeTreeBuilder builder = parent.create(); - - builder.startStatement().string("returnNode = "); - builder.startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE_TO_POLYMORHPIC); - builder.string("this"); - builder.tree(builder.create().startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string(currentNode).end().build()); - builder.tree(builder.create().startNew(polyClassName).string(currentNode).end().build()); - builder.startGroup().cast(baseClassName(node)).startCall("copy").end().end(); - builder.string("newNode"); - builder.string("message"); - builder.end(); - builder.end(); - - return builder.build(); - } - - private CodeExecutableElement createCreateSpecializationMethod(SpecializationGroup group) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), baseClassName(node)), - SPECIALIZE); - - final boolean needsFrame = node.isFrameUsedByAnyGuard(); - - if (!needsFrame) { - method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getTruffleTypes().getTruffleBoundary())); - } - - addInternalValueParameters(method, node.getGenericSpecialization(), needsFrame, !needsFrame, false); - final CodeTreeBuilder builder = method.createBuilder(); - builder.tree(createExecuteTree(builder, node.getGenericSpecialization(), group, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createCreateSpecializationMethodBody0(builder, current, needsFrame); - } - }, null, false, true, false, true)); - - emitUnreachableSpecializations(builder, node); - - return method; - } - - private CodeTree createCreateSpecializationMethodBody0(CodeTreeBuilder parent, SpecializationData current, boolean useDeoptimize) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (current.isFallback()) { - builder.startReturn().nullLiteral().end(); - } else { - String className = nodeSpecializationClassName(current); - if (!current.getExcludedBy().isEmpty()) { - builder.startIf().string("!").startStaticCall(context.getTruffleTypes().getDslShare(), "isExcluded"); - builder.string("this").string(nodeSpecializationClassName(current), ".", METADATA_FIELD_NAME).end().end(); - builder.startBlock(); - } - - if (current.getNode().getGenericSpecialization().isReachable() && useDeoptimize) { - builder.tree(createDeoptimize(builder)); - } - builder.startReturn(); - builder.cast(baseClassName(getSpecialization().getNode())); - builder.startGroup().startCall(className, NodeFactoryFactory.FACTORY_METHOD_NAME).string("this"); - for (Parameter param : current.getSignatureParameters()) { - NodeChildData child = param.getSpecification().getExecution().getChild(); - List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (types.size() > 1) { - builder.string(implicitTypeName(param)); - } - } - builder.end().end(); - builder.end(); - - if (!current.getExcludedBy().isEmpty()) { - builder.end(); - } - } - return builder.build(); - - } - - private static void emitUnreachableSpecializations(final CodeTreeBuilder builder, NodeData node) { - for (SpecializationData current : node.getSpecializations()) { - if (current.isReachable()) { - continue; - } - builder.string("// unreachable ").string(current.getId()).newLine(); - } - } - - protected CodeTree createExecuteTree(CodeTreeBuilder outerParent, final SpecializationData source, final SpecializationGroup group, final CodeBlock guardedblock, - final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) { - return guard(outerParent, source, group, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder parent, Integer ifCount) { - CodeTreeBuilder builder = parent.create(); - - if (group.getSpecialization() != null) { - builder.tree(guardedblock.create(builder, group.getSpecialization())); - - assert group.getChildren().isEmpty() : "missed a specialization"; - - } else { - for (SpecializationGroup childGroup : group.getChildren()) { - builder.tree(createExecuteTree(builder, source, childGroup, guardedblock, null, false, emitAssumptions, typedCasts, castForGuardsOnly)); - } - } - - return builder.build(); - } - }, elseBlock, forceElse, emitAssumptions, typedCasts, castForGuardsOnly); - } - - private CodeTree guard(CodeTreeBuilder parent, SpecializationData source, SpecializationGroup group, CodeBlock bodyBlock, CodeTree elseBlock, boolean forceElse, boolean emitAssumptions, - boolean typedCasts, boolean castForGuardsOnly) { - CodeTreeBuilder builder = parent.create(); - - int ifCount = emitGuards(builder, source, group, emitAssumptions, typedCasts, castForGuardsOnly); - - if (isReachableGroup(group, ifCount)) { - builder.tree(bodyBlock.create(builder, ifCount)); - } - - builder.end(ifCount); - - if (elseBlock != null) { - if (ifCount > 0 || forceElse) { - builder.tree(elseBlock); - } - } - - return builder.build(); - } - - private static boolean isReachableGroup(SpecializationGroup group, int ifCount) { - if (ifCount != 0) { - return true; - } - SpecializationGroup previous = group.getPreviousGroup(); - if (previous == null || previous.findElseConnectableGuards().isEmpty()) { - return true; - } - - /* - * Hacky else case. In this case the specialization is not reachable due to previous else - * branch. This is only true if the minimum state is not checked. - */ - if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && - (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { - return false; - } - - return true; - } - - private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) { - CodeTreeBuilder guardsBuilder = builder.create(); - CodeTreeBuilder castBuilder = builder.create(); - CodeTreeBuilder guardsCastBuilder = builder.create(); - - String guardsAnd = ""; - String guardsCastAnd = ""; - - if (emitAssumptions) { - for (String assumption : group.getAssumptions()) { - guardsBuilder.string(guardsAnd); - guardsBuilder.string("this"); - guardsBuilder.string(".").string(assumption).string(".isValid()"); - guardsAnd = " && "; - } - } - - for (TypeGuard typeGuard : group.getTypeGuards()) { - Parameter valueParam = source.getSignatureParameter(typeGuard.getSignatureIndex()); - - if (valueParam == null) { - /* - * If used inside a execute evaluated method then the value param may not exist. In - * that case we assume that the value is executed generic or of the current - * specialization. - */ - if (group.getSpecialization() != null) { - valueParam = group.getSpecialization().getSignatureParameter(typeGuard.getSignatureIndex()); - } else { - valueParam = node.getGenericSpecialization().getSignatureParameter(typeGuard.getSignatureIndex()); - } - } - - NodeExecutionData execution = valueParam.getSpecification().getExecution(); - CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts); - if (implicitGuard != null) { - guardsBuilder.string(guardsAnd); - guardsBuilder.tree(implicitGuard); - guardsAnd = " && "; - } - - CodeTree implicitGetType = null; - if (castForGuardsOnly) { - implicitGetType = createGetImplicitType(builder, execution, valueParam, typeGuard.getType()); - } - - boolean performCast = true; - if (castForGuardsOnly) { - // if cast for guards we just cast if the type guard is used inside a guard. - performCast = group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard); - } - - if (performCast) { - CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), typedCasts); - if (cast != null) { - castBuilder.tree(cast); - } - } - if (implicitGetType != null) { - castBuilder.tree(implicitGetType); - } - } - List elseGuards = group.findElseConnectableGuards(); - - for (GuardExpression guard : group.getGuards()) { - if (elseGuards.contains(guard)) { - continue; - } - - if (needsTypeGuard(source, group, guard)) { - guardsCastBuilder.tree(createMethodGuard(builder, guardsCastAnd, source, guard)); - guardsCastAnd = " && "; - } else { - guardsBuilder.tree(createMethodGuard(builder, guardsAnd, source, guard)); - guardsAnd = " && "; - } - } - - int ifCount = startGuardIf(builder, guardsBuilder.build(), 0, elseGuards); - builder.tree(castBuilder.build()); - ifCount = startGuardIf(builder, guardsCastBuilder.build(), ifCount, elseGuards); - return ifCount; - } - - private static int startGuardIf(CodeTreeBuilder builder, CodeTree condition, int ifCount, List elseGuard) { - int newIfCount = ifCount; - - if (!condition.isEmpty()) { - if (ifCount == 0 && !elseGuard.isEmpty()) { - builder.startElseIf(); - } else { - builder.startIf(); - } - builder.tree(condition); - builder.end().startBlock(); - newIfCount++; - } else if (ifCount == 0 && !elseGuard.isEmpty()) { - builder.startElseBlock(); - newIfCount++; - } - return newIfCount; - } - - private static boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) { - for (Parameter parameter : guard.getResolvedGuard().getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - - int signatureIndex = source.getNode().getChildExecutions().indexOf(parameter.getSpecification().getExecution()); - if (signatureIndex == -1) { - continue; - } - - TypeGuard typeGuard = group.findTypeGuard(signatureIndex); - if (typeGuard != null) { - TypeData requiredType = typeGuard.getType(); - - Parameter sourceParameter = source.findParameter(parameter.getLocalName()); - if (sourceParameter == null) { - sourceParameter = source.getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); - } - - if (ElementUtils.needsCastTo(sourceParameter.getType(), requiredType.getPrimitiveType())) { - return true; - } - } - } - return false; - } - - private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - TypeData sourceType = source.getTypeSystemType(); - - if (!sourceType.needsCastTo(targetType)) { - return null; - } - - builder.startGroup(); - - if (execution.isShortCircuit()) { - Parameter shortCircuit = source.getPreviousParameter(); - assert shortCircuit != null; - builder.string("("); - builder.string("!").string(valueName(shortCircuit)); - builder.string(" || "); - } - - List types = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType); - if (types.size() > 1) { - String castTypeName = null; - if (typedCasts) { - castTypeName = implicitTypeName(source); - } - CodeTree check; - if (castTypeName == null) { - check = TypeSystemCodeGenerator.implicitCheck(targetType, CodeTreeBuilder.singleString(valueName(source)), null); - } else { - check = TypeSystemCodeGenerator.implicitCheck(targetType, CodeTreeBuilder.singleString(valueName(source)), castTypeName); - } - builder.tree(check); - } else { - builder.tree(TypeSystemCodeGenerator.check(targetType, CodeTreeBuilder.singleString(valueName(source)))); - } - - if (execution.isShortCircuit()) { - builder.string(")"); - } - - builder.end(); // group - - return builder.build(); - } - - // TODO merge redundancies with #createTypeGuard - private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) { - TypeData sourceType = source.getTypeSystemType(); - - if (!sourceType.needsCastTo(targetType)) { - return null; - } - - CodeTree condition = null; - if (execution.isShortCircuit()) { - Parameter shortCircuit = source.getPreviousParameter(); - assert shortCircuit != null; - condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); - } - - CodeTree cast; - List types = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType); - if (types.size() > 1) { - String castTypeName = null; - if (typedCasts) { - castTypeName = implicitTypeName(source); - } - cast = TypeSystemCodeGenerator.implicitCast(targetType, CodeTreeBuilder.singleString(valueName(source)), castTypeName); - } else { - cast = TypeSystemCodeGenerator.cast(targetType, valueName(source)); - } - - CodeTreeBuilder builder = parent.create(); - builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast)); - - return builder.build(); - } - - private CodeTree createGetImplicitType(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType) { - CodeTree condition = null; - if (execution.isShortCircuit()) { - Parameter shortCircuit = source.getPreviousParameter(); - assert shortCircuit != null; - condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); - } - - CodeTreeBuilder builder = parent.create(); - List types = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType); - if (types.size() > 1) { - CodeTree castType = TypeSystemCodeGenerator.implicitType(targetType, CodeTreeBuilder.singleString(valueName(source))); - builder.tree(createLazyAssignment(builder, implicitTypeName(source), context.getType(Class.class), condition, castType)); - } - return builder.build(); - } - - private static CodeTree createMethodGuard(CodeTreeBuilder parent, String prefix, SpecializationData source, GuardExpression guard) { - CodeTreeBuilder builder = parent.create(); - builder.string(prefix); - if (guard.isNegated()) { - builder.string("!"); - } - builder.tree(createTemplateMethodCall(builder, null, source, guard.getResolvedGuard(), null)); - return builder.build(); - } - - protected CodeTree createGenericInvoke(CodeTreeBuilder parent, SpecializationData source, SpecializationData current) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - if (current.getMethod() == null) { - emitEncounteredSynthetic(builder, getSpecialization().getNode(), current); - } else { - builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end(); - } - - return encloseThrowsWithFallThrough(parent, current, builder.build()); - } - - private CodeTree encloseThrowsWithFallThrough(CodeTreeBuilder parent, SpecializationData current, CodeTree tree) { - if (current.getExceptions().isEmpty()) { - return tree; - } - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - builder.startTryBlock(); - builder.tree(tree); - for (SpecializationThrowsData exception : current.getExceptions()) { - builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx"); - builder.tree(createDeoptimize(builder)); - builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), null, - "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass()))); - } - builder.end(); - - return builder.build(); - } - - protected CodeTree createCastingExecute(CodeTreeBuilder parent, ExecutableTypeData executable, ExecutableTypeData castExecutable) { - TypeData type = executable.getType(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - TypeData primaryType = castExecutable.getType(); - - boolean needsTry = castExecutable.hasUnexpectedValue(context); - boolean returnVoid = type.isVoid(); - - List executeParameters = new ArrayList<>(); - for (Parameter sourceParameter : executable.getSignatureParameters()) { - Parameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); - if (targetParameter != null) { - executeParameters.add(targetParameter); - } - } - - // execute names are enforced no cast - String[] executeParameterNames = new String[executeParameters.size()]; - for (int i = 0; i < executeParameterNames.length; i++) { - executeParameterNames[i] = valueName(executeParameters.get(i)); - } - - builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null)); - boolean hasUnexpected = executable.hasUnexpectedValue(context); - - CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames); - if (needsTry) { - if (!returnVoid) { - builder.declaration(primaryType.getPrimitiveType(), "value"); - } - builder.startTryBlock(); - - if (returnVoid) { - builder.statement(primaryExecuteCall); - } else { - builder.startStatement(); - builder.string("value = "); - builder.tree(primaryExecuteCall); - builder.end(); - } - - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); - if (returnVoid) { - builder.string("// ignore").newLine(); - } else { - builder.startReturn(); - builder.tree(createExpectExecutableType(specialization.getNode().getTypeSystem().getGenericTypeData(), hasUnexpected, executable.getType(), - CodeTreeBuilder.singleString("ex.getResult()"))); - builder.end(); - } - builder.end(); - - if (!returnVoid) { - builder.startReturn(); - builder.tree(createExpectExecutableType(castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), CodeTreeBuilder.singleString("value"))); - builder.end(); - } - } else { - if (returnVoid) { - builder.statement(primaryExecuteCall); - } else { - builder.startReturn(); - builder.tree(createExpectExecutableType(castExecutable.getReturnType().getTypeSystemType(), hasUnexpected, executable.getType(), primaryExecuteCall)); - builder.end(); - } - } - - return builder.build(); - } - - private static CodeTree createExpectExecutableType(TypeData sourceType, boolean hasUnexpected, TypeData exepctedType, CodeTree value) { - return createCastType(sourceType, exepctedType, hasUnexpected, value); - } - - protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData currentSpecialization, List targetParameters, - Parameter unexpectedParameter) { - CodeTreeBuilder builder = parent.create(); - for (Parameter targetParameter : targetParameters) { - if (!targetParameter.getSpecification().isSignature()) { - continue; - } - NodeExecutionData execution = targetParameter.getSpecification().getExecution(); - CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter); - CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, currentSpecialization, sourceExecutable, targetParameter, execution.isShortCircuit(), - unexpectedParameter); - CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, currentSpecialization, targetParameter, unexpectedParameter); - - if (shortCircuitTree == executionExpressions) { - if (containsNewLine(executionExpressions)) { - builder.declaration(targetParameter.getType(), valueName(targetParameter)); - builder.tree(shortCircuitTree); - } else { - builder.startStatement().type(targetParameter.getType()).string(" ").tree(shortCircuitTree).end(); - } - } else { - builder.tree(shortCircuitTree); - } - - } - return builder.build(); - } - - private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) { - ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(type); - if (targetExecutable == null) { - targetExecutable = execution.getChild().findAnyGenericExecutableType(context); - } - return targetExecutable; - } - - private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter targetParameter, Parameter unexpectedParameter) { - if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { - List possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter); - if (possiblePolymorphicTypes.size() > 1) { - CodeTreeBuilder builder = parent.create(); - - boolean elseIf = false; - for (TypeData possiblePolymoprhicType : possiblePolymorphicTypes) { - if (possiblePolymoprhicType.isGeneric()) { - continue; - } - elseIf = builder.startIf(elseIf); - - Parameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); - TypeData sourceType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; - builder.string(polymorphicTypeName(targetParameter.getSpecification().getExecution())).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType()); - builder.end().startBlock(); - builder.startStatement(); - builder.tree(createExecuteChildExpression(parent, execution, sourceType, new Parameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null)); - builder.end(); - builder.end(); - } - - builder.startElseBlock(); - builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end(); - builder.end(); - - return builder.build(); - } - } - return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter); - } - - protected static final List getImplicitTypeParameters(SpecializationData model) { - List parameter = new ArrayList<>(); - for (Parameter param : model.getSignatureParameters()) { - NodeChildData child = param.getSpecification().getExecution().getChild(); - List types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (types.size() > 1) { - parameter.add(param); - } - } - return parameter; - } - - private List lookupPolymorphicTargetTypes(Parameter param) { - Set possiblePolymorphicTypes = new HashSet<>(); - for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) { - if (!otherSpecialization.isSpecialized()) { - continue; - } - Parameter otherParameter = otherSpecialization.findParameter(param.getLocalName()); - if (otherParameter != null) { - possiblePolymorphicTypes.add(otherParameter.getTypeSystemType()); - } - } - List types = new ArrayList<>(possiblePolymorphicTypes); - Collections.sort(types); - return types; - } - - private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter param, Parameter unexpectedParameter) { - CodeTreeBuilder builder = parent.create(); - Parameter sourceParameter = sourceExecutable.findParameter(param.getLocalName()); - String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null); - if (childExecuteName != null) { - builder.string(valueName(param)); - builder.string(" = "); - builder.startCall(childExecuteName); - - for (Parameter parameters : sourceExecutable.getParameters()) { - if (parameters.getSpecification().isSignature()) { - continue; - } - builder.string(parameters.getLocalName()); - } - - if (sourceParameter != null) { - builder.string(valueNameEvaluated(sourceParameter)); - } - - builder.string(implicitTypeName(param)); - - builder.end(); - } else { - List sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; - if (sourceTypes.size() > 1) { - builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType)); - } else { - builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null)); - } - } - return builder.build(); - } - - private static String createExecuteChildMethodName(Parameter param, boolean expect) { - NodeExecutionData execution = param.getSpecification().getExecution(); - NodeChildData child = execution.getChild(); - if (child.getExecuteWith().size() > 0) { - return null; - } - List sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (sourceTypes.size() <= 1) { - return null; - } - String prefix = expect ? "expect" : "execute"; - String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : ""; - return prefix + ElementUtils.firstLetterUpperCase(child.getName()) + ElementUtils.firstLetterUpperCase(ElementUtils.getTypeId(param.getType())) + suffix; - } - - private List createExecuteChilds(Parameter param, Set expectTypes) { - CodeExecutableElement executeMethod = createExecuteChild(param, null); - if (executeMethod == null) { - return Collections.emptyList(); - } - List childs = new ArrayList<>(); - childs.add(executeMethod); - - for (TypeData expectType : expectTypes) { - CodeExecutableElement method = createExecuteChild(param, expectType); - if (method != null) { - childs.add(method); - } - } - return childs; - } - - private CodeExecutableElement createExecuteChild(Parameter param, TypeData expectType) { - String childExecuteName = createExecuteChildMethodName(param, expectType != null); - if (childExecuteName == null) { - return null; - } - - CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName); - method.getThrownTypes().add(context.getTruffleTypes().getUnexpectedValueException()); - method.addParameter(new CodeVariableElement(context.getTruffleTypes().getFrame(), "frameValue")); - if (expectType != null) { - method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param))); - } - method.addParameter(new CodeVariableElement(context.getType(Class.class), implicitTypeName(param))); - - CodeTreeBuilder builder = method.createBuilder(); - builder.declaration(param.getType(), valueName(param)); - builder.tree(createExecuteChildImplicitExpressions(builder, param, expectType)); - builder.startReturn().string(valueName(param)).end(); - - return method; - } - - private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, Parameter targetParameter, TypeData expectType) { - CodeTreeBuilder builder = parent.create(); - NodeExecutionData execution = targetParameter.getSpecification().getExecution(); - List sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType()); - boolean elseIf = false; - int index = 0; - for (TypeData sourceType : sourceTypes) { - if (index < sourceTypes.size() - 1) { - elseIf = builder.startIf(elseIf); - builder.string(implicitTypeName(targetParameter)).string(" == ").typeLiteral(sourceType.getPrimitiveType()); - builder.end(); - builder.startBlock(); - } else { - builder.startElseBlock(); - } - - ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(sourceType); - if (implictExecutableTypeData == null) { - /* - * For children with executeWith.size() > 0 an executable type may not exist so use - * the generic executable type which is guaranteed to exist. An expect call is - * inserted automatically by #createExecuteExpression. - */ - implictExecutableTypeData = execution.getChild().getNodeData().findAnyGenericExecutableType(context, execution.getChild().getExecuteWith().size()); - } - - ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType()); - CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast); - builder.statement(execute); - builder.end(); - index++; - } - return builder.build(); - } - - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, Parameter targetParameter, Parameter unexpectedParameter, - ImplicitCastData cast) { - // assignments: targetType <- castTargetType <- castSourceType <- sourceType - TypeData sourceType = sourceParameterType; - TypeData targetType = targetParameter.getTypeSystemType(); - TypeData castSourceType = targetType; - TypeData castTargetType = targetType; - - if (cast != null) { - castSourceType = cast.getSourceType(); - castTargetType = cast.getTargetType(); - } - - CodeTree expression; - if (sourceType == null) { - ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType); - expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter); - sourceType = targetExecutable.getType(); - } else { - expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)); - } - - // target = expectTargetType(implicitCast(expectCastSourceType(source))) - expression = createExpectType(sourceType, castSourceType, expression); - expression = createImplicitCast(cast, expression); - expression = createExpectType(castTargetType, targetType, expression); - - CodeTreeBuilder builder = parent.create(); - builder.string(valueName(targetParameter)); - builder.string(" = "); - builder.tree(expression); - return builder.build(); - } - - private static CodeTree createImplicitCast(ImplicitCastData cast, CodeTree expression) { - if (cast == null) { - return expression; - } - return TypeSystemCodeGenerator.invokeImplicitCast(cast, expression); - } - - private boolean containsNewLine(CodeTree tree) { - if (tree.getCodeKind() == CodeTreeKind.NEW_LINE) { - return true; - } - - List enclosing = tree.getEnclosedElements(); - if (enclosing != null) { - for (CodeTree codeTree : enclosing) { - if (containsNewLine(codeTree)) { - return true; - } - } - } - return false; - } - - private boolean hasUnexpected(Parameter sourceParameter, Parameter targetParameter, Parameter unexpectedParameter) { - NodeExecutionData execution = targetParameter.getSpecification().getExecution(); - - if (getSpecialization().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) { - // check for other polymorphic types - List polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter); - if (polymorphicTargetTypes.size() > 1) { - for (TypeData polymorphicTargetType : polymorphicTargetTypes) { - if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) { - return true; - } - } - } - } - - if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) { - return true; - } - return false; - } - - private boolean hasUnexpectedType(NodeExecutionData execution, Parameter sourceParameter, TypeData targetType) { - List implicitSourceTypes = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType); - - for (TypeData implicitSourceType : implicitSourceTypes) { - TypeData sourceType; - ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType); - if (sourceParameter != null) { - sourceType = sourceParameter.getTypeSystemType(); - } else { - if (targetExecutable.hasUnexpectedValue(context)) { - return true; - } - sourceType = targetExecutable.getType(); - } - - ImplicitCastData cast = getSpecialization().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType); - if (cast != null) { - if (cast.getSourceType().needsCastTo(targetType)) { - return true; - } - } - - if (sourceType.needsCastTo(targetType)) { - return true; - } - } - return false; - } - - private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData currentSpecialization, ExecutableTypeData currentExecutable, Parameter param, - boolean shortCircuit, Parameter unexpectedParameter) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - Parameter sourceParameter = currentExecutable.findParameter(param.getLocalName()); - boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter); - if (!unexpected) { - return body; - } - - if (!shortCircuit) { - builder.declaration(param.getType(), valueName(param)); - } - builder.startTryBlock(); - - if (containsNewLine(body)) { - builder.tree(body); - } else { - builder.statement(body); - } - - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); - SpecializationData generic = currentSpecialization.getNode().getGenericSpecialization(); - Parameter genericParameter = generic.findParameter(param.getLocalName()); - - List genericParameters = generic.getParametersAfter(genericParameter); - builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter)); - if (currentSpecialization.isPolymorphic()) { - builder.tree(createReturnOptimizeTypes(builder, currentExecutable, currentSpecialization, param)); - } else { - builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), param, "Expected " + param.getLocalName() + " instanceof " + - ElementUtils.getSimpleName(param.getType()))); - } - builder.end(); // catch block - - return builder.build(); - } - - private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData currentSpecialization, Parameter param) { - SpecializationData polymorphic = node.getPolymorphicSpecialization(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(context.getType(Object.class)).end(); - - builder.startReturn(); - - CodeTreeBuilder execute = new CodeTreeBuilder(builder); - execute.startCall("next0", EXECUTE_CHAINED); - addInternalValueParameterNames(execute, currentSpecialization, polymorphic, param.getLocalName(), true, false, null); - execute.end(); - - TypeData sourceType = polymorphic.getReturnType().getTypeSystemType(); - - builder.tree(createExpectExecutableType(sourceType, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), execute.build())); - - builder.end(); - return builder.build(); - } - - private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, Parameter unexpectedParameter) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (targetExecution != null) { - builder.tree(createAccessChild(targetExecution, null)); - builder.string("."); - } - - builder.startCall(targetExecutable.getMethodName()); - - // TODO this should be merged with #createTemplateMethodCall - int index = 0; - for (Parameter parameter : targetExecutable.getParameters()) { - - if (!parameter.getSpecification().isSignature()) { - builder.string(parameter.getLocalName()); - } else { - - if (index < targetExecution.getChild().getExecuteWith().size()) { - NodeChildData child = targetExecution.getChild().getExecuteWith().get(index); - - ParameterSpec spec = getSpecialization().getSpecification().findParameterSpec(child.getName()); - List specializationParams = getSpecialization().findParameters(spec); - - if (specializationParams.isEmpty()) { - builder.defaultValue(parameter.getType()); - continue; - } - - Parameter specializationParam = specializationParams.get(0); - - TypeData targetType = parameter.getTypeSystemType(); - TypeData sourceType = specializationParam.getTypeSystemType(); - String localName = specializationParam.getLocalName(); - - if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) { - localName = "ex.getResult()"; - sourceType = getSpecialization().getNode().getTypeSystem().getGenericTypeData(); - } - - CodeTree value = CodeTreeBuilder.singleString(localName); - - if (sourceType.needsCastTo(targetType)) { - value = TypeSystemCodeGenerator.cast(targetType, value); - } - builder.tree(value); - } else { - builder.defaultValue(parameter.getType()); - } - index++; - } - } - - builder.end(); - - return builder.build(); - } - - private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData currentSpecialization, Parameter parameter, Parameter exceptionParam) { - NodeExecutionData execution = parameter.getSpecification().getExecution(); - if (execution == null || !execution.isShortCircuit()) { - return body; - } - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - Parameter shortCircuitParam = currentSpecialization.getPreviousParam(parameter); - builder.tree(createShortCircuitValue(builder, currentSpecialization, execution, shortCircuitParam, exceptionParam)); - builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); - builder.startIf().string(shortCircuitParam.getLocalName()).end(); - builder.startBlock(); - - if (containsNewLine(body)) { - builder.tree(body); - } else { - builder.statement(body); - } - builder.end(); - - return builder.build(); - } - - private static CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, Parameter shortCircuitParam, Parameter exceptionParam) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - int shortCircuitIndex = 0; - for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) { - if (otherExectuion.isShortCircuit()) { - if (otherExectuion == execution) { - break; - } - shortCircuitIndex++; - } - } - - builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); - ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); - builder.end(); // statement - - return builder.build(); - } - - protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, Parameter exceptionParam, String reason) { - SpecializationData generic = node.getGenericSpecialization(); - CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); - specializeCall.startCall(REWRITE); - addInternalValueParameterNames(specializeCall, generic, node.getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, false, null); - specializeCall.doubleQuote(reason); - specializeCall.end().end(); - - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - builder.startReturn(); - builder.tree(createExpectExecutableType(generic.getReturnType().getTypeSystemType(), hasUnexpected, returnType, specializeCall.build())); - builder.end(); - - return builder.build(); - } - - static String valueNameEvaluated(Parameter targetParameter) { - return valueName(targetParameter) + "Evaluated"; - } - - static String implicitTypeName(Parameter param) { - return param.getLocalName() + "ImplicitType"; - } - - static String polymorphicTypeName(NodeExecutionData param) { - return param.getName() + "PolymorphicType"; - } - - static String valueName(Parameter param) { - return param.getLocalName(); - } - - private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) { - String reference = thisReference; - if (reference == null) { - reference = "this"; - } - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - Element accessElement = targetExecution.getChild().getAccessElement(); - if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { - builder.string(reference).string(".").string(targetExecution.getChild().getName()); - } else if (accessElement.getKind() == ElementKind.FIELD) { - builder.string(reference).string(".").string(accessElement.getSimpleName().toString()); - } else { - throw new AssertionError(); - } - if (targetExecution.isIndexed()) { - builder.string("[" + targetExecution.getIndex() + "]"); - } - return builder.build(); - } - - private static String castValueName(Parameter parameter) { - return valueName(parameter) + "Cast"; - } - - static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean disableFrame, - Map customNames) { - if (forceFrame && !disableFrame && specialization.getSpecification().findParameterSpec("frame") != null) { - builder.string("frameValue"); - } - for (Parameter parameter : specialization.getParameters()) { - ParameterSpec spec = parameter.getSpecification(); - if ((disableFrame || forceFrame) && spec.getName().equals("frame")) { - continue; - } - - if (parameter.getSpecification().isLocal()) { - continue; - } - - Parameter sourceParameter = source.findParameter(parameter.getLocalName()); - - if (customNames != null && customNames.containsKey(parameter.getLocalName())) { - builder.string(customNames.get(parameter.getLocalName())); - } else if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { - builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); - } else if (sourceParameter != null) { - builder.string(valueName(sourceParameter, parameter)); - } else { - builder.string(valueName(parameter)); - } - } - } - - private static String valueName(Parameter sourceParameter, Parameter targetParameter) { - if (!sourceParameter.getSpecification().isSignature()) { - return valueName(targetParameter); - } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { - if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) { - return castValueName(targetParameter); - } - } - return valueName(targetParameter); - } - - static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, - String... customSignatureValueNames) { - CodeTreeBuilder builder = parent.create(); - - boolean castedValues = sourceMethod != targetMethod; - - builder.startGroup(); - ExecutableElement method = targetMethod.getMethod(); - if (method == null) { - throw new UnsupportedOperationException(); - } - TypeElement targetClass = ElementUtils.findNearestEnclosingType(method.getEnclosingElement()); - NodeData node = (NodeData) targetMethod.getTemplate(); - - if (target == null) { - boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); - if (accessible) { - if (builder.findMethod().getModifiers().contains(STATIC)) { - if (method.getModifiers().contains(STATIC)) { - builder.type(targetClass.asType()); - } else { - builder.string(THIS_NODE_LOCAL_VAR_NAME); - } - } else { - if (targetMethod instanceof ExecutableTypeData) { - builder.string("this"); - } else { - builder.string("super"); - } - } - } else { - if (method.getModifiers().contains(STATIC)) { - builder.type(targetClass.asType()); - } else { - Parameter firstParameter = null; - for (Parameter searchParameter : targetMethod.getParameters()) { - if (searchParameter.getSpecification().isSignature()) { - firstParameter = searchParameter; - break; - } - } - if (firstParameter == null) { - throw new AssertionError(); - } - - Parameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName()); - - if (castedValues && sourceParameter != null) { - builder.string(valueName(sourceParameter, firstParameter)); - } else { - builder.string(valueName(firstParameter)); - } - } - } - builder.string("."); - } else { - builder.tree(target); - } - builder.startCall(method.getSimpleName().toString()); - - int signatureIndex = 0; - - for (Parameter targetParameter : targetMethod.getParameters()) { - Parameter valueParameter = null; - if (sourceMethod != null) { - valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); - } - if (valueParameter == null) { - valueParameter = targetParameter; - } - TypeMirror targetType = targetParameter.getType(); - TypeMirror valueType = null; - if (valueParameter != null) { - valueType = valueParameter.getType(); - } - - if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) { - builder.string(customSignatureValueNames[signatureIndex]); - signatureIndex++; - } else if (targetParameter.getSpecification().isLocal()) { - builder.startGroup(); - if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { - builder.string(THIS_NODE_LOCAL_VAR_NAME).string("."); - } else { - builder.string("this."); - } - builder.string(targetParameter.getSpecification().getName()); - builder.end(); - } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { - builder.cast(targetParameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); - } else if (!ElementUtils.needsCastTo(valueType, targetType)) { - builder.startGroup(); - builder.string(valueName(targetParameter)); - builder.end(); - } else { - builder.string(castValueName(targetParameter)); - } - } - - builder.end().end(); - - return builder.build(); - } - - public static String baseClassName(NodeData node) { - String nodeid = resolveNodeId(node); - String name = ElementUtils.firstLetterUpperCase(nodeid); - name += "NodeGen"; - return name; - } - - /** - *
        -     * variant1 $condition != null
        -     *
        -     * $type $name = defaultValue($type);
        -     * if ($condition) {
        -     *     $name = $value;
        -     * }
        -     *
        -     * variant2 $condition != null
        -     * $type $name = $value;
        -     * 
        - * - * . - */ - private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (condition == null) { - builder.declaration(type, name, value); - } else { - builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).build()); - - builder.startIf().tree(condition).end(); - builder.startBlock(); - builder.startStatement(); - builder.string(name); - builder.string(" = "); - builder.tree(value); - builder.end(); // statement - builder.end(); // block - } - return builder.build(); - } - - void emitEncounteredSynthetic(CodeTreeBuilder builder, NodeData model, TemplateMethod current) { - CodeTreeBuilder nodes = builder.create(); - CodeTreeBuilder arguments = builder.create(); - nodes.startCommaGroup(); - arguments.startCommaGroup(); - boolean empty = true; - for (Parameter parameter : current.getParameters()) { - NodeExecutionData executionData = parameter.getSpecification().getExecution(); - if (executionData != null) { - if (executionData.isShortCircuit()) { - nodes.nullLiteral(); - arguments.string(valueName(parameter.getPreviousParameter())); - } - nodes.tree(createAccessChild(executionData, "rootNode")); - arguments.string(valueName(parameter)); - empty = false; - } - } - nodes.end(); - arguments.end(); - builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end(); - - builder.declaration(baseClassName(model), "rootNode", builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_FIND_ROOT).string("this").end()); - builder.startThrow().startNew(context.getType(UnsupportedSpecializationException.class)); - builder.string("rootNode"); - builder.startNewArray(context.getTruffleTypes().getNodeArray(), null); - builder.tree(nodes.build()); - builder.end(); - if (!empty) { - builder.tree(arguments.build()); - } - builder.end().end(); - } - - private static ExecutableElement findCopyConstructor(TypeMirror type) { - for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(type).getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - if (isCopyConstructor(constructor)) { - return constructor; - } - } - - return null; - } - - static String nodeSpecializationClassName(SpecializationData specialization) { - String nodeid = resolveNodeId(specialization.getNode()); - String name = ElementUtils.firstLetterUpperCase(nodeid); - name += ElementUtils.firstLetterUpperCase(specialization.getId()); - name += "Node"; - return name; - } - - static String nodePolymorphicClassName(NodeData node) { - return ElementUtils.firstLetterUpperCase(resolveNodeId(node)) + "PolymorphicNode"; - } - - private static String resolveNodeId(NodeData node) { - String nodeid = node.getNodeId(); - if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { - nodeid = nodeid.substring(0, nodeid.length() - 4); - } - return nodeid; - } - - private static CodeTree createCastType(TypeData sourceType, TypeData targetType, boolean expect, CodeTree value) { - if (targetType == null) { - return value; - } else if (sourceType != null && !sourceType.needsCastTo(targetType)) { - return value; - } - - if (expect) { - return TypeSystemCodeGenerator.expect(targetType, value); - } else { - return TypeSystemCodeGenerator.cast(targetType, value); - } - } - - private static CodeTree createExpectType(TypeData sourceType, TypeData targetType, CodeTree expression) { - return createCastType(sourceType, targetType, true, expression); - } - - static CodeTree createDeoptimize(CodeTreeBuilder parent) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - builder.startStatement(); - builder.startStaticCall(ProcessorContext.getInstance().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end(); - builder.end(); - return builder.build(); - } - - private TypeMirror getUnexpectedValueException() { - return context.getTruffleTypes().getUnexpectedValueException(); - } - - interface CodeBlock { - - CodeTree create(CodeTreeBuilder parent, T value); - - } - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Sat Feb 21 19:55:33 2015 +0100 @@ -122,38 +122,14 @@ } private static String getAccessorClassName(NodeData node) { - return node.isGenerateFactory() ? NodeFactoryFactory.factoryClassName(node) : NodeBaseFactory.baseClassName(node); + return node.isGenerateFactory() ? NodeFactoryFactory.factoryClassName(node) : NodeGenFactory.nodeTypeName(node); } private static List generateNodes(ProcessorContext context, NodeData node) { if (!node.needsFactory()) { return Collections.emptyList(); } - if (node.getTypeSystem().getOptions().useNewLayout()) { - return Arrays.asList(new NodeGenFactory(context, node).create()); - } else { - return generateNodesOld(context, node); - } - } - - private static List generateNodesOld(ProcessorContext context, NodeData node) { - List nodeTypes = new ArrayList<>(); - SpecializationData generic = node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization(); - CodeTypeElement baseNode = new NodeBaseFactory(context, node, generic).create(); - nodeTypes.add(baseNode); - - for (SpecializationData specialization : node.getSpecializations()) { - if (!specialization.isReachable() || specialization.isFallback()) { - continue; - } - if (specialization.isPolymorphic() && node.isPolymorphic(context)) { - nodeTypes.add(new PolymorphicNodeFactory(context, node, specialization, baseNode).create()); - continue; - } - - nodeTypes.add(new SpecializedNodeFactory(context, node, specialization, baseNode).create()); - } - return nodeTypes; + return Arrays.asList(new NodeGenFactory(context, node).create()); } private static ExecutableElement createGetFactories(ProcessorContext context, NodeData node) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java Sat Feb 21 19:55:33 2015 +0100 @@ -31,7 +31,6 @@ import javax.lang.model.type.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.dsl.internal.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.model.*; @@ -40,20 +39,16 @@ class NodeFactoryFactory { - static final String FACTORY_METHOD_NAME = "create0"; + static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY"; private final ProcessorContext context; private final NodeData node; - private final TypeSystemData typeSystem; - private final DSLOptions options; private final CodeTypeElement createdFactoryElement; public NodeFactoryFactory(ProcessorContext context, NodeData node, CodeTypeElement createdClass) { this.context = context; this.node = node; this.createdFactoryElement = createdClass; - this.typeSystem = node.getTypeSystem(); - this.options = typeSystem.getOptions(); } public static String factoryClassName(NodeData node) { @@ -94,7 +89,7 @@ // execution signature builder.startGroup(); if (node.getChildExecutions().isEmpty()) { - builder.staticReference(context.getTruffleTypes().getDslMetadata(), NodeBaseFactory.EMPTY_CLASS_ARRAY); + builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); } else { builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null); for (NodeExecutionData execution : node.getChildExecutions()) { @@ -107,11 +102,11 @@ // node signatures builder.startGroup(); builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null); - List constructors = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType()); + List constructors = GeneratorUtils.findUserConstructors(createdFactoryElement.asType()); for (ExecutableElement constructor : constructors) { builder.startGroup(); if (constructor.getParameters().isEmpty()) { - builder.staticReference(context.getTruffleTypes().getDslMetadata(), NodeBaseFactory.EMPTY_CLASS_ARRAY); + builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); } else { builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null); for (VariableElement var : constructor.getParameters()) { @@ -135,7 +130,7 @@ method.addParameter(arguments); CodeTreeBuilder builder = method.createBuilder(); - List signatures = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType()); + List signatures = GeneratorUtils.findUserConstructors(createdFactoryElement.asType()); boolean ifStarted = false; for (ExecutableElement element : signatures) { @@ -230,7 +225,7 @@ } public void createFactoryMethods(CodeTypeElement clazz) { - List constructors = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType()); + List constructors = GeneratorUtils.findUserConstructors(createdFactoryElement.asType()); for (ExecutableElement constructor : constructors) { clazz.add(createCreateMethod(constructor)); if (constructor instanceof CodeExecutableElement) { @@ -252,11 +247,7 @@ if (node.getSpecializations().isEmpty()) { body.nullLiteral(); } else { - if (options.useNewLayout()) { - body.startNew(NodeGenFactory.nodeType(node)); - } else { - body.startCall(NodeBaseFactory.nodeSpecializationClassName(node.getSpecializations().get(0)), FACTORY_METHOD_NAME); - } + body.startNew(NodeGenFactory.nodeType(node)); for (VariableElement var : method.getParameters()) { body.string(var.getSimpleName().toString()); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Sat Feb 21 19:55:33 2015 +0100 @@ -32,7 +32,6 @@ import javax.lang.model.type.*; import javax.lang.model.util.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.*; @@ -42,18 +41,22 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; +import com.oracle.truffle.api.nodes.Node.Children; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror; import com.oracle.truffle.dsl.processor.model.*; import com.oracle.truffle.dsl.processor.parser.*; import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard; public class NodeGenFactory { - private static final String FRAME_VALUE = "frameValue"; - + private static final String FRAME_VALUE = TemplateMethod.FRAME_NAME; private static final String NAME_SUFFIX = "_"; + private static final String NODE_SUFFIX = "NodeGen"; private final ProcessorContext context; private final NodeData node; @@ -70,11 +73,10 @@ this.genericType = typeSystem.getGenericTypeData(); this.options = typeSystem.getOptions(); this.singleSpecializable = isSingleSpecializableImpl(); - this.varArgsThreshold = calculateVarArgsThresHold(); - + this.varArgsThreshold = calculateVarArgsThreshold(); } - private int calculateVarArgsThresHold() { + private int calculateVarArgsThreshold() { TypeMirror specialization = context.getType(SpecializationNode.class); TypeElement specializationType = fromTypeMirror(specialization); @@ -88,7 +90,11 @@ } public static String nodeTypeName(NodeData node) { - return resolveNodeId(node) + "NodeGen"; + return resolveNodeId(node) + NODE_SUFFIX; + } + + private static String assumptionName(AssumptionExpression assumption) { + return assumption.getId() + NAME_SUFFIX; } private static String resolveNodeId(NodeData node) { @@ -153,18 +159,10 @@ } } - private static String assumptionName(String assumption) { - return assumption + "_"; - } - public CodeTypeElement create() { CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(FINAL), nodeTypeName(node), node.getTemplateType().asType()); ElementUtils.setVisibility(clazz.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers())); - for (String assumption : node.getAssumptions()) { - clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getType(Assumption.class), assumptionName(assumption))); - } - for (NodeChildData child : node.getChildren()) { clazz.addOptional(createAccessChildMethod(child)); } @@ -183,7 +181,7 @@ } } - for (ExecutableElement superConstructor : NodeBaseFactory.findUserConstructors(node.getTemplateType().asType())) { + for (ExecutableElement superConstructor : GeneratorUtils.findUserConstructors(node.getTemplateType().asType())) { clazz.add(createNodeConstructor(clazz, superConstructor)); } @@ -215,6 +213,8 @@ } clazz.add(createGetCostMethod()); + avoidFindbugsProblems(clazz); + if (singleSpecializable) { if (node.needsRewrites(context)) { clazz.add(createUnsupportedMethod()); @@ -238,9 +238,31 @@ return clazz; } + private void avoidFindbugsProblems(CodeTypeElement clazz) { + TypeElement type = context.getEnvironment().getElementUtils().getTypeElement("edu.umd.cs.findbugs.annotations.SuppressFBWarnings"); + if (type == null) { + return; + } + boolean foundComparison = false; + outer: for (SpecializationData specialization : node.getSpecializations()) { + for (GuardExpression guard : specialization.getGuards()) { + if (guard.getExpression().containsComparisons()) { + foundComparison = true; + break outer; + } + } + } + + if (foundComparison) { + CodeAnnotationMirror annotation = new CodeAnnotationMirror((DeclaredType) type.asType()); + annotation.setElementValue(annotation.findExecutableElement("value"), new CodeAnnotationValue("SA_LOCAL_SELF_COMPARISON")); + clazz.addAnnotationMirror(annotation); + } + } + private Element createUnsupportedMethod() { LocalContext locals = LocalContext.load(this); - CodeExecutableElement method = locals.createMethod(modifiers(PRIVATE), getType(UnsupportedSpecializationException.class), "unsupported"); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED), getType(UnsupportedSpecializationException.class), "unsupported"); CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); @@ -332,7 +354,7 @@ List generateSpecializations = new ArrayList<>(); generateSpecializations.add(node.getUninitializedSpecialization()); - if (needsPolymorphic(reachableSpecializations)) { + if (needsPolymorphic()) { generateSpecializations.add(node.getPolymorphicSpecialization()); } generateSpecializations.addAll(reachableSpecializations); @@ -348,6 +370,26 @@ return node.getUninitializedSpecialization(); } + private boolean needsPolymorphic() { + List reachableSpecializations = getReachableSpecializations(); + if (reachableSpecializations.size() != 1) { + return true; + } + + SpecializationData specialization = reachableSpecializations.get(0); + for (Parameter parameter : specialization.getSignatureParameters()) { + TypeData type = parameter.getTypeSystemType(); + if (type != null && type.hasImplicitSourceTypes()) { + return true; + } + } + if (specialization.hasMultipleInstances()) { + return true; + } + return false; + + } + // create specialization private CodeTypeElement createBaseSpecialization() { @@ -490,7 +532,8 @@ } private Element createMergeMethod(SpecializationData specialization) { - if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic()) { + boolean cacheBoundGuard = specialization.hasMultipleInstances(); + if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic() && !cacheBoundGuard) { return null; } TypeMirror specializationNodeType = getType(SpecializationNode.class); @@ -511,7 +554,11 @@ builder.statement("removeSame(\"Contained by " + containedSpecialization.createReferenceName() + "\")"); builder.end(); } - builder.statement("return super.merge(newNode)"); + if (cacheBoundGuard) { + builder.statement("return super.mergeNoSame(newNode)"); + } else { + builder.statement("return super.merge(newNode)"); + } } return executable; @@ -553,21 +600,6 @@ return executable; } - private boolean needsPolymorphic(List reachableSpecializations) { - if (reachableSpecializations.size() > 1) { - return true; - } - if (options.implicitCastOptimization().isDuplicateTail()) { - SpecializationData specialization = reachableSpecializations.get(0); - for (Parameter parameter : specialization.getSignatureParameters()) { - if (parameter.getTypeSystemType().hasImplicitSourceTypes()) { - return true; - } - } - } - return false; - } - private Element createCreateFallback(Map generatedSpecializationClasses) { SpecializationData fallback = node.getGenericSpecialization(); if (fallback == null) { @@ -612,7 +644,7 @@ if (generatedType == null) { throw new AssertionError("No generated type for " + specialization); } - return createSlowPathExecute(specialization, locals); + return createSlowPathExecute(specialization, values); } public boolean isFastPath() { @@ -622,7 +654,7 @@ builder.tree(execution); - if (hasFallthrough(group, genericType, locals, false)) { + if (hasFallthrough(group, genericType, locals, false, null)) { builder.returnNull(); } return method; @@ -711,8 +743,6 @@ return evaluatedCount; } - // create specialization - private Element createUnsupported() { SpecializationData fallback = node.getGenericSpecialization(); if (fallback == null || optimizeFallback(fallback) || fallback.getMethod() == null) { @@ -736,12 +766,25 @@ if (reachableSpecializations.size() != 1) { return false; } - for (Parameter parameter : reachableSpecializations.get(0).getSignatureParameters()) { + + SpecializationData specialization = reachableSpecializations.get(0); + + for (Parameter parameter : specialization.getSignatureParameters()) { TypeData type = parameter.getTypeSystemType(); if (type != null && type.hasImplicitSourceTypes()) { return false; } } + + if (!specialization.getAssumptionExpressions().isEmpty()) { + return false; + } + + if (specialization.getCaches().size() > 0) { + // TODO chumer: caches do not yet support single specialization. + // it could be worthwhile to explore if this is possible + return false; + } return true; } @@ -810,7 +853,7 @@ if (wrappedExecutableType != null) { builder.startReturn().tree(callTemplateMethod(null, wrappedExecutableType, locals)).end(); } else { - builder.tree(createFastPathExecute(builder, specialization, execType.getType(), locals)); + builder.tree(createFastPath(builder, specialization, execType.getType(), locals)); } } else { // create acceptAndExecute @@ -968,7 +1011,8 @@ continue; } } - builder.string(parameter.getLocalName()); + + builder.defaultValue(parameter.getType()); } builder.end(); return builder.build(); @@ -1012,9 +1056,46 @@ if (specialization.isFallback()) { return builder.returnNull().build(); } + if (node.isFrameUsedByAnyGuard()) { builder.tree(createTransferToInterpreterAndInvalidate()); } + + // caches unbound to guards are invoked after all guards + for (CacheExpression cache : specialization.getCaches()) { + if (!specialization.isCacheBoundByGuard(cache)) { + initializeCache(builder, specialization, cache, currentValues); + } + } + boolean hasAssumptions = !specialization.getAssumptionExpressions().isEmpty(); + if (hasAssumptions) { + + for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { + CodeTree assumptions = DSLExpressionGenerator.write(assumption.getExpression(), accessParent(null), + castBoundTypes(bindExpressionValues(assumption.getExpression(), specialization, currentValues))); + String name = assumptionName(assumption); + // needs specialization index for assumption to make unique + String varName = name + specialization.getIndex(); + TypeMirror type = assumption.getExpression().getResolvedType(); + builder.declaration(type, varName, assumptions); + currentValues.set(name, new LocalVariable(null, type, varName, null)); + } + + builder.startIf(); + String sep = ""; + for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { + LocalVariable assumptionVar = currentValues.get(assumptionName(assumption)); + if (assumptionVar == null) { + throw new AssertionError("assumption var not resolved"); + } + builder.string(sep); + builder.startCall("isValid").tree(assumptionVar.createReference()).end(); + sep = " && "; + } + builder.end(); + builder.startBlock(); + } + for (SpecializationData otherSpeciailzation : node.getSpecializations()) { if (otherSpeciailzation == specialization) { continue; @@ -1027,7 +1108,29 @@ } } - builder.startReturn().tree(createCallCreateMethod(specialization, null, currentValues)).end(); + CodeTree create = createCallCreateMethod(specialization, null, currentValues); + + if (specialization.hasMultipleInstances()) { + builder.declaration(getType(SpecializationNode.class), "s", create); + DSLExpression limitExpression = specialization.getLimitExpression(); + CodeTree limitExpressionTree; + if (limitExpression == null) { + limitExpressionTree = CodeTreeBuilder.singleString("3"); + } else { + limitExpressionTree = DSLExpressionGenerator.write(limitExpression, accessParent(null), // + castBoundTypes(bindExpressionValues(limitExpression, specialization, currentValues))); + } + + builder.startIf().string("countSame(s) < ").tree(limitExpressionTree).end().startBlock(); + builder.statement("return s"); + builder.end(); + } else { + builder.startReturn().tree(create).end(); + } + + if (hasAssumptions) { + builder.end(); + } if (mayBeExcluded(specialization)) { CodeTreeBuilder checkHasSeenBuilder = builder.create(); @@ -1039,7 +1142,7 @@ return builder.build(); } - private static boolean hasFallthrough(SpecializationGroup group, TypeData forType, LocalContext currentValues, boolean fastPath) { + private boolean hasFallthrough(SpecializationGroup group, TypeData forType, LocalContext currentValues, boolean fastPath, List ignoreGuards) { for (TypeGuard guard : group.getTypeGuards()) { if (currentValues.getValue(guard.getSignatureIndex()) == null) { // not evaluated @@ -1051,22 +1154,44 @@ } } - List expressions = new ArrayList<>(group.getGuards()); - expressions.removeAll(group.findElseConnectableGuards()); - if (!expressions.isEmpty()) { + List guards = new ArrayList<>(group.getGuards()); + List elseConnectable = group.findElseConnectableGuards(); + guards.removeAll(elseConnectable); + if (ignoreGuards != null) { + guards.removeAll(ignoreGuards); + } + SpecializationData specialization = group.getSpecialization(); + if (specialization != null && fastPath) { + for (ListIterator iterator = guards.listIterator(); iterator.hasNext();) { + GuardExpression guard = iterator.next(); + if (!specialization.isDynamicParameterBound(guard.getExpression())) { + iterator.remove(); + } + } + } + + if (!guards.isEmpty()) { return true; } - if ((!fastPath || forType.isGeneric()) && !group.getAssumptions().isEmpty()) { + if (!fastPath && specialization != null && !specialization.getAssumptionExpressions().isEmpty()) { + return true; + } + + if (!fastPath && specialization != null && mayBeExcluded(specialization)) { return true; } - if (!fastPath && group.getSpecialization() != null && !group.getSpecialization().getExceptions().isEmpty()) { - return true; + if (!elseConnectable.isEmpty()) { + SpecializationGroup previous = group.getPrevious(); + if (previous != null && hasFallthrough(previous, forType, currentValues, fastPath, previous.getGuards())) { + return true; + } } - if (!group.getChildren().isEmpty()) { - return hasFallthrough(group.getChildren().get(group.getChildren().size() - 1), forType, currentValues, fastPath); + List groupChildren = group.getChildren(); + if (!groupChildren.isEmpty()) { + return hasFallthrough(groupChildren.get(groupChildren.size() - 1), forType, currentValues, fastPath, ignoreGuards); } return false; @@ -1117,11 +1242,25 @@ } if (currentValues != null) { for (Parameter p : specialization.getSignatureParameters()) { - LocalVariable local = currentValues.get(p.getLocalName()); CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getTypeSystemType()); if (var != null) { - builder.tree(local.createReference()); + // we need the original name here + builder.tree(LocalVariable.fromParameter(p).createReference()); + } + } + for (CacheExpression cache : specialization.getCaches()) { + LocalVariable variable = currentValues.get(cache.getParameter().getLocalName()); + if (variable == null) { + throw new AssertionError("Could not bind cached value " + cache.getParameter().getLocalName() + ": " + currentValues); } + builder.tree(variable.createReference()); + } + for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { + LocalVariable variable = currentValues.get(assumptionName(assumption)); + if (variable == null) { + throw new AssertionError("Could not bind assumption value " + assumption.getId() + ": " + currentValues); + } + builder.tree(variable.createReference()); } } builder.end(); @@ -1199,6 +1338,31 @@ } } } + for (CacheExpression cache : specialization.getCaches()) { + String name = cache.getParameter().getLocalName(); + TypeMirror type = cache.getParameter().getType(); + + if (ElementUtils.isAssignable(type, new ArrayCodeTypeMirror(getType(Node.class)))) { + CodeVariableElement var = clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name)); + var.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(Children.class))); + } else if (ElementUtils.isAssignable(type, getType(Node.class))) { + CodeVariableElement var = clazz.add(new CodeVariableElement(modifiers(PRIVATE), type, name)); + var.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(Child.class))); + } else { + clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name)); + } + constructor.addParameter(new CodeVariableElement(type, name)); + builder.startStatement().string("this.").string(name).string(" = ").string(name).end(); + } + + for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { + String name = assumptionName(assumption); + TypeMirror type = assumption.getExpression().getResolvedType(); + CodeVariableElement field = clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name)); + field.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class))); + constructor.addParameter(new CodeVariableElement(type, name)); + builder.startStatement().string("this.").string(name).string(" = ").string(name).end(); + } } if (constructor.getParameters().isEmpty()) { @@ -1258,9 +1422,12 @@ return builder.build(); } - private static CodeTree createCallDelegate(String methodName, TypeData forType, LocalContext currentValues) { + private static CodeTree createCallDelegate(String methodName, String reason, TypeData forType, LocalContext currentValues) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); builder.startCall(methodName); + if (reason != null) { + builder.doubleQuote(reason); + } currentValues.addReferencesTo(builder, FRAME_VALUE); builder.end(); @@ -1300,6 +1467,10 @@ TypeData type = forType == null ? genericType : forType; LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold); + if (specialization != null) { + currentLocals.loadFastPathState(specialization); + } + CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); @@ -1308,12 +1479,12 @@ } CodeTreeBuilder builder = executable.createBuilder(); - builder.tree(createFastPathExecute(builder, specialization, type, currentLocals)); + builder.tree(createFastPath(builder, specialization, type, currentLocals)); return executable; } - private CodeTree createFastPathExecute(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) { + private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) { final CodeTreeBuilder builder = parent.create(); for (NodeExecutionData execution : node.getChildExecutions()) { @@ -1334,11 +1505,11 @@ LocalContext originalValues = currentLocals.copy(); if (specialization == null) { - builder.startReturn().tree(createCallDelegate("acceptAndExecute", type, currentLocals)).end(); + builder.startReturn().tree(createCallDelegate("acceptAndExecute", null, type, currentLocals)).end(); } else if (specialization.isPolymorphic()) { builder.tree(createCallNext(type, currentLocals)); } else if (specialization.isUninitialized()) { - builder.startReturn().tree(createCallDelegate("uninitialized", type, currentLocals)).end(); + builder.startReturn().tree(createCallDelegate("uninitialized", null, type, currentLocals)).end(); } else { final TypeData finalType = type; SpecializationGroup group = SpecializationGroup.create(specialization); @@ -1352,7 +1523,7 @@ } }; builder.tree(createGuardAndCast(group, type, currentLocals, executionFactory)); - if (hasFallthrough(group, type, originalValues, true) || group.getSpecialization().isFallback()) { + if (hasFallthrough(group, type, originalValues, true, null) || group.getSpecialization().isFallback()) { builder.tree(createCallNext(type, originalValues)); } } @@ -1403,6 +1574,27 @@ ifCount++; } CodeTreeBuilder execute = builder.create(); + + if (!specialization.getAssumptionExpressions().isEmpty()) { + builder.startTryBlock(); + for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { + LocalVariable assumptionVar = currentValues.get(assumptionName(assumption)); + if (assumptionVar == null) { + throw new AssertionError("Could not resolve assumption var " + currentValues); + } + builder.startStatement().startCall("check").tree(assumptionVar.createReference()).end().end(); + } + builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae"); + builder.startReturn(); + List assumptionIds = new ArrayList<>(); + for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { + assumptionIds.add(assumption.getId()); + } + builder.tree(createCallDelegate("removeThis", String.format("Assumption %s invalidated", assumptionIds), forType, currentValues)); + builder.end(); + builder.end(); + } + execute.startReturn(); if (specialization.getMethod() == null) { execute.startCall("unsupported"); @@ -1426,27 +1618,24 @@ } else { castGuards = new HashSet<>(); for (TypeGuard castGuard : group.getTypeGuards()) { - if (isTypeGuardUsedInAnyGuardBelow(group, currentValues, castGuard)) { + if (isTypeGuardUsedInAnyGuardOrCacheBelow(group, currentValues, castGuard)) { castGuards.add(castGuard); } } } - CodeTree[] checkAndCast = createTypeCheckAndCast(group.getTypeGuards(), castGuards, currentValues, execution); + + SpecializationData specialization = group.getSpecialization(); + CodeTree[] checkAndCast = createTypeCheckAndLocals(specialization, group.getTypeGuards(), castGuards, currentValues, execution); + CodeTree check = checkAndCast[0]; CodeTree cast = checkAndCast[1]; List elseGuardExpressions = group.findElseConnectableGuards(); List guardExpressions = new ArrayList<>(group.getGuards()); guardExpressions.removeAll(elseGuardExpressions); - CodeTree methodGuards = createMethodGuardCheck(guardExpressions, currentValues); - - if (!group.getAssumptions().isEmpty()) { - if (execution.isFastPath() && !forType.isGeneric()) { - cast = appendAssumptionFastPath(cast, group.getAssumptions(), forType, currentValues); - } else { - methodGuards = appendAssumptionSlowPath(methodGuards, group.getAssumptions()); - } - } + CodeTree[] methodGuardAndAssertions = createMethodGuardCheck(guardExpressions, specialization, currentValues, execution.isFastPath()); + CodeTree methodGuards = methodGuardAndAssertions[0]; + CodeTree guardAssertions = methodGuardAndAssertions[1]; int ifCount = 0; if (!check.isEmpty()) { @@ -1468,13 +1657,15 @@ builder.startElseBlock(); ifCount++; } + if (!guardAssertions.isEmpty()) { + builder.tree(guardAssertions); + } boolean reachable = isReachableGroup(group, ifCount); if (reachable) { for (SpecializationGroup child : group.getChildren()) { builder.tree(createGuardAndCast(child, forType, currentValues.copy(), execution)); } - SpecializationData specialization = group.getSpecialization(); if (specialization != null) { builder.tree(execution.createExecute(specialization, currentValues)); } @@ -1484,33 +1675,6 @@ return builder.build(); } - private CodeTree appendAssumptionSlowPath(CodeTree methodGuards, List assumptions) { - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - - builder.tree(methodGuards); - String connect = methodGuards.isEmpty() ? "" : " && "; - for (String assumption : assumptions) { - builder.string(connect); - builder.startCall(accessParent(assumptionName(assumption)), "isValid").end(); - connect = " && "; - } - - return builder.build(); - } - - private CodeTree appendAssumptionFastPath(CodeTree casts, List assumptions, TypeData forType, LocalContext currentValues) { - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - builder.tree(casts); - builder.startTryBlock(); - for (String assumption : assumptions) { - builder.startStatement().startCall(accessParent(assumptionName(assumption)), "check").end().end(); - } - builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae"); - builder.tree(createCallNext(forType, currentValues)); - builder.end(); - return builder.build(); - } - private static boolean isReachableGroup(SpecializationGroup group, int ifCount) { if (ifCount != 0) { return true; @@ -1524,7 +1688,7 @@ * Hacky else case. In this case the specialization is not reachable due to previous else * branch. This is only true if the minimum state is not checked. */ - if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() && + if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) { return false; } @@ -1532,22 +1696,25 @@ return true; } - private boolean isTypeGuardUsedInAnyGuardBelow(SpecializationGroup group, LocalContext currentValues, TypeGuard typeGuard) { - NodeExecutionData execution = node.getChildExecutions().get(typeGuard.getSignatureIndex()); + private boolean isTypeGuardUsedInAnyGuardOrCacheBelow(SpecializationGroup group, LocalContext currentValues, TypeGuard typeGuard) { + String localName = currentValues.getValue(typeGuard.getSignatureIndex()).getName(); + SpecializationData specialization = group.getSpecialization(); for (GuardExpression guard : group.getGuards()) { - List guardParameters = guard.getResolvedGuard().findByExecutionData(execution); - TypeData sourceType = currentValues.getValue(typeGuard.getSignatureIndex()).getType(); - - for (Parameter guardParameter : guardParameters) { - if (sourceType.needsCastTo(guardParameter.getType())) { + if (isVariableBoundIn(specialization, guard.getExpression(), localName, currentValues)) { + return true; + } + } + if (specialization != null) { + for (CacheExpression cache : specialization.getCaches()) { + if (isVariableBoundIn(specialization, cache.getExpression(), localName, currentValues)) { return true; } } } for (SpecializationGroup child : group.getChildren()) { - if (isTypeGuardUsedInAnyGuardBelow(child, currentValues, typeGuard)) { + if (isTypeGuardUsedInAnyGuardOrCacheBelow(child, currentValues, typeGuard)) { return true; } } @@ -1555,6 +1722,17 @@ return false; } + private static boolean isVariableBoundIn(SpecializationData specialization, DSLExpression expression, String localName, LocalContext currentValues) throws AssertionError { + Map boundValues = bindExpressionValues(expression, specialization, currentValues); + for (Variable var : expression.findBoundVariables()) { + LocalVariable target = boundValues.get(var); + if (target != null && localName.equals(target.getName())) { + return true; + } + } + return false; + } + private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeData targetType) { LocalContext locals = LocalContext.load(this, 0, varArgsThreshold); @@ -1946,23 +2124,80 @@ return builder.build(); } - private CodeTree createMethodGuardCheck(List guardExpressions, LocalContext currentValues) { - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + private CodeTree[] createMethodGuardCheck(List guardExpressions, SpecializationData specialization, LocalContext currentValues, boolean fastPath) { + CodeTreeBuilder expressionBuilder = CodeTreeBuilder.createBuilder(); + CodeTreeBuilder assertionBuilder = CodeTreeBuilder.createBuilder(); String and = ""; for (GuardExpression guard : guardExpressions) { - builder.string(and); - if (guard.isNegated()) { - builder.string("!"); + DSLExpression expression = guard.getExpression(); + + Map resolvedBindings = castBoundTypes(bindExpressionValues(expression, specialization, currentValues)); + CodeTree expressionCode = DSLExpressionGenerator.write(expression, accessParent(null), resolvedBindings); + + if (!specialization.isDynamicParameterBound(expression) && fastPath) { + /* + * Guards where no dynamic parameters are bound can just be executed on the fast + * path. + */ + assertionBuilder.startAssert().tree(expressionCode).end(); + } else { + expressionBuilder.string(and); + expressionBuilder.tree(expressionCode); + and = " && "; } - builder.tree(callTemplateMethod(accessParent(null), guard.getResolvedGuard(), currentValues)); - and = " && "; } - return builder.build(); + return new CodeTree[]{expressionBuilder.build(), assertionBuilder.build()}; } - private CodeTree[] createTypeCheckAndCast(List typeGuards, Set castGuards, LocalContext currentValues, SpecializationExecution specializationExecution) { + private static Map castBoundTypes(Map bindings) { + Map resolvedBindings = new HashMap<>(); + for (Variable variable : bindings.keySet()) { + LocalVariable localVariable = bindings.get(variable); + CodeTree resolved = localVariable.createReference(); + TypeMirror sourceType = localVariable.getTypeMirror(); + TypeMirror targetType = variable.getResolvedTargetType(); + if (targetType == null) { + targetType = variable.getResolvedType(); + } + if (!ElementUtils.isAssignable(sourceType, targetType)) { + resolved = CodeTreeBuilder.createBuilder().cast(targetType, resolved).build(); + } + resolvedBindings.put(variable, resolved); + } + return resolvedBindings; + } + + private static Map bindExpressionValues(DSLExpression expression, SpecializationData specialization, LocalContext currentValues) throws AssertionError { + Map bindings = new HashMap<>(); + + Set boundVariables = expression.findBoundVariables(); + if (specialization == null && !boundVariables.isEmpty()) { + throw new AssertionError("Cannot bind guard variable in non-specialization group. yet."); + } + + // resolve bindings for local context + for (Variable variable : boundVariables) { + Parameter resolvedParameter = specialization.findByVariable(variable.getResolvedVariable()); + if (resolvedParameter != null) { + LocalVariable localVariable; + if (resolvedParameter.getSpecification().isSignature()) { + NodeExecutionData execution = resolvedParameter.getSpecification().getExecution(); + localVariable = currentValues.getValue(execution); + } else { + localVariable = currentValues.get(resolvedParameter.getLocalName()); + } + if (localVariable != null) { + bindings.put(variable, localVariable); + } + } + } + return bindings; + } + + private CodeTree[] createTypeCheckAndLocals(SpecializationData specialization, List typeGuards, Set castGuards, LocalContext currentValues, + SpecializationExecution specializationExecution) { CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder(); - CodeTreeBuilder castsBuilder = CodeTreeBuilder.createBuilder(); + CodeTreeBuilder localsBuilder = CodeTreeBuilder.createBuilder(); for (TypeGuard typeGuard : typeGuards) { int signatureIndex = typeGuard.getSignatureIndex(); LocalVariable value = currentValues.getValue(signatureIndex); @@ -2023,12 +2258,31 @@ if (castGuards == null || castGuards.contains(typeGuard)) { LocalVariable castVariable = currentValues.getValue(execution).nextName().newType(typeGuard.getType()).accessWith(null); currentValues.setValue(execution, castVariable); - castsBuilder.tree(castVariable.createDeclaration(castBuilder.build())); + localsBuilder.tree(castVariable.createDeclaration(castBuilder.build())); } checksBuilder.tree(checkBuilder.build()); } - return new CodeTree[]{checksBuilder.build(), castsBuilder.build()}; + + if (specialization != null && !specializationExecution.isFastPath()) { + for (CacheExpression cache : specialization.getCaches()) { + if (specialization.isCacheBoundByGuard(cache)) { + initializeCache(localsBuilder, specialization, cache, currentValues); + } + } + } + + return new CodeTree[]{checksBuilder.build(), localsBuilder.build()}; + } + + private void initializeCache(CodeTreeBuilder builder, SpecializationData specialization, CacheExpression cache, LocalContext currentValues) { + CodeTree initializer = DSLExpressionGenerator.write(cache.getExpression(), accessParent(null), castBoundTypes(bindExpressionValues(cache.getExpression(), specialization, currentValues))); + String name = cache.getParameter().getLocalName(); + // multiple specializations might use the same name + String varName = name + specialization.getIndex(); + TypeMirror type = cache.getParameter().getType(); + builder.declaration(type, varName, initializer); + currentValues.set(name, new LocalVariable(null, type, varName, null)); } public static final class LocalContext { @@ -2040,6 +2294,20 @@ this.factory = factory; } + public void loadFastPathState(SpecializationData specialization) { + for (CacheExpression cache : specialization.getCaches()) { + Parameter cacheParameter = cache.getParameter(); + String name = cacheParameter.getVariableElement().getSimpleName().toString(); + set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getTypeSystemType(), cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name))); + } + + for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) { + String name = assumptionName(assumption); + TypeMirror type = assumption.getExpression().getResolvedType(); + set(name, new LocalVariable(null, type, name, CodeTreeBuilder.singleString("this." + name))); + } + } + public CodeExecutableElement createMethod(Set modifiers, TypeMirror returnType, String name, String... optionalArguments) { CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name); addParametersTo(method, optionalArguments); @@ -2238,6 +2506,11 @@ return values.get(shortCircuitName(execution)); } + @Override + public String toString() { + return "LocalContext [values=" + values + "]"; + } + } public static final class LocalVariable { @@ -2329,6 +2602,11 @@ return newType(type.getTypeSystem().getGenericTypeData()); } + @Override + public String toString() { + return "Local[type = " + getTypeMirror() + ", name = " + name + ", accessWith = " + accessorTree + "]"; + } + } private interface SpecializationExecution { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/PolymorphicNodeFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/PolymorphicNodeFactory.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.generator; - -import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.type.*; - -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.model.*; -import com.oracle.truffle.dsl.processor.model.*; - -class PolymorphicNodeFactory extends SpecializedNodeFactory { - - public PolymorphicNodeFactory(ProcessorContext context, NodeData node, SpecializationData specialization, CodeTypeElement nodeGen) { - super(context, node, specialization, nodeGen); - } - - @Override - public CodeTypeElement create() { - TypeMirror baseType = node.getNodeType(); - if (nodeGen != null) { - baseType = nodeGen.asType(); - } - CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(PRIVATE, FINAL), nodePolymorphicClassName(node), baseType); - - clazz.getAnnotationMirrors().add(createNodeInfo(NodeCost.POLYMORPHIC)); - - for (Parameter polymorphParameter : specialization.getSignatureParameters()) { - if (!polymorphParameter.getTypeSystemType().isGeneric()) { - continue; - } - Set types = new HashSet<>(); - for (SpecializationData otherSpecialization : node.getSpecializations()) { - if (!otherSpecialization.isSpecialized()) { - continue; - } - Parameter parameter = otherSpecialization.findParameter(polymorphParameter.getLocalName()); - assert parameter != null; - types.add(parameter.getTypeSystemType()); - } - - } - - for (NodeExecutionData execution : node.getChildExecutions()) { - String fieldName = polymorphicTypeName(execution); - CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), context.getType(Class.class), fieldName); - var.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal())); - clazz.add(var); - } - - createConstructors(clazz); - createExecuteMethods(clazz); - - clazz.add(createUpdateTypes0()); - createCachedExecuteMethods(clazz); - - return clazz; - } - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/SpecializedNodeFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/SpecializedNodeFactory.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,557 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.generator; - -import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; -import static javax.lang.model.element.Modifier.*; - -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import javax.lang.model.util.*; - -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.*; -import com.oracle.truffle.dsl.processor.java.model.*; -import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror; -import com.oracle.truffle.dsl.processor.model.*; -import com.oracle.truffle.dsl.processor.parser.*; - -class SpecializedNodeFactory extends NodeBaseFactory { - - protected final CodeTypeElement nodeGen; - - public SpecializedNodeFactory(ProcessorContext context, NodeData node, SpecializationData specialization, CodeTypeElement nodeGen) { - super(context, node, specialization); - this.nodeGen = nodeGen; - } - - @Override - public CodeTypeElement create() { - TypeMirror baseType = node.getNodeType(); - if (nodeGen != null) { - baseType = nodeGen.asType(); - } - CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(PRIVATE, FINAL), nodeSpecializationClassName(specialization), baseType); - - if (specialization.isSpecialized() || specialization.isUninitialized()) { - clazz.add(createGetMetadata0(false)); - clazz.add(createMetadataLiteral()); - } - - NodeCost cost; - if (specialization.isFallback()) { - cost = NodeCost.MEGAMORPHIC; - } else if (specialization.isUninitialized()) { - cost = NodeCost.UNINITIALIZED; - } else if (specialization.isPolymorphic()) { - cost = NodeCost.POLYMORPHIC; - } else if (specialization.isSpecialized()) { - cost = NodeCost.MONOMORPHIC; - } else { - throw new AssertionError(); - } - clazz.getAnnotationMirrors().add(createNodeInfo(cost)); - - if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) { - clazz.add(createUninitializedGetCostOverride()); - } - - createConstructors(clazz); - - createExecuteMethods(clazz); - createCachedExecuteMethods(clazz); - - if (specialization.isUninitialized()) { - if (specialization.getNode().isFallbackReachable()) { - CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK); - var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal())); - clazz.add(var); - } - clazz.add(createExecuteUninitialized()); - } - - if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) { - clazz.add(createCopyConstructorFactoryMethod(clazz, nodeGen.asType())); - } else { - for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) { - if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) { - // skip copy constructor - not used - continue; - } - clazz.add(createConstructorFactoryMethod(clazz, constructor)); - } - } - - return clazz; - } - - private Element createUninitializedGetCostOverride() { - TypeMirror returnType = context.getTruffleTypes().getNodeCost(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost"); - CodeTreeBuilder builder = method.createBuilder(); - builder.startIf().string(CONTAINS_FALLBACK).end().startBlock(); - builder.startReturn().staticReference(returnType, "MONOMORPHIC").end(); - builder.end(); - builder.startReturn().string("super.getCost()").end(); - return method; - } - - private CodeVariableElement createMetadataLiteral() { - CodeVariableElement includes = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getTruffleTypes().getDslMetadata(), METADATA_FIELD_NAME); - - CodeTreeBuilder builder = includes.createInitBuilder(); - - Set contains = specialization.getContains(); - if (specialization.isUninitialized()) { - contains = new HashSet<>(); - - SpecializationData polymorphic = node.getPolymorphicSpecialization(); - if (polymorphic != null) { - contains.addAll(polymorphic.getContains()); - } - SpecializationData generic = node.getGenericSpecialization(); - if (generic != null) { - contains.addAll(generic.getContains()); - } - } - - builder.startNew(context.getTruffleTypes().getDslMetadata()); - builder.startGroup().string(nodeSpecializationClassName(getSpecialization()), ".class").end(); - builder.tree(createSpecializationListLiteral(builder, contains)); - builder.tree(createSpecializationListLiteral(builder, getSpecialization().getExcludedBy())); - builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getSpecialization()))); - builder.string("0").string("0"); - builder.end(); - return includes; - } - - private CodeTree createSpecializationTypeLiteral(CodeTreeBuilder parent, List list) { - ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); - CodeTreeBuilder builder = parent.create(); - - if (list.isEmpty()) { - builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); - } else { - builder.startNewArray(classArray, null); - for (TypeMirror type : list) { - builder.typeLiteral(type); - } - builder.end(); - } - - return builder.build(); - } - - private CodeTree createSpecializationListLiteral(CodeTreeBuilder parent, Set list) { - ArrayType classArray = new ArrayCodeTypeMirror(context.getType(Class.class)); - CodeTreeBuilder builder = parent.create(); - - if (list.isEmpty()) { - builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY); - } else { - builder.startNewArray(classArray, null); - for (SpecializationData current : list) { - SpecializationData s = current; - if (s.isFallback() || s.isPolymorphic()) { - s = getSpecialization().getNode().getUninitializedSpecialization(); - } - builder.startGroup().string(nodeSpecializationClassName(s)).string(".class").end(); - } - builder.end(); - } - - return builder.build(); - } - - protected CodeAnnotationMirror createNodeInfo(NodeCost cost) { - String shortName = node.getShortName(); - CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(context.getTruffleTypes().getNodeInfoAnnotation()); - if (shortName != null) { - nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName)); - } - - DeclaredType nodeinfoCost = context.getTruffleTypes().getNodeCost(); - VariableElement varKind = ElementUtils.findVariableElement(nodeinfoCost, cost.name()); - - nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind)); - return nodeInfoMirror; - } - - protected void createConstructors(CodeTypeElement clazz) { - TypeElement superTypeElement = ElementUtils.fromTypeMirror(clazz.getSuperclass()); - for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) { - if (specialization.isUninitialized()) { - // ignore copy constructors for uninitialized if not polymorphic - if (isCopyConstructor(constructor) && !node.isPolymorphic(context)) { - continue; - } - } else if (node.getUninitializedSpecialization() != null) { - // ignore others than copy constructors for specialized nodes - if (!isCopyConstructor(constructor)) { - continue; - } - } - - CodeExecutableElement superConstructor = GeneratorUtils.createSuperConstructor(context, clazz, constructor); - if (superConstructor == null) { - continue; - } - CodeTree body = superConstructor.getBodyTree(); - CodeTreeBuilder builder = superConstructor.createBuilder(); - builder.tree(body); - - if (superConstructor != null) { - for (Parameter param : getImplicitTypeParameters(getSpecialization())) { - clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), context.getType(Class.class), implicitTypeName(param))); - superConstructor.getParameters().add(new CodeVariableElement(context.getType(Class.class), implicitTypeName(param))); - - builder.startStatement(); - builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param)); - builder.end(); - } - - clazz.add(superConstructor); - } - } - } - - protected void createExecuteMethods(CodeTypeElement clazz) { - - List primaryExecutes = null; - int lastEvaluatedCount = -1; - - for (ExecutableTypeData execType : node.getExecutableTypes()) { - if (execType.isFinal()) { - continue; - } - if (execType.getEvaluatedCount() != lastEvaluatedCount) { - lastEvaluatedCount = execType.getEvaluatedCount(); - primaryExecutes = findFunctionalExecutableType(lastEvaluatedCount); - } - - CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true); - clazz.add(executeMethod); - CodeTreeBuilder builder = executeMethod.getBuilder(); - CodeTree result = createExecuteBody(builder, execType, primaryExecutes); - if (result != null) { - builder.tree(result); - } else { - clazz.remove(executeMethod); - } - } - } - - protected void createCachedExecuteMethods(CodeTypeElement clazz) { - if (!node.isPolymorphic(context)) { - return; - } - - final SpecializationData polymorphic = node.getPolymorphicSpecialization(); - ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED); - CodeExecutableElement executeMethod = CodeExecutableElement.clone(context.getEnvironment(), executeCached); - executeMethod.getModifiers().remove(Modifier.ABSTRACT); - CodeTreeBuilder builder = executeMethod.createBuilder(); - - if (specialization.isPolymorphic()) { - builder.startReturn().startCall("this.next0", EXECUTE_CHAINED); - addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, false, null); - builder.end().end(); - } else if (specialization.isUninitialized()) { - builder.tree(createDeoptimizeUninitialized(node, builder)); - builder.startReturn().startCall("this", EXECUTE_UNINITIALIZED); - addInternalValueParameterNames(builder, polymorphic, polymorphic, null, true, false, null); - builder.end().end(); - } else { - CodeTreeBuilder elseBuilder = new CodeTreeBuilder(builder); - elseBuilder.startReturn().startCall("this.next0", EXECUTE_CHAINED); - addInternalValueParameterNames(elseBuilder, polymorphic, polymorphic, null, true, false, null); - elseBuilder.end().end(); - - builder.tree(createExecuteTree(builder, polymorphic, SpecializationGroup.create(specialization), new CodeBlock() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createGenericInvoke(b, polymorphic, current); - } - }, elseBuilder.build(), false, true, true, false)); - } - clazz.add(executeMethod); - } - - private static CodeTree createDeoptimizeUninitialized(NodeData node, CodeTreeBuilder parent) { - CodeTreeBuilder builder = parent.create(); - if (node.getGenericSpecialization().isReachable()) { - builder.startIf().string("!containsFallback").end().startBlock(); - builder.tree(createDeoptimize(builder)); - builder.end(); - } else { - builder.tree(createDeoptimize(builder)); - } - return builder.build(); - } - - private CodeTree createExecuteBody(CodeTreeBuilder parent, ExecutableTypeData execType, List primaryExecutes) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) { - builder.tree(createFunctionalExecute(builder, execType)); - } else if (needsCastingExecuteMethod(execType)) { - assert !primaryExecutes.isEmpty(); - builder.tree(createCastingExecute(builder, execType, primaryExecutes.get(0))); - } else { - return null; - } - - return builder.build(); - } - - private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) { - CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), execType.getMethod()); - - method.getAnnotationMirrors().clear(); - for (VariableElement variable : method.getParameters()) { - variable.getAnnotationMirrors().clear(); - } - - CodeTreeBuilder builder = method.createBuilder(); - int i = 0; - int signatureIndex = -1; - for (VariableElement param : method.getParameters()) { - CodeVariableElement var = CodeVariableElement.clone(param); - Parameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null; - String name; - if (actualParameter != null) { - if (actualParameter.getSpecification().isSignature()) { - signatureIndex++; - } - - if (evaluated && actualParameter.getSpecification().isSignature()) { - name = valueNameEvaluated(actualParameter); - } else { - name = valueName(actualParameter); - } - - int varArgCount = getSpecialization().getSignatureSize() - signatureIndex; - if (evaluated && actualParameter.isTypeVarArgs()) { - Parameter baseVarArgs = actualParameter; - name = valueName(baseVarArgs) + "Args"; - - builder.startAssert().string(name).string(" != null").end(); - builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end(); - if (varArgCount > 0) { - List varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size()); - for (Parameter varArg : varArgsParameter) { - if (varArgCount <= 0) { - break; - } - TypeMirror type = baseVarArgs.getType(); - if (type.getKind() == TypeKind.ARRAY) { - type = ((ArrayType) type).getComponentType(); - } - builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]"); - varArgCount--; - } - } - } - } else { - name = "arg" + i; - } - var.setName(name); - method.getParameters().set(i, var); - i++; - } - - method.getAnnotationMirrors().clear(); - method.getModifiers().remove(Modifier.ABSTRACT); - return method; - } - - private static boolean needsCastingExecuteMethod(ExecutableTypeData execType) { - if (execType.isAbstract()) { - return true; - } - if (execType.getType().isGeneric()) { - return true; - } - return false; - } - - private List findFunctionalExecutableType(int evaluatedCount) { - TypeData primaryType = specialization.getReturnType().getTypeSystemType(); - List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); - - List filteredTypes = new ArrayList<>(); - for (ExecutableTypeData compareType : otherTypes) { - if (ElementUtils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { - filteredTypes.add(compareType); - } - } - - // no direct matches found use generic where the type is Object - if (filteredTypes.isEmpty()) { - for (ExecutableTypeData compareType : otherTypes) { - if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(context)) { - filteredTypes.add(compareType); - } - } - } - - if (filteredTypes.isEmpty()) { - for (ExecutableTypeData compareType : otherTypes) { - if (compareType.getType().isGeneric()) { - filteredTypes.add(compareType); - } - } - } - - return filteredTypes; - } - - private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final ExecutableTypeData executable) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - - if (specialization.isUninitialized()) { - builder.tree(createDeoptimizeUninitialized(specialization.getNode(), builder)); - } - - builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null)); - - CodeTree returnSpecialized = null; - - if (specialization.findNextSpecialization() != null) { - CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); - returnBuilder.tree(createDeoptimize(builder)); - returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), null, "One of guards " + specialization.getGuards() + " failed")); - returnSpecialized = returnBuilder.build(); - } - - builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock() { - - public CodeTree create(CodeTreeBuilder b, SpecializationData current) { - return createExecute(b, executable); - } - }, returnSpecialized, false, false, false, false)); - - return builder.build(); - } - - private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) { - builder.startTryBlock(); - } - - for (String assumption : specialization.getAssumptions()) { - builder.startStatement(); - builder.string("this.").string(assumption).string(".check()"); - builder.end(); - } - - CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); - if (specialization.isPolymorphic()) { - returnBuilder.startCall("next0", EXECUTE_CHAINED); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, false, null); - returnBuilder.end(); - } else if (specialization.isUninitialized()) { - returnBuilder.startCall(EXECUTE_UNINITIALIZED); - addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, false, null); - returnBuilder.end(); - } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { - emitEncounteredSynthetic(builder, getSpecialization().getNode(), specialization); - } else { - returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null)); - } - - if (!returnBuilder.isEmpty()) { - TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); - TypeData sourceType = specialization.getReturnType().getTypeSystemType(); - - builder.startReturn(); - if (targetType == null || sourceType == null) { - builder.tree(returnBuilder.build()); - } else if (sourceType.needsCastTo(targetType)) { - CodeTree cast; - if (executable.hasUnexpectedValue(context)) { - cast = TypeSystemCodeGenerator.expect(targetType, returnBuilder.build()); - } else { - cast = TypeSystemCodeGenerator.cast(targetType, returnBuilder.build()); - } - builder.tree(cast); - } else { - builder.tree(returnBuilder.build()); - } - builder.end(); - } - - if (!specialization.getExceptions().isEmpty()) { - for (SpecializationThrowsData exception : specialization.getExceptions()) { - builder.end().startCatchBlock(exception.getJavaClass(), "ex"); - builder.tree(createDeoptimize(builder)); - builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), null, "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass()))); - } - builder.end(); - } - if (!specialization.getAssumptions().isEmpty()) { - builder.end().startCatchBlock(context.getTruffleTypes().getInvalidAssumption(), "ex"); - builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), null, "Assumption failed")); - builder.end(); - } - - return builder.build(); - } - - private CodeExecutableElement createCopyConstructorFactoryMethod(CodeTypeElement clazz, TypeMirror baseType) { - List implicitTypeParams = getImplicitTypeParameters(specialization); - String baseName = "current"; - CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), NodeFactoryFactory.FACTORY_METHOD_NAME); - method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName)); - for (Parameter implicitTypeParam : implicitTypeParams) { - method.addParameter(new CodeVariableElement(context.getType(Class.class), implicitTypeName(implicitTypeParam))); - } - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startNew(clazz.asType()); - builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end(); - for (Parameter param : implicitTypeParams) { - builder.string(implicitTypeName(param)); - } - builder.end().end(); - return method; - } - - private CodeExecutableElement createConstructorFactoryMethod(CodeTypeElement clazz, ExecutableElement constructor) { - List parameters = constructor.getParameters(); - CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), NodeFactoryFactory.FACTORY_METHOD_NAME, - parameters.toArray(new CodeVariableElement[parameters.size()])); - CodeTreeBuilder builder = method.createBuilder(); - builder.startReturn(); - builder.startNew(clazz.asType()); - for (VariableElement param : parameters) { - builder.string(((CodeVariableElement) param).getName()); - } - builder.end().end(); - return method; - } -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Sat Feb 21 19:55:33 2015 +0100 @@ -118,14 +118,6 @@ return builder.build(); } - public static CodeTree cast(TypeData sourceType, TypeData targetType, CodeTree content) { - if (sourceType != null && !sourceType.needsCastTo(targetType)) { - return content; - } else { - return cast(targetType, content); - } - } - public static CodeTree expect(TypeData type, CodeTree content) { if (type.isGeneric() || type.isVoid()) { return content; @@ -208,15 +200,13 @@ public CodeTypeElement create(ProcessorContext context, TypeSystemData typeSystem) { CodeTypeElement clazz = new TypeClassFactory(context, typeSystem).create(); - if (typeSystem.getOptions().useNewLayout()) { - clazz.add(new TypeSystemNodeFactory(context, typeSystem).create()); + clazz.add(new TypeSystemNodeFactory(context, typeSystem).create()); - if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) { - for (TypeData type : typeSystem.getTypes()) { - List sourceTypes = typeSystem.lookupSourceTypes(type); - if (sourceTypes.size() > 1) { - clazz.add(new ImplicitCastNodeFactory(context, type).create()); - } + if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) { + for (TypeData type : typeSystem.getTypes()) { + List sourceTypes = typeSystem.lookupSourceTypes(type); + if (sourceTypes.size() > 1) { + clazz.add(new ImplicitCastNodeFactory(context, type).create()); } } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Sat Feb 21 19:55:33 2015 +0100 @@ -119,16 +119,6 @@ return b.toString(); } - public static VariableElement findVariableElement(DeclaredType type, String name) { - List elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements()); - for (VariableElement variableElement : elements) { - if (variableElement.getSimpleName().toString().equals(name)) { - return variableElement; - } - } - return null; - } - public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) { TypeMirror boxedType = primitiveType; if (boxedType.getKind().isPrimitive()) { @@ -191,8 +181,17 @@ } public static String getReadableSignature(ExecutableElement method) { - // TODO toString does not guarantee a good signature - return method.toString(); + StringBuilder builder = new StringBuilder(); + builder.append(method.getSimpleName().toString()); + builder.append("("); + String sep = ""; + for (VariableElement var : method.getParameters()) { + builder.append(sep); + builder.append(getSimpleName(var.asType())); + sep = ", "; + } + builder.append(")"); + return builder.toString(); } public static boolean hasError(TypeMirror mirror) { @@ -570,7 +569,7 @@ public static TypeElement findNearestEnclosingType(Element element) { List elements = getElementHierarchy(element); for (Element e : elements) { - if (e.getKind().isClass()) { + if (e.getKind().isClass() || e.getKind().isInterface()) { return (TypeElement) e; } } @@ -588,29 +587,6 @@ return types; } - public static List getAssignableTypes(ProcessorContext context, TypeMirror type) { - if (isPrimitive(type)) { - return Arrays.asList(type, boxType(context, type), context.getType(Object.class)); - } else if (type.getKind() == TypeKind.ARRAY) { - return Arrays.asList(type, context.getType(Object.class)); - } else if (type.getKind() == TypeKind.DECLARED) { - DeclaredType declaredType = (DeclaredType) type; - TypeElement typeElement = fromTypeMirror(declaredType); - List types = getSuperTypes(typeElement); - List mirrors = new ArrayList<>(types.size()); - mirrors.add(type); - for (TypeElement superTypeElement : types) { - mirrors.add(superTypeElement.asType()); - } - if (typeElement.getKind().isInterface()) { - mirrors.add(getType(context.getEnvironment(), Object.class)); - } - return mirrors; - } else { - return Collections.emptyList(); - } - } - /** * Gets the element representing the {@linkplain TypeElement#getSuperclass() super class} of a * given type element. @@ -690,6 +666,8 @@ return pack.getQualifiedName().toString(); case ARRAY: return getSimpleName(((ArrayType) mirror).getComponentType()); + case EXECUTABLE: + return null; default: throw new RuntimeException("Unknown type specified " + mirror.getKind()); } @@ -854,14 +832,16 @@ public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); - return findAnnotationMirror(mirrors, expectedAnnotationType); + return findAnnotationMirror(mirrors, expectedAnnotationType.asType()); } public static AnnotationMirror findAnnotationMirror(List mirrors, TypeElement expectedAnnotationType) { + return findAnnotationMirror(mirrors, expectedAnnotationType.asType()); + } + + public static AnnotationMirror findAnnotationMirror(List mirrors, TypeMirror expectedAnnotationType) { for (AnnotationMirror mirror : mirrors) { - DeclaredType annotationType = mirror.getAnnotationType(); - TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); - if (actualAnnotationType.equals(expectedAnnotationType)) { + if (typeEquals(mirror.getAnnotationType(), expectedAnnotationType)) { return mirror; } } @@ -1079,42 +1059,53 @@ return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement()); } - public static ExecutableElement findMethod(TypeElement type, Set includeModifiers, Set excludeModifiers, String methodName, List types) { - outer: for (ExecutableElement executable : ElementFilter.methodsIn(type.getEnclosedElements())) { - if (includeModifiers != null) { - if (!executable.getModifiers().containsAll(includeModifiers)) { - continue; - } - } - if (excludeModifiers != null) { - if (executable.getModifiers().containsAll(excludeModifiers)) { - continue; - } - } - if (!executable.getSimpleName().toString().equals(methodName)) { - continue; - } - if (types.size() != executable.getParameters().size()) { - continue; - } - for (int i = 0; i < types.size(); i++) { - TypeMirror var1 = types.get(i); - VariableElement var2 = executable.getParameters().get(i); - if (ElementUtils.typeEquals(var1, var2.asType())) { - continue outer; - } - } - return executable; + public static boolean variableEquals(VariableElement var1, VariableElement var2) { + if (!var1.getSimpleName().equals(var2.getSimpleName())) { + return false; } - return null; + if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) { + return false; + } + if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) { + return false; + } + return true; } - public static List asTypes(List elements) { - List types = new ArrayList<>(elements.size()); - for (Element element : elements) { - types.add(element.asType()); + public static boolean executableEquals(ExecutableElement var1, ExecutableElement var2) { + if (!var1.getSimpleName().equals(var2.getSimpleName())) { + return false; + } + if (var1.getParameters().size() != var2.getParameters().size()) { + return false; + } + if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) { + return false; } - return types; + if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) { + return false; + } + for (int i = 0; i < var1.getParameters().size(); i++) { + if (!typeEquals(var1.getParameters().get(i).asType(), var2.getParameters().get(i).asType())) { + return false; + } + } + return true; } + public static boolean elementEquals(Element element1, Element element2) { + if (element1.getKind() != element2.getKind()) { + return false; + } else if (element1 instanceof VariableElement) { + return variableEquals((VariableElement) element1, (VariableElement) element2); + } else if (element1 instanceof ExecutableElement) { + return executableEquals((ExecutableElement) element1, (ExecutableElement) element2); + } else if (element1 instanceof TypeElement) { + return typeEquals(element1.asType(), element2.asType()); + } else if (element1 instanceof PackageElement) { + return element1.getSimpleName().equals(element2.getSimpleName()); + } else { + throw new AssertionError("unsupported element type"); + } + } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Sat Feb 21 19:55:33 2015 +0100 @@ -77,11 +77,11 @@ } public static CodeTree singleString(String s) { - return new CodeTreeBuilder(null).string(s).getTree(); + return createBuilder().string(s).build(); } public static CodeTree singleType(TypeMirror s) { - return new CodeTreeBuilder(null).type(s).getTree(); + return createBuilder().type(s).build(); } private CodeTreeBuilder push(CodeTreeKind kind) { @@ -324,10 +324,6 @@ return end(); } - public CodeTreeBuilder dot() { - return string("."); - } - public CodeTreeBuilder newLine() { return push(NEW_LINE); } @@ -576,17 +572,6 @@ return declaration(type, name, init.getTree()); } - public CodeTreeBuilder declaration(String type, String name, CodeTreeBuilder init) { - if (init == this) { - throw new IllegalArgumentException("Recursive builder usage."); - } - return declaration(type, name, init.getTree()); - } - - public CodeTreeBuilder declaration(TypeMirror type, String name) { - return declaration(type, name, (CodeTree) null); - } - public CodeTreeBuilder create() { return new CodeTreeBuilder(this); } @@ -622,11 +607,6 @@ return root; } - public CodeTreeBuilder cast(String baseClassName) { - string("(").string(baseClassName).string(") "); - return this; - } - public CodeTreeBuilder cast(TypeMirror type) { string("(").type(type).string(") "); return this; @@ -671,22 +651,10 @@ return startReturn().string("true").end(); } - public CodeTreeBuilder instanceOf(CodeTree var, CodeTree type) { - return tree(var).string(" instanceof ").tree(type); - } - public CodeTreeBuilder instanceOf(CodeTree var, TypeMirror type) { return tree(var).string(" instanceof ").type(type); } - public CodeTreeBuilder instanceOf(String var, String type) { - return instanceOf(singleString(var), singleString(type)); - } - - public CodeTreeBuilder instanceOf(String var, TypeMirror type) { - return instanceOf(singleString(var), singleType(type)); - } - public CodeTreeBuilder defaultValue(TypeMirror mirror) { switch (mirror.getKind()) { case VOID: @@ -717,26 +685,6 @@ } } - public CodeTreeBuilder assertFalse() { - return startAssert().string("false").end(); - } - - public CodeTreeBuilder breakStatement() { - return statement("break"); - } - - public CodeTreeBuilder isNull() { - return string(" == null"); - } - - public CodeTreeBuilder isNotNull() { - return string(" != null"); - } - - public CodeTreeBuilder is(CodeTree tree) { - return string(" == ").tree(tree); - } - public CodeTreeBuilder startTryBlock() { return string("try ").startBlock(); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java Sat Feb 21 19:55:33 2015 +0100 @@ -173,15 +173,6 @@ return ElementFilter.fieldsIn(getEnclosedElements()); } - public ExecutableElement getMethod(String name) { - for (Element element : getEnclosedElements()) { - if (element.getKind() == ElementKind.METHOD && element.getSimpleName().toString().equals(name)) { - return (ExecutableElement) element; - } - } - return null; - } - public List getMethods() { return ElementFilter.methodsIn(getEnclosedElements()); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java Sat Feb 21 19:55:33 2015 +0100 @@ -85,6 +85,11 @@ } @Override + public String toString() { + return super.toString() + "/* " + ElementUtils.getSimpleName(type) + "*/"; + } + + @Override public ElementKind getKind() { if (getEnclosingElement() instanceof ExecutableElement) { return ElementKind.PARAMETER; diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.java.*; + +public final class AnnotatedParameterSpec extends ParameterSpec { + + private final DeclaredType annotationType; + + public AnnotatedParameterSpec(DeclaredType type) { + super("annotated", Collections. emptyList()); + this.annotationType = type; + } + + public DeclaredType getAnnotationType() { + return annotationType; + } + + @Override + public boolean matches(VariableElement variable) { + if (ElementUtils.findAnnotationMirror(variable.getAnnotationMirrors(), annotationType) != null) { + return true; + } + return false; + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.java.*; + +public final class AssumptionExpression extends MessageContainer { + + private final TemplateMethod source; + private final DSLExpression expression; + private final String id; + + public AssumptionExpression(TemplateMethod source, DSLExpression expression, String id) { + this.source = source; + this.expression = expression; + this.id = id; + } + + public String getId() { + return id; + } + + @Override + public Element getMessageElement() { + return source.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return source.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return ElementUtils.getAnnotationValue(getMessageAnnotation(), "assumptions"); + } + + public DSLExpression getExpression() { + return expression; + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java Sat Feb 21 19:55:33 2015 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import javax.lang.model.element.*; + +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.java.*; + +public final class CacheExpression extends MessageContainer { + + private final DSLExpression expression; + private final Parameter sourceParameter; + private final AnnotationMirror sourceAnnotationMirror; + + public CacheExpression(Parameter sourceParameter, AnnotationMirror sourceAnnotationMirror, DSLExpression expression) { + this.sourceParameter = sourceParameter; + this.expression = expression; + this.sourceAnnotationMirror = sourceAnnotationMirror; + } + + public Parameter getParameter() { + return sourceParameter; + } + + @Override + public Element getMessageElement() { + return sourceParameter.getVariableElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return sourceAnnotationMirror; + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return ElementUtils.getAnnotationValue(getMessageAnnotation(), "value"); + } + + public DSLExpression getExpression() { + return expression; + } + +} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Sat Feb 21 19:55:33 2015 +0100 @@ -85,12 +85,4 @@ return super.equals(obj); } - public boolean hasFrame() { - return getFrame() != null; - } - - public Parameter getFrame() { - return findParameter("frameValue"); - } - } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.model; - -import java.util.*; - -public class GuardData extends TemplateMethod { - - private List impliesExpressions; - - public GuardData(TemplateMethod method, List impliesExpressions) { - super(method); - this.impliesExpressions = impliesExpressions; - } - - public List getImpliesExpressions() { - return impliesExpressions; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof GuardData) { - GuardData other = (GuardData) obj; - return getMethod().equals(other.getMethod()); - } - return false; - } - - @Override - public int hashCode() { - return getMethod().hashCode(); - } - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,120 +24,63 @@ import java.util.*; -public final class GuardExpression { - - private GuardData resolvedGuard; - private NodeExecutionData[] resolvedChildren; - - private final String guardName; - private final boolean negated; - private final String[] childNames; +import javax.lang.model.element.*; - public GuardExpression(String expression, boolean allowArguments) { - String exp = expression; - if (exp.startsWith("!")) { - exp = exp.substring(1, exp.length()); - negated = true; - } else { - negated = false; - } +import com.oracle.truffle.dsl.processor.expression.*; +import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate; +import com.oracle.truffle.dsl.processor.java.*; - int argumentStart = exp.indexOf('('); - int endIndex = exp.lastIndexOf(')'); - if (allowArguments && argumentStart != -1 && endIndex != -1) { - guardName = exp.substring(0, argumentStart).trim(); - String arguments = exp.substring(argumentStart + 1, endIndex); - String[] children = arguments.split(","); - for (int i = 0; i < children.length; i++) { - children[i] = children[i].trim(); - } - if (children.length == 1 && children[0].isEmpty()) { - childNames = new String[0]; - } else { - childNames = children; - } - } else { - guardName = exp; - childNames = null; - } +public final class GuardExpression extends MessageContainer { + + private final TemplateMethod source; + private final DSLExpression expression; + + public GuardExpression(TemplateMethod source, DSLExpression expression) { + this.source = source; + this.expression = expression; } - public String[] getChildNames() { - return childNames; - } - - public boolean isResolved() { - return resolvedGuard != null; + @Override + public Element getMessageElement() { + return source.getMessageElement(); } - public String getGuardName() { - return guardName; - } - - public NodeExecutionData[] getResolvedChildren() { - return resolvedChildren; - } - - public void setResolvedChildren(NodeExecutionData[] resolvedChildren) { - this.resolvedChildren = resolvedChildren; - } - - public void setResolvedGuard(GuardData guard) { - this.resolvedGuard = guard; + @Override + public AnnotationMirror getMessageAnnotation() { + return source.getMessageAnnotation(); } @Override - public boolean equals(Object obj) { - if (this == obj) { + public AnnotationValue getMessageAnnotationValue() { + return ElementUtils.getAnnotationValue(getMessageAnnotation(), "guards"); + } + + public DSLExpression getExpression() { + return expression; + } + + public boolean equalsNegated(GuardExpression other) { + boolean negated = false; + DSLExpression thisExpression = expression; + if (thisExpression instanceof Negate) { + negated = true; + thisExpression = ((Negate) thisExpression).getReceiver(); + } + + boolean otherNegated = false; + DSLExpression otherExpression = other.expression; + if (otherExpression instanceof Negate) { + otherNegated = true; + otherExpression = ((Negate) otherExpression).getReceiver(); + } + return Objects.equals(thisExpression, otherExpression) && negated != otherNegated; + } + + public boolean implies(GuardExpression other) { + if (Objects.equals(expression, other.expression)) { return true; - } else if (obj instanceof GuardExpression) { - GuardExpression other = (GuardExpression) obj; - if (isResolved() && other.isResolved()) { - return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated && Arrays.equals(resolvedChildren, other.resolvedChildren); - } else { - boolean equal = guardName.equals(other.guardName) && negated == other.negated; - if (childNames != null && other.childNames != null) { - equal &= Arrays.equals(childNames, other.childNames); - } - return equal; - } } return false; } - @Override - public int hashCode() { - return Objects.hash(guardName, negated, resolvedGuard, resolvedChildren); - } - - public boolean implies(GuardExpression other) { - if (equals(other)) { - return true; - } - - if (isResolved() && other.isResolved()) { - for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) { - if (implies.getGuardName().equals(other.getGuardName())) { - if (implies.isNegated() == other.isNegated()) { - return true; - } - } - } - } - return false; - } - - @Override - public String toString() { - return (negated ? "!" : "") + guardName; - } - - public boolean isNegated() { - return negated; - } - - public GuardData getResolvedGuard() { - return resolvedGuard; - } - } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java Sat Feb 21 19:55:33 2015 +0100 @@ -119,7 +119,7 @@ TypeElement expectError = context.getTruffleTypes().getExpectError(); if (expectError != null) { Element element = getMessageElement(); - AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError); + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError.asType()); if (mirror != null) { List values = ElementUtils.getAnnotationValueList(String.class, mirror, "value"); if (values == null) { @@ -149,7 +149,7 @@ TypeElement expectError = context.getTruffleTypes().getExpectError(); if (expectError != null) { - AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError); + AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError.asType()); if (mirror != null) { List expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value"); boolean found = false; diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Sat Feb 21 19:55:33 2015 +0100 @@ -33,6 +33,7 @@ private final ParameterSpec returnType; private final List optional = new ArrayList<>(); private final List required = new ArrayList<>(); + private final List annotations = new ArrayList<>(); private boolean ignoreAdditionalParameters; private boolean ignoreAdditionalSpecifications; @@ -69,6 +70,10 @@ return spec; } + public List getAnnotations() { + return annotations; + } + public ParameterSpec getReturnType() { return returnType; } @@ -89,15 +94,6 @@ return specs; } - public ParameterSpec findParameterSpec(String name) { - for (ParameterSpec spec : getAll()) { - if (spec.getName().equals(name)) { - return spec; - } - } - return null; - } - public void applyTypeDefinitions(String prefix) { this.typeDefinitions = createTypeDefinitions(prefix); } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Sat Feb 21 19:55:33 2015 +0100 @@ -52,7 +52,7 @@ private final Element accessElement; private final Cardinality cardinality; - private List executeWith = Collections.emptyList(); + private List executeWith = Collections.emptyList(); private NodeData childNode; @@ -66,11 +66,11 @@ this.cardinality = cardinality; } - public List getExecuteWith() { + public List getExecuteWith() { return executeWith; } - public void setExecuteWith(List executeWith) { + public void setExecuteWith(List executeWith) { this.executeWith = executeWith; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Sat Feb 21 19:55:33 2015 +0100 @@ -42,7 +42,6 @@ private final List children; private final List childExecutions; private final List fields; - private final List assumptions; private ParameterSpec instanceParameterSpec; @@ -64,7 +63,6 @@ this.fields = new ArrayList<>(); this.children = new ArrayList<>(); this.childExecutions = new ArrayList<>(); - this.assumptions = new ArrayList<>(); this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false); this.thisExecution.getChild().setNode(this); this.generateFactory = generateFactory; @@ -148,17 +146,13 @@ if (!specialization.isReachable()) { continue; } - if (specialization.isFrameUsedByGuard()) { + if (specialization.isFrameUsed()) { return true; } } return false; } - public boolean isPolymorphic(ProcessorContext context) { - return needsRewrites(context); - } - public List getCasts() { return casts; } @@ -221,10 +215,6 @@ return getTemplateType().asType(); } - public List getAssumptions() { - return assumptions; - } - public boolean needsFactory() { if (specializations == null) { return false; @@ -243,7 +233,7 @@ public boolean supportsFrame() { if (executableTypes != null) { for (ExecutableTypeData execType : getExecutableTypes(-1)) { - if (execType.findParameter("frameValue") == null) { + if (execType.findParameter(TemplateMethod.FRAME_NAME) == null) { return false; } } @@ -431,7 +421,6 @@ dumpProperty(builder, indent, "fields", getChildren()); dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); dumpProperty(builder, indent, "specializations", getSpecializations()); - dumpProperty(builder, indent, "assumptions", getAssumptions()); dumpProperty(builder, indent, "casts", getCasts()); dumpProperty(builder, indent, "messages", collectMessages()); if (getEnclosingNodes().size() > 0) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Sat Feb 21 19:55:33 2015 +0100 @@ -74,11 +74,11 @@ return shortCircuit; } - public String getShortCircuitId() { - return createShortCircuitId(child, index); + public String getIndexedName() { + return createIndexedName(child, index); } - public static String createShortCircuitId(NodeChildData child, int varArgsIndex) { + public static String createIndexedName(NodeChildData child, int varArgsIndex) { String shortCircuitName = child.getName(); if (child.getCardinality().isMany()) { shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]"; diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java Sat Feb 21 19:55:33 2015 +0100 @@ -29,17 +29,19 @@ private final Element messageElement; private final AnnotationMirror messageAnnotation; - private final String name; - private final TypeMirror type; private final boolean generated; private ExecutableElement getter; + private final VariableElement variable; - public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, TypeMirror type, String name, boolean generated) { + public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, VariableElement variableElement, boolean generated) { this.messageElement = messageElement; this.messageAnnotation = messageAnnotation; - this.name = name; - this.type = type; this.generated = generated; + this.variable = variableElement; + } + + public VariableElement getVariable() { + return variable; } public void setGetter(ExecutableElement getter) { @@ -57,11 +59,11 @@ } public String getName() { - return name; + return variable.getSimpleName().toString(); } public TypeMirror getType() { - return type; + return variable.asType(); } public boolean isGenerated() { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Sat Feb 21 19:55:33 2015 +0100 @@ -22,23 +22,23 @@ */ package com.oracle.truffle.dsl.processor.model; +import javax.lang.model.element.*; import javax.lang.model.type.*; -import com.oracle.truffle.dsl.processor.java.*; - public final class Parameter { private final ParameterSpec specification; private TypeData typeSystemType; private TemplateMethod method; - private final String localName; + private String localName; private final int specificationVarArgsIndex; private final int typeVarArgsIndex; - private final TypeMirror actualType; + + private final VariableElement variableElement; - public Parameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex) { + public Parameter(ParameterSpec specification, VariableElement variableElement, int specificationVarArgsIndex, int typeVarArgsIndex) { this.specification = specification; - this.actualType = actualType; + this.variableElement = variableElement; this.typeSystemType = null; this.specificationVarArgsIndex = specificationVarArgsIndex; @@ -51,22 +51,30 @@ this.localName = valueName; } - public Parameter(ParameterSpec specification, TypeData actualType, int specificationIndex, int varArgsIndex) { - this(specification, actualType.getPrimitiveType(), specificationIndex, varArgsIndex); + public Parameter(ParameterSpec specification, TypeData actualType, VariableElement variableElement, int specificationIndex, int varArgsIndex) { + this(specification, variableElement, specificationIndex, varArgsIndex); this.typeSystemType = actualType; } public Parameter(Parameter parameter, TypeData otherType) { - this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex); + this(parameter.specification, otherType, parameter.variableElement, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex); } public Parameter(Parameter parameter) { this.specification = parameter.specification; - this.actualType = parameter.actualType; this.typeSystemType = parameter.typeSystemType; this.specificationVarArgsIndex = parameter.specificationVarArgsIndex; this.localName = parameter.localName; this.typeVarArgsIndex = parameter.typeVarArgsIndex; + this.variableElement = parameter.variableElement; + } + + public void setLocalName(String localName) { + this.localName = localName; + } + + public VariableElement getVariableElement() { + return variableElement; } public int getTypeVarArgsIndex() { @@ -94,7 +102,7 @@ } public TypeMirror getType() { - return actualType; + return variableElement.asType(); } public TypeData getTypeSystemType() { @@ -111,6 +119,7 @@ @Override public String toString() { - return ElementUtils.getSimpleName(actualType); + return "Parameter [localName=" + localName + ", type=" + getType() + ", variableElement=" + variableElement + "]"; } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,6 +24,7 @@ import java.util.*; +import javax.lang.model.element.*; import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.java.*; @@ -114,8 +115,11 @@ return allowedTypes; } - public boolean matches(TypeMirror actualType) { - return allowedTypesIdentifier.contains(ElementUtils.getUniqueIdentifier(actualType)); + public boolean matches(VariableElement variable) { + if (allowedTypesIdentifier != null) { + return allowedTypesIdentifier.contains(ElementUtils.getUniqueIdentifier(variable.asType())); + } + return true; } @Override diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,7 +24,10 @@ import java.util.*; +import javax.lang.model.element.*; + import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.expression.*; import com.oracle.truffle.dsl.processor.java.*; public final class SpecializationData extends TemplateMethod { @@ -40,8 +43,9 @@ private final SpecializationKind kind; private final List exceptions; private List guards = Collections.emptyList(); + private List caches = Collections.emptyList(); + private List assumptionExpressions = Collections.emptyList(); private List shortCircuits; - private List assumptions = Collections.emptyList(); private final Set contains = new TreeSet<>(); private final Set containsNames = new TreeSet<>(); private final Set excludedBy = new TreeSet<>(); @@ -49,6 +53,7 @@ private SpecializationData insertBefore; private boolean reachable; private int index; + private DSLExpression limitExpression; public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List exceptions) { super(template); @@ -62,6 +67,57 @@ } } + public boolean isCacheBoundByGuard(CacheExpression cacheExpression) { + for (GuardExpression expression : getGuards()) { + if (expression.getExpression().findBoundVariableElements().contains(cacheExpression.getParameter().getVariableElement())) { + return true; + } + } + + // check all next binding caches if they are bound by guard + Set boundVariables = cacheExpression.getExpression().findBoundVariableElements(); + boolean found = false; + for (CacheExpression expression : getCaches()) { + if (cacheExpression == expression) { + found = true; + } else if (found) { + if (boundVariables.contains(expression.getParameter().getVariableElement())) { + if (isCacheBoundByGuard(expression)) { + return true; + } + } + } + } + return false; + } + + public boolean isDynamicParameterBound(DSLExpression expression) { + Set boundVariables = expression.findBoundVariableElements(); + for (Parameter parameter : getDynamicParameters()) { + if (boundVariables.contains(parameter.getVariableElement())) { + return true; + } + } + return false; + } + + public Parameter findByVariable(VariableElement variable) { + for (Parameter parameter : getParameters()) { + if (ElementUtils.variableEquals(parameter.getVariableElement(), variable)) { + return parameter; + } + } + return null; + } + + public DSLExpression getLimitExpression() { + return limitExpression; + } + + public void setLimitExpression(DSLExpression limitExpression) { + this.limitExpression = limitExpression; + } + public void setInsertBefore(SpecializationData insertBefore) { this.insertBefore = insertBefore; } @@ -106,6 +162,14 @@ return kind == SpecializationKind.POLYMORPHIC; } + public List getDynamicParameters() { + List uncachedParameters = new ArrayList<>(getParameters()); + for (CacheExpression cacheExpression : getCaches()) { + uncachedParameters.remove(cacheExpression.getParameter()); + } + return uncachedParameters; + } + @Override protected List findChildContainers() { List sinks = new ArrayList<>(); @@ -113,11 +177,13 @@ sinks.addAll(exceptions); } if (guards != null) { - for (GuardExpression guard : guards) { - if (guard.isResolved()) { - sinks.add(guard.getResolvedGuard()); - } - } + sinks.addAll(guards); + } + if (caches != null) { + sinks.addAll(caches); + } + if (assumptionExpressions != null) { + sinks.addAll(assumptionExpressions); } return sinks; } @@ -129,9 +195,10 @@ if (!getGuards().isEmpty()) { return true; } - if (!getAssumptions().isEmpty()) { + if (!getAssumptionExpressions().isEmpty()) { return true; } + for (Parameter parameter : getSignatureParameters()) { NodeChildData child = parameter.getSpecification().getExecution().getChild(); ExecutableTypeData type = child.findExecutableType(parameter.getTypeSystemType()); @@ -183,48 +250,6 @@ return index; } - public boolean isContainedBy(SpecializationData next) { - if (compareTo(next) > 0) { - // must be declared after the current specialization - return false; - } - - Iterator currentSignature = getSignatureParameters().iterator(); - Iterator nextSignature = next.getSignatureParameters().iterator(); - - while (currentSignature.hasNext() && nextSignature.hasNext()) { - TypeData currentType = currentSignature.next().getTypeSystemType(); - TypeData prevType = nextSignature.next().getTypeSystemType(); - - if (!currentType.isImplicitSubtypeOf(prevType)) { - return false; - } - } - - for (String nextAssumption : next.getAssumptions()) { - if (!getAssumptions().contains(nextAssumption)) { - return false; - } - } - - Iterator nextGuards = next.getGuards().iterator(); - while (nextGuards.hasNext()) { - GuardExpression nextGuard = nextGuards.next(); - boolean implied = false; - for (GuardExpression currentGuard : getGuards()) { - if (currentGuard.implies(nextGuard)) { - implied = true; - break; - } - } - if (!implied) { - return false; - } - } - - return true; - } - public NodeData getNode() { return node; } @@ -261,14 +286,6 @@ return shortCircuits; } - public List getAssumptions() { - return assumptions; - } - - public void setAssumptions(List assumptions) { - this.assumptions = assumptions; - } - public SpecializationData findNextSpecialization() { List specializations = node.getSpecializations(); for (int i = 0; i < specializations.size() - 1; i++) { @@ -284,19 +301,40 @@ return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); } - public boolean isFrameUsedByGuard() { - for (GuardExpression guard : getGuards()) { - if (guard.getResolvedGuard() == null) { - continue; - } + public boolean isFrameUsed() { + return getFrame() != null; + } + + public List getCaches() { + return caches; + } + + public void setCaches(List caches) { + this.caches = caches; + } + + public void setAssumptionExpressions(List assumptionExpressions) { + this.assumptionExpressions = assumptionExpressions; + } - for (Parameter param : guard.getResolvedGuard().getParameters()) { - if (ElementUtils.typeEquals(param.getType(), getNode().getFrameType())) { - return true; + public List getAssumptionExpressions() { + return assumptionExpressions; + } + + public boolean hasMultipleInstances() { + if (!getCaches().isEmpty()) { + for (GuardExpression guard : getGuards()) { + DSLExpression guardExpression = guard.getExpression(); + Set boundVariables = guardExpression.findBoundVariableElements(); + if (isDynamicParameterBound(guardExpression)) { + for (CacheExpression cache : getCaches()) { + if (boundVariables.contains(cache.getParameter().getVariableElement())) { + return true; + } + } } } } - return false; } @@ -306,6 +344,12 @@ } if (!prev.getExceptions().isEmpty()) { + // may get excluded by exception + return true; + } + + if (hasMultipleInstances()) { + // may fallthrough due to limit return true; } @@ -321,10 +365,10 @@ } } - for (String prevAssumption : prev.getAssumptions()) { - if (!getAssumptions().contains(prevAssumption)) { - return true; - } + if (!prev.getAssumptionExpressions().isEmpty()) { + // TODO: chumer: we could at least check reachability after trivial assumptions + // not sure if this is worth it. + return true; } Iterator prevGuards = prev.getGuards().iterator(); @@ -339,4 +383,14 @@ return false; } + + public CacheExpression findCache(Parameter resolvedParameter) { + for (CacheExpression cache : getCaches()) { + if (cache.getParameter() == resolvedParameter) { + return cache; + } + } + return null; + } + } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Sat Feb 21 19:55:33 2015 +0100 @@ -35,6 +35,7 @@ */ public class TemplateMethod extends MessageContainer implements Comparable { + public static final String FRAME_NAME = "frameValue"; public static final int NO_NATURAL_ORDER = -1; private String id; @@ -68,6 +69,10 @@ this.id = id; } + public final Parameter getFrame() { + return findParameter(FRAME_NAME); + } + public String createReferenceName() { if (getMethod() == null) { return "-"; @@ -135,16 +140,6 @@ } } - public List getRequiredParameters() { - List requiredParameters = new ArrayList<>(); - for (Parameter parameter : getParameters()) { - if (getSpecification().getRequired().contains(parameter.getSpecification())) { - requiredParameters.add(parameter); - } - } - return requiredParameters; - } - public Iterable getSignatureParameters() { return new FilteredIterable<>(getParameters(), new Predicate() { public boolean evaluate(Parameter value) { @@ -157,16 +152,6 @@ return parameters; } - public List findParameters(ParameterSpec spec) { - List foundParameters = new ArrayList<>(); - for (Parameter param : getReturnTypeAndParameters()) { - if (param.getSpecification().getName().equals(spec.getName())) { - foundParameters.add(param); - } - } - return foundParameters; - } - public Parameter findParameterOrDie(NodeExecutionData execution) { for (Parameter parameter : parameters) { if (parameter.getSpecification().isSignature() && parameter.getSpecification().getExecution() == execution) { @@ -200,11 +185,6 @@ return Collections.unmodifiableList(allParameters); } - public boolean canBeAccessedByInstanceOf(TypeMirror type) { - TypeMirror methodType = ElementUtils.findNearestEnclosingType(getMethod()).asType(); - return ElementUtils.isAssignable(type, methodType) || ElementUtils.isAssignable(methodType, type); - } - public ExecutableElement getMethod() { return method; } @@ -258,20 +238,6 @@ return signature; } - public Parameter getSignatureParameter(int searchIndex) { - int index = 0; - for (Parameter parameter : getParameters()) { - if (!parameter.getSpecification().isSignature()) { - continue; - } - if (index == searchIndex) { - return parameter; - } - index++; - } - return null; - } - public void updateSignature(TypeSignature signature) { // TODO(CH): fails in normal usage - output ok though // assert signature.size() >= 1; @@ -311,19 +277,6 @@ return compare; } - public List getParametersAfter(Parameter genericParameter) { - boolean found = false; - List foundParameters = new ArrayList<>(); - for (Parameter param : getParameters()) { - if (param.getLocalName().equals(genericParameter.getLocalName())) { - found = true; - } else if (found) { - foundParameters.add(param); - } - } - return foundParameters; - } - public int compareBySignature(TemplateMethod compareMethod) { final TypeSystemData typeSystem = getTemplate().getTypeSystem(); if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Sat Feb 21 19:55:33 2015 +0100 @@ -146,15 +146,6 @@ return result; } - public TypeData findType(String simpleName) { - for (TypeData type : types) { - if (ElementUtils.getTypeId(type.getBoxedType()).equals(simpleName)) { - return type; - } - } - return null; - } - public TypeData findTypeData(TypeMirror type) { if (ElementUtils.typeEquals(voidType.getPrimitiveType(), type)) { return voidType; diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -103,10 +103,10 @@ } @Override - public boolean matches(TypeMirror actualType) { + public boolean matches(VariableElement variable) { boolean found = false; for (TypeMirror specType : getAllowedTypes()) { - if (ElementUtils.isAssignable(actualType, specType)) { + if (ElementUtils.isAssignable(variable.asType(), specType)) { found = true; break; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -36,9 +36,11 @@ public class ExecutableTypeMethodParser extends NodeMethodParser { private final List frameTypes; + private final NodeChildData child; - public ExecutableTypeMethodParser(ProcessorContext context, NodeData node, List frameTypes) { + public ExecutableTypeMethodParser(ProcessorContext context, NodeData node, NodeChildData child, List frameTypes) { super(context, node); + this.child = child; this.frameTypes = frameTypes; setParseNullOnError(false); getParser().setEmitErrors(false); @@ -54,9 +56,19 @@ TypeSystemData typeSystem = getNode().getTypeSystem(); List allowedTypes = typeSystem.getPrimitiveTypeMirrors(); Set allowedIdentifiers = typeSystem.getTypeIdentifiers(); - for (ParameterSpec originalSpec : requiredSpecs) { - spec.addRequired(new ParameterSpec(originalSpec, allowedTypes, allowedIdentifiers)); + + if (child != null) { + for (NodeExecutionData executeWith : child.getExecuteWith()) { + ParameterSpec parameter = spec.addRequired(new ParameterSpec(executeWith.getName(), allowedTypes, allowedIdentifiers)); + parameter.setExecution(executeWith); + parameter.setSignature(true); + } + } else { + for (ParameterSpec originalSpec : requiredSpecs) { + spec.addRequired(new ParameterSpec(originalSpec, allowedTypes, allowedIdentifiers)); + } } + spec.setIgnoreAdditionalSpecifications(true); spec.setIgnoreAdditionalParameters(true); spec.setVariableRequiredParameters(true); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java Sat Feb 21 19:47:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.dsl.processor.parser; - -import java.lang.annotation.*; -import java.util.*; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.*; -import com.oracle.truffle.dsl.processor.model.*; - -public class GuardParser extends NodeMethodParser { - - private final GuardExpression expression; - private final TemplateMethod guardedMethod; - - public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, GuardExpression expression) { - super(context, node); - this.expression = expression; - this.guardedMethod = compatibleSource; - getParser().setEmitErrors(false); - setParseNullOnError(false); - } - - @Override - protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) { - return super.createValueParameterSpec(execution); - } - - @Override - public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); - spec.setIgnoreAdditionalSpecifications(true); - spec.getRequired().clear(); - - if (expression.getResolvedChildren() != null) { - for (NodeExecutionData execution : expression.getResolvedChildren()) { - List foundInGuardedMethod = guardedMethod.findByExecutionData(execution); - for (Parameter guardedParameter : foundInGuardedMethod) { - spec.addRequired(createParameterSpec(guardedParameter)); - } - } - } else { - for (Parameter parameter : guardedMethod.getRequiredParameters()) { - spec.addRequired(createParameterSpec(parameter)); - } - } - - return spec; - } - - private ParameterSpec createParameterSpec(Parameter parameter) { - List typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType()); - Set typeIds = new HashSet<>(); - for (TypeMirror typeMirror : typeMirrors) { - typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror)); - } - if (parameter.getSpecification().isSignature()) { - typeIds.retainAll(getTypeSystem().getTypeIdentifiers()); - } - - return new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds); - } - - @Override - protected List nodeTypeMirrors(NodeData nodeData) { - Set typeMirrors = new LinkedHashSet<>(); - typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); - typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors()); - return new ArrayList<>(typeMirrors); - } - - @Override - protected Set nodeTypeIdentifiers(NodeData nodeData) { - return nodeData.getTypeSystem().getTypeIdentifiers(); - } - - @Override - protected ParameterSpec createReturnParameterSpec() { - return new ParameterSpec("returnType", getContext().getType(boolean.class)); - } - - @Override - public boolean isParsable(ExecutableElement method) { - return true; - } - - @Override - public GuardData create(TemplateMethod method, boolean invalid) { - Implies impliesAnnotation = method.getMethod().getAnnotation(Implies.class); - String[] impliesExpressions = new String[0]; - if (impliesAnnotation != null) { - impliesExpressions = impliesAnnotation.value(); - } - List guardExpressions = new ArrayList<>(); - for (String string : impliesExpressions) { - guardExpressions.add(new GuardExpression(string, false)); - } - return new GuardData(method, guardExpressions); - } - - @Override - public Class getAnnotationType() { - return null; - } - -} diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,6 +30,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; import com.oracle.truffle.dsl.processor.model.*; public final class MethodSpecParser { @@ -76,18 +77,13 @@ String id = method.getSimpleName().toString(); TypeMirror returnType = method.getReturnType(); - List parameterTypes = new ArrayList<>(); - for (VariableElement var : method.getParameters()) { - parameterTypes.add(var.asType()); - } - - return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes); + return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, method.getParameters()); } public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, - List parameterTypes) { + List parameterTypes) { ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); - Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1); + Parameter returnTypeMirror = matchParameter(returnTypeSpec, new CodeVariableElement(returnType, "returnType"), -1, -1); if (returnTypeMirror == null) { if (emitErrors) { TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()); @@ -139,11 +135,11 @@ * end matching the required arguments, parsing fails. Parameters prior to the parsed required * ones are cut and used to parse the optional parameters. */ - private List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { + private List parseParameters(MethodSpec spec, List parameterTypes, boolean varArgs) { List parsedRequired = null; int offset = 0; for (; offset <= parameterTypes.size(); offset++) { - List parameters = new ArrayList<>(); + List parameters = new ArrayList<>(); parameters.addAll(parameterTypes.subList(offset, parameterTypes.size())); parsedRequired = parseParametersRequired(spec, parameters, varArgs); if (parsedRequired != null) { @@ -158,7 +154,7 @@ if (parsedRequired.isEmpty() && offset == 0) { offset = parameterTypes.size(); } - List potentialOptionals = parameterTypes.subList(0, offset); + List potentialOptionals = parameterTypes.subList(0, offset); List parsedOptionals = parseParametersOptional(spec, potentialOptionals); if (parsedOptionals == null) { return null; @@ -170,7 +166,7 @@ return finalParameters; } - private List parseParametersOptional(MethodSpec spec, List types) { + private List parseParametersOptional(MethodSpec spec, List types) { List parsedParams = new ArrayList<>(); int typeStartIndex = 0; @@ -178,8 +174,8 @@ outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) { ParameterSpec specification = specifications.get(specIndex); for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) { - TypeMirror actualType = types.get(typeIndex); - Parameter optionalParam = matchParameter(specification, actualType, -1, -1); + VariableElement variable = types.get(typeIndex); + Parameter optionalParam = matchParameter(specification, variable, -1, -1); if (optionalParam != null) { parsedParams.add(optionalParam); typeStartIndex = typeIndex + 1; @@ -195,7 +191,7 @@ return parsedParams; } - private List parseParametersRequired(MethodSpec spec, List types, boolean typeVarArgs) { + private List parseParametersRequired(MethodSpec spec, List types, boolean typeVarArgs) { List parsedParams = new ArrayList<>(); List specifications = spec.getRequired(); boolean specVarArgs = spec.isVariableRequiredParameters(); @@ -204,7 +200,7 @@ ParameterSpec specification; while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) { - TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs); + VariableElement actualType = nextActualType(types, typeIndex, typeVarArgs); if (actualType == null) { if (spec.isIgnoreAdditionalSpecifications()) { break; @@ -230,8 +226,18 @@ specificationIndex++; } + // consume randomly ordered annotated parameters + VariableElement variable; + while ((variable = nextActualType(types, typeIndex, typeVarArgs)) != null) { + Parameter matchedParamter = matchAnnotatedParameter(spec, variable); + if (matchedParamter == null) { + break; + } + parsedParams.add(matchedParamter); + typeIndex++; + } + if (typeIndex < types.size()) { - // additional types available if (spec.isIgnoreAdditionalParameters()) { return parsedParams; } else { @@ -242,6 +248,19 @@ return parsedParams; } + private Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) { + for (ParameterSpec parameterSpec : spec.getAnnotations()) { + if (parameterSpec.matches(variable)) { + Parameter matchedParameter = matchParameter(parameterSpec, variable, -1, -1); + if (matchedParameter != null) { + matchedParameter.setLocalName(variable.getSimpleName().toString()); + return matchedParameter; + } + } + } + return null; + } + private static ParameterSpec nextSpecification(List specifications, int specIndex, boolean varArgs) { if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) { return specifications.get(specifications.size() - 1); @@ -252,12 +271,12 @@ } } - private static TypeMirror nextActualType(List types, int typeIndex, boolean varArgs) { + private static VariableElement nextActualType(List types, int typeIndex, boolean varArgs) { if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) { // unpack varargs array argument - TypeMirror actualType = types.get(types.size() - 1); - if (actualType.getKind() == TypeKind.ARRAY) { - actualType = ((ArrayType) actualType).getComponentType(); + VariableElement actualType = types.get(types.size() - 1); + if (actualType.asType().getKind() == TypeKind.ARRAY) { + actualType = new CodeVariableElement(((ArrayType) actualType.asType()).getComponentType(), actualType.getSimpleName().toString()); } return actualType; } else if (typeIndex < types.size()) { @@ -267,21 +286,21 @@ } } - private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) { - TypeMirror resolvedType = mirror; + private Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) { + TypeMirror resolvedType = variable.asType(); if (hasError(resolvedType)) { return null; } - if (!specification.matches(resolvedType)) { + if (!specification.matches(variable)) { return null; } TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); if (resolvedTypeData != null) { - return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex); + return new Parameter(specification, resolvedTypeData, variable, specificationIndex, varArgsIndex); } else { - return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex); + return new Parameter(specification, variable, specificationIndex, varArgsIndex); } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -89,7 +89,7 @@ } for (NodeExecutionData execution : getNode().getChildExecutions()) { - if (breakName != null && execution.getShortCircuitId().equals(breakName)) { + if (breakName != null && execution.getIndexedName().equals(breakName)) { break; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,11 +30,15 @@ import javax.lang.model.util.*; import javax.tools.Diagnostic.Kind; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.expression.*; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.compiler.*; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror; +import com.oracle.truffle.dsl.processor.java.model.*; import com.oracle.truffle.dsl.processor.model.*; import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind; @@ -98,7 +102,8 @@ } catch (CompileErrorException e) { throw e; } catch (Throwable e) { - throw new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType)), e); + e.addSuppressed(new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType)), e)); + throw e; } if (node == null && !enclosedNodes.isEmpty()) { node = new NodeData(context, rootType); @@ -133,12 +138,14 @@ } NodeData node = parseNodeData(templateType, lookupTypes); + if (node.hasErrors()) { + return node; + } - node.getAssumptions().addAll(parseAssumptions(lookupTypes)); node.getFields().addAll(parseFields(lookupTypes, members)); node.getChildren().addAll(parseChildren(lookupTypes, members)); node.getChildExecutions().addAll(parseExecutions(node.getChildren(), members)); - node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, context.getFrameTypes()).parse(members))); + node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, null, context.getFrameTypes()).parse(members))); initializeExecutableTypes(node); initializeImportGuards(node, lookupTypes, members); @@ -174,8 +181,10 @@ return node; } - private ArrayList loadMembers(TypeElement templateType) { - return new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + private List loadMembers(TypeElement templateType) { + List members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + + return members; } private boolean containsSpecializations(List elements) { @@ -191,7 +200,7 @@ private void initializeImportGuards(NodeData node, List lookupTypes, List elements) { for (TypeElement lookupType : lookupTypes) { - AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportGuards.class); + AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportStatic.class); if (importAnnotation == null) { continue; } @@ -206,29 +215,44 @@ node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass)); continue; } + TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass); - - // hack to reload type is necessary for incremental compiling in eclipse. - // otherwise methods inside of import guard types are just not found. - typeElement = ElementUtils.fromTypeMirror(context.reloadType(typeElement.asType())); - if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) { node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass)); continue; } - - List importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement)); - - for (ExecutableElement importMethod : importMethods) { - if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) { - continue; - } - elements.add(importMethod); - } + elements.addAll(importPublicStaticMembers(typeElement, false)); } } } + private List importPublicStaticMembers(TypeElement importGuardClass, boolean includeConstructors) { + // hack to reload type is necessary for incremental compiling in eclipse. + // otherwise methods inside of import guard types are just not found. + TypeElement typeElement = ElementUtils.fromTypeMirror(context.reloadType(importGuardClass.asType())); + + List members = new ArrayList<>(); + for (Element importElement : processingEnv.getElementUtils().getAllMembers(typeElement)) { + if (!importElement.getModifiers().contains(Modifier.PUBLIC)) { + continue; + } + + if (includeConstructors && importElement.getKind() == ElementKind.CONSTRUCTOR) { + members.add(importElement); + } + + if (!importElement.getModifiers().contains(Modifier.STATIC)) { + continue; + } + + ElementKind kind = importElement.getKind(); + if (kind.isField() || kind == ElementKind.METHOD) { + members.add(importElement); + } + } + return members; + } + private NodeData parseNodeData(TypeElement templateType, List typeHierarchy) { AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); if (typeSystemMirror == null) { @@ -255,24 +279,6 @@ } - private List parseAssumptions(List typeHierarchy) { - List assumptionsList = new ArrayList<>(); - for (int i = typeHierarchy.size() - 1; i >= 0; i--) { - TypeElement type = typeHierarchy.get(i); - AnnotationMirror assumptions = ElementUtils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class); - if (assumptions != null) { - List assumptionStrings = ElementUtils.getAnnotationValueList(String.class, assumptions, "value"); - for (String string : assumptionStrings) { - if (assumptionsList.contains(string)) { - assumptionsList.remove(string); - } - assumptionsList.add(string); - } - } - } - return assumptionsList; - } - private List parseFields(List typeHierarchy, List elements) { Set names = new HashSet<>(); @@ -283,7 +289,7 @@ } if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { String name = field.getSimpleName().toString(); - fields.add(new NodeFieldData(field, null, field.asType(), name, false)); + fields.add(new NodeFieldData(field, null, field, false)); names.add(name); } } @@ -298,7 +304,7 @@ String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name")); TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type"); - NodeFieldData field = new NodeFieldData(typeElement, mirror, type, name, true); + NodeFieldData field = new NodeFieldData(typeElement, mirror, new CodeVariableElement(type, name), true); if (name.isEmpty()) { field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty."); } else if (names.contains(name)) { @@ -396,46 +402,6 @@ } } - for (NodeChildData child : filteredChildren) { - List executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); - AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); - List executeWith = new ArrayList<>(); - for (String executeWithString : executeWithStrings) { - - if (child.getName().equals(executeWithString)) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString); - continue; - } - - NodeChildData found = null; - boolean before = true; - for (NodeChildData resolveChild : filteredChildren) { - if (resolveChild == child) { - before = false; - continue; - } - if (resolveChild.getName().equals(executeWithString)) { - found = resolveChild; - break; - } - } - - if (found == null) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString); - continue; - } else if (!before) { - child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, - executeWithString); - continue; - } - executeWith.add(found); - } - child.setExecuteWith(executeWith); - if (child.getNodeData() == null) { - continue; - } - } - return filteredChildren; } @@ -466,6 +432,7 @@ } } + TypeMirror cacheAnnotation = context.getType(Cached.class); List frameTypes = context.getFrameTypes(); // pre-parse specializations to find signature size for (ExecutableElement method : methods) { @@ -473,10 +440,10 @@ if (mirror == null) { continue; } - int currentArgumentIndex = 0; boolean skipShortCircuit = false; outer: for (VariableElement var : method.getParameters()) { + TypeMirror type = var.asType(); if (currentArgumentIndex == 0) { // skip optionals @@ -486,13 +453,18 @@ } } } + + if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) { + continue outer; + } + int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1; if (childIndex == -1) { continue; } if (!skipShortCircuit) { NodeChildData child = children.get(childIndex); - if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentIndex - childIndex))) { + if (shortCircuits.contains(NodeExecutionData.createIndexedName(child, currentArgumentIndex - childIndex))) { skipShortCircuit = true; continue; } @@ -519,7 +491,7 @@ } int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1; NodeChildData child = children.get(childIndex); - boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex)); + boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex)); executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit)); } return executions; @@ -536,16 +508,11 @@ Parameter frame = execute.getFrame(); TypeMirror resolvedFrameType; - if (frame == null) { - resolvedFrameType = node.getTypeSystem().getVoidType().getPrimitiveType(); - } else { + if (frame != null) { resolvedFrameType = frame.getType(); - } - - if (frameType == null) { - frameType = resolvedFrameType; - } else { - if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) { + if (frameType == null) { + frameType = resolvedFrameType; + } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) { // found inconsistent frame types inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType)); inconsistentFrameTypes.add(ElementUtils.getSimpleName(resolvedFrameType)); @@ -558,6 +525,10 @@ Collections.sort(inconsistentFrameTypesList); node.addError("Invalid inconsistent frame types %s found for the declared execute methods. The frame type must be identical for all execute methods.", inconsistentFrameTypesList); } + if (frameType == null) { + frameType = context.getType(void.class); + } + node.setFrameType(frameType); int totalGenericCount = 0; @@ -627,9 +598,11 @@ } private void initializeChildren(NodeData node) { + initializeExecuteWith(node); + for (NodeChildData child : node.getChildren()) { TypeMirror nodeType = child.getNodeType(); - NodeData fieldNodeData = parseChildNodeData(node, ElementUtils.fromTypeMirror(nodeType)); + NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType)); child.setNode(fieldNodeData); if (fieldNodeData == null || fieldNodeData.hasErrors()) { @@ -649,7 +622,44 @@ } } - private NodeData parseChildNodeData(NodeData parentNode, TypeElement originalTemplateType) { + private static void initializeExecuteWith(NodeData node) { + for (NodeChildData child : node.getChildren()) { + List executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); + AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); + List executeWith = new ArrayList<>(); + for (String executeWithString : executeWithStrings) { + if (child.getName().equals(executeWithString)) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString); + continue; + } + NodeExecutionData found = null; + boolean before = true; + for (NodeExecutionData resolveChild : node.getChildExecutions()) { + if (resolveChild.getChild() == child) { + before = false; + continue; + } + if (resolveChild.getIndexedName().equals(executeWithString)) { + found = resolveChild; + break; + } + } + + if (found == null) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString); + continue; + } else if (!before) { + child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, + executeWithString); + continue; + } + executeWith.add(found); + } + child.setExecuteWith(executeWith); + } + } + + private NodeData parseChildNodeData(NodeData parentNode, NodeChildData child, TypeElement originalTemplateType) { TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { @@ -666,8 +676,10 @@ // Declaration order is not required for child nodes. List members = processingEnv.getElementUtils().getAllMembers(templateType); NodeData node = parseNodeData(templateType, lookupTypes); - - node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, createAllowedChildFrameTypes(parentNode)).parse(members))); + if (node.hasErrors()) { + return node; + } + node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, child, createAllowedChildFrameTypes(parentNode)).parse(members))); node.setFrameType(parentNode.getFrameType()); return node; } @@ -687,31 +699,29 @@ return; } - initializeGuards(elements, node); + initializeExpressions(elements, node); + + if (node.hasErrors()) { + return; + } + initializeGeneric(node); initializeUninitialized(node); initializeOrder(node); initializePolymorphism(node); // requires specializations initializeReachability(node); initializeContains(node); - - if (!node.hasErrors() && !node.getTypeSystem().getOptions().useNewLayout()) { - initializeExceptions(node); - } resolveContains(node); - if (node.getTypeSystem().getOptions().useNewLayout()) { - List specializations = node.getSpecializations(); - for (SpecializationData cur : specializations) { - for (SpecializationData child : specializations) { - if (child != null && child != cur && child.getContains().contains(cur)) { - cur.getExcludedBy().add(child); - } + List specializations = node.getSpecializations(); + for (SpecializationData cur : specializations) { + for (SpecializationData contained : cur.getContains()) { + if (contained != cur) { + contained.getExcludedBy().add(cur); } } } - // verify specialization parameter length initializeSpecializationIdsWithMethodNames(node.getSpecializations()); } @@ -763,40 +773,6 @@ } } - private static void initializeExceptions(NodeData node) { - List specializations = node.getSpecializations(); - - for (int i = 0; i < specializations.size(); i++) { - SpecializationData cur = specializations.get(i); - if (cur.getExceptions().isEmpty()) { - continue; - } - SpecializationData next = i + 1 < specializations.size() ? specializations.get(i + 1) : null; - - if (!cur.isContainedBy(next)) { - next.addError("This specialiation is not a valid exceptional rewrite target for %s. To fix this make %s compatible to %s or remove the exceptional rewrite.", - cur.createReferenceName(), next != null ? next.createReferenceName() : "-", cur.createReferenceName()); - continue; - } - Set nextContains = next != null ? next.getContains() : Collections. emptySet(); - if (!nextContains.contains(cur)) { - nextContains.add(cur); - } - } - - for (SpecializationData cur : specializations) { - if (cur.getExceptions().isEmpty()) { - continue; - } - for (SpecializationData child : specializations) { - if (child != null && child != cur && child.getContains().contains(cur)) { - cur.getExcludedBy().add(child); - } - } - } - - } - private static void initializeContains(NodeData node) { for (SpecializationData specialization : node.getSpecializations()) { Set resolvedSpecializations = specialization.getContains(); @@ -810,14 +786,10 @@ AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName); } else { - if (!foundSpecialization.isContainedBy(specialization)) { + if (foundSpecialization.compareTo(specialization) > 0) { AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains"); if (foundSpecialization.compareTo(specialization) > 0) { specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName); - } else { - specialization.addError(value, - "The contained specialization '%s' is not fully compatible. The contained specialization must be strictly more generic than the containing one.", - includeName); } } @@ -964,81 +936,196 @@ return changed; } - private void initializeGuards(List elements, NodeData node) { - Map> potentialGuards = new HashMap<>(); - for (SpecializationData specialization : node.getSpecializations()) { - for (GuardExpression exp : specialization.getGuards()) { - potentialGuards.put(exp.getGuardName(), null); - } + private void initializeExpressions(List elements, NodeData node) { + List members = filterNotAccessibleElements(node.getTemplateType(), elements); + + List fields = new ArrayList<>(); + for (NodeFieldData field : node.getFields()) { + fields.add(field.getVariable()); } - TypeMirror booleanType = context.getType(boolean.class); - for (ExecutableElement potentialGuard : ElementFilter.methodsIn(elements)) { - if (potentialGuard.getModifiers().contains(Modifier.PRIVATE)) { - continue; - } - String methodName = potentialGuard.getSimpleName().toString(); - if (!potentialGuards.containsKey(methodName)) { + for (SpecializationData specialization : node.getSpecializations()) { + if (specialization.getMethod() == null) { continue; } - if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) { + List specializationMembers = new ArrayList<>(members.size() + specialization.getParameters().size() + fields.size()); + for (Parameter p : specialization.getParameters()) { + specializationMembers.add(p.getVariableElement()); + } + specializationMembers.addAll(fields); + specializationMembers.addAll(members); + DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers); + + initializeCaches(specialization, resolver); + initializeGuards(specialization, resolver); + if (specialization.hasErrors()) { continue; } + initializeLimit(specialization, resolver); + initializeAssumptions(specialization, resolver); + } + } + + private void initializeAssumptions(SpecializationData specialization, DSLExpressionResolver resolver) { + final DeclaredType assumptionType = context.getDeclaredType(Assumption.class); + final TypeMirror assumptionArrayType = new ArrayCodeTypeMirror(assumptionType); + final List assumptionDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions"); + List assumptionExpressions = new ArrayList<>(); + int assumptionId = 0; + for (String assumption : assumptionDefinitions) { + AssumptionExpression assumptionExpression; + DSLExpression expression = null; + try { + expression = DSLExpression.parse(assumption); + expression.accept(resolver); + assumptionExpression = new AssumptionExpression(specialization, expression, "assumption" + assumptionId); + if (!ElementUtils.isAssignable(expression.getResolvedType(), assumptionType) && !ElementUtils.isAssignable(expression.getResolvedType(), assumptionArrayType)) { + assumptionExpression.addError("Incompatible return type %s. Assumptions must be assignable to %s or %s.", ElementUtils.getSimpleName(expression.getResolvedType()), + ElementUtils.getSimpleName(assumptionType), ElementUtils.getSimpleName(assumptionArrayType)); + } + if (specialization.isDynamicParameterBound(expression)) { + specialization.addError("Assumption expressions must not bind dynamic parameter values."); + } + } catch (InvalidExpressionException e) { + assumptionExpression = new AssumptionExpression(specialization, null, "assumption" + assumptionId); + assumptionExpression.addError("Error parsing expression '%s': %s", assumption, e.getMessage()); + } + assumptionExpressions.add(assumptionExpression); + } + specialization.setAssumptionExpressions(assumptionExpressions); + } + + private void initializeLimit(SpecializationData specialization, DSLExpressionResolver resolver) { + AnnotationValue annotationValue = ElementUtils.getAnnotationValue(specialization.getMessageAnnotation(), "limit"); + + String limitValue; + if (annotationValue == null) { + limitValue = ""; + } else { + limitValue = (String) annotationValue.getValue(); + } + if (limitValue.isEmpty()) { + limitValue = "3"; + } else if (!specialization.hasMultipleInstances()) { + specialization.addWarning(annotationValue, "The limit expression has no effect. Multiple specialization instantiations are impossible for this specialization."); + return; + } + + TypeMirror expectedType = context.getType(int.class); + try { + DSLExpression expression = DSLExpression.parse(limitValue); + expression.accept(resolver); + if (!ElementUtils.typeEquals(expression.getResolvedType(), expectedType)) { + specialization.addError(annotationValue, "Incompatible return type %s. Limit expressions must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()), + ElementUtils.getSimpleName(expectedType)); + } + if (specialization.isDynamicParameterBound(expression)) { + specialization.addError(annotationValue, "Limit expressions must not bind dynamic parameter values."); + } - List potentialMethods = potentialGuards.get(methodName); - if (potentialMethods == null) { - potentialMethods = new ArrayList<>(); - potentialGuards.put(methodName, potentialMethods); + specialization.setLimitExpression(expression); + } catch (InvalidExpressionException e) { + specialization.addError(annotationValue, "Error parsing expression '%s': %s", limitValue, e.getMessage()); + } + } + + private void initializeCaches(SpecializationData specialization, DSLExpressionResolver resolver) { + TypeMirror cacheMirror = context.getType(Cached.class); + List expressions = new ArrayList<>(); + for (Parameter parameter : specialization.getParameters()) { + AnnotationMirror annotationMirror = ElementUtils.findAnnotationMirror(parameter.getVariableElement().getAnnotationMirrors(), cacheMirror); + if (annotationMirror != null) { + String initializer = ElementUtils.getAnnotationValue(String.class, annotationMirror, "value"); + + TypeMirror parameterType = parameter.getType(); + + DSLExpressionResolver localResolver = resolver; + if (parameterType.getKind() == TypeKind.DECLARED) { + localResolver = localResolver.copy(importPublicStaticMembers(ElementUtils.fromTypeMirror(parameterType), true)); + } + + CacheExpression cacheExpression; + DSLExpression expression = null; + try { + expression = DSLExpression.parse(initializer); + expression.accept(localResolver); + cacheExpression = new CacheExpression(parameter, annotationMirror, expression); + if (!ElementUtils.typeEquals(expression.getResolvedType(), parameter.getType())) { + cacheExpression.addError("Incompatible return type %s. The expression type must be equal to the parameter type %s.", ElementUtils.getSimpleName(expression.getResolvedType()), + ElementUtils.getSimpleName(parameter.getType())); + } + } catch (InvalidExpressionException e) { + cacheExpression = new CacheExpression(parameter, annotationMirror, null); + cacheExpression.addError("Error parsing expression '%s': %s", initializer, e.getMessage()); + } + expressions.add(cacheExpression); } - potentialMethods.add(potentialGuard); + } + specialization.setCaches(expressions); + + if (specialization.hasErrors()) { + return; } - for (SpecializationData specialization : node.getSpecializations()) { - for (GuardExpression exp : specialization.getGuards()) { - resolveGuardExpression(node, specialization, potentialGuards, exp); + // verify that cache expressions are bound in the correct order. + for (int i = 0; i < expressions.size(); i++) { + CacheExpression currentExpression = expressions.get(i); + Set boundVariables = currentExpression.getExpression().findBoundVariableElements(); + for (int j = i + 1; j < expressions.size(); j++) { + CacheExpression boundExpression = expressions.get(j); + if (boundVariables.contains(boundExpression.getParameter().getVariableElement())) { + currentExpression.addError("The initializer expression of parameter '%s' binds unitialized parameter '%s. Reorder the parameters to resolve the problem.", + currentExpression.getParameter().getLocalName(), boundExpression.getParameter().getLocalName()); + break; + } } } } - private void resolveGuardExpression(NodeData node, TemplateMethod source, Map> guards, GuardExpression expression) { - List availableGuards = guards.get(expression.getGuardName()); - if (availableGuards == null) { - source.addError("No compatible guard with method name '%s' found.", expression.getGuardName()); - return; + private void initializeGuards(SpecializationData specialization, DSLExpressionResolver resolver) { + final TypeMirror booleanType = context.getType(boolean.class); + List guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); + List guardExpressions = new ArrayList<>(); + for (String guard : guardDefinitions) { + GuardExpression guardExpression; + DSLExpression expression = null; + try { + expression = DSLExpression.parse(guard); + expression.accept(resolver); + guardExpression = new GuardExpression(specialization, expression); + if (!ElementUtils.typeEquals(expression.getResolvedType(), booleanType)) { + guardExpression.addError("Incompatible return type %s. Guards must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()), ElementUtils.getSimpleName(booleanType)); + } + } catch (InvalidExpressionException e) { + guardExpression = new GuardExpression(specialization, null); + guardExpression.addError("Error parsing expression '%s': %s", guard, e.getMessage()); + } + guardExpressions.add(guardExpression); } + specialization.setGuards(guardExpressions); + } - String[] childNames = expression.getChildNames(); - if (childNames != null) { - NodeExecutionData[] resolvedExecutions = new NodeExecutionData[childNames.length]; - for (int i = 0; i < childNames.length; i++) { - String childName = childNames[i]; - NodeExecutionData execution = node.findExecutionByExpression(childName); - if (execution == null) { - source.addError("Guard parameter '%s' for guard '%s' could not be mapped to a declared child node.", childName, expression.getGuardName()); - return; + private static List filterNotAccessibleElements(TypeElement templateType, List elements) { + String packageName = ElementUtils.getPackageName(templateType); + List filteredElements = new ArrayList<>(elements); + for (Element element : elements) { + Modifier visibility = ElementUtils.getVisibility(element.getModifiers()); + if (visibility == Modifier.PRIVATE) { + continue; + } else if (visibility == null) { + String elementPackageName = ElementUtils.getPackageName(element.getEnclosingElement().asType()); + if (!Objects.equals(packageName, elementPackageName) && !elementPackageName.equals("java.lang")) { + continue; } - resolvedExecutions[i] = execution; } - expression.setResolvedChildren(resolvedExecutions); + + filteredElements.add(element); } - - GuardParser parser = new GuardParser(context, node, source, expression); - List matchingGuards = parser.parse(availableGuards); - if (!matchingGuards.isEmpty() && matchingGuards.get(0) != null) { - expression.setResolvedGuard(matchingGuards.get(0)); - } else { - MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation()); - spec.applyTypeDefinitions("types"); - source.addError("No guard with name '%s' matched the required signature. Expected signature: %n%s", expression.getGuardName(), spec.toSignatureString("guard")); - } + return filteredElements; } private void initializeGeneric(final NodeData node) { - if (!node.needsRewrites(context)) { - return; - } - List generics = new ArrayList<>(); for (SpecializationData spec : node.getSpecializations()) { if (spec.isFallback()) { @@ -1068,10 +1155,10 @@ GenericParser parser = new GenericParser(context, node); MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null); - List parameterTypes = new ArrayList<>(); + List parameterTypes = new ArrayList<>(); int signatureIndex = 1; for (ParameterSpec spec : specification.getRequired()) { - parameterTypes.add(createGenericType(spec, node.getSpecializations(), signatureIndex)); + parameterTypes.add(new CodeVariableElement(createGenericType(spec, node.getSpecializations(), signatureIndex), "arg" + signatureIndex)); if (spec.isSignature()) { signatureIndex++; } @@ -1196,7 +1283,7 @@ continue; } shortCircuitExecutions.add(execution); - String valueName = execution.getShortCircuitId(); + String valueName = execution.getIndexedName(); List availableCircuits = groupedShortCircuits.get(valueName); if (availableCircuits == null || availableCircuits.isEmpty()) { @@ -1252,7 +1339,7 @@ List assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size()); for (NodeExecutionData shortCircuit : shortCircuitExecutions) { - List availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId()); + List availableShortCuts = groupedShortCircuits.get(shortCircuit.getIndexedName()); ShortCircuitData genericShortCircuit = null; ShortCircuitData compatibleShortCircuit = null; @@ -1392,62 +1479,22 @@ } } - private void verifyConstructors(NodeData nodeData) { - if (nodeData.getTypeSystem().getOptions().useNewLayout()) { - List constructors = ElementFilter.constructorsIn(nodeData.getTemplateType().getEnclosedElements()); - if (constructors.isEmpty()) { - return; - } - - boolean oneNonPrivate = false; - for (ExecutableElement constructor : constructors) { - if (ElementUtils.getVisibility(constructor.getModifiers()) != Modifier.PRIVATE) { - oneNonPrivate = true; - break; - } - } - if (!oneNonPrivate && !nodeData.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { - nodeData.addError("At least one constructor must be non-private."); - } - return; - } - if (!nodeData.needsRewrites(context)) { - // no specialization constructor is needed if the node never rewrites. + private static void verifyConstructors(NodeData nodeData) { + List constructors = ElementFilter.constructorsIn(nodeData.getTemplateType().getEnclosedElements()); + if (constructors.isEmpty()) { return; } - TypeElement type = ElementUtils.fromTypeMirror(nodeData.getNodeType()); - List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); - - boolean parametersFound = false; + boolean oneNonPrivate = false; for (ExecutableElement constructor : constructors) { - if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) { - parametersFound = true; + if (ElementUtils.getVisibility(constructor.getModifiers()) != Modifier.PRIVATE) { + oneNonPrivate = true; + break; } } - if (!parametersFound) { - return; + if (!oneNonPrivate && !nodeData.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + nodeData.addError("At least one constructor must be non-private."); } - for (ExecutableElement e : constructors) { - if (e.getParameters().size() == 1) { - TypeMirror firstArg = e.getParameters().get(0).asType(); - if (ElementUtils.typeEquals(firstArg, nodeData.getNodeType())) { - if (e.getModifiers().contains(Modifier.PRIVATE)) { - nodeData.addError("The specialization constructor must not be private."); - } else if (constructors.size() <= 1) { - nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); - } - return; - } - } - } - - // not found - nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", ElementUtils.getSimpleName(type), ElementUtils.getSimpleName(type)); - } - - public static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) { - return constructor.getParameters().size() == 1 && ElementUtils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection()); } private AnnotationMirror findFirstAnnotation(List elements, Class annotation) { diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -42,7 +42,7 @@ shortCircuitValues = new HashSet<>(); for (NodeExecutionData execution : node.getChildExecutions()) { if (execution.isShortCircuit()) { - shortCircuitValues.add(execution.getShortCircuitId()); + shortCircuitValues.add(execution.getIndexedName()); } } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Sat Feb 21 19:55:33 2015 +0100 @@ -24,10 +24,6 @@ import java.util.*; -import javax.lang.model.type.*; - -import com.oracle.truffle.dsl.processor.*; -import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.model.*; import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature; @@ -37,7 +33,6 @@ */ public final class SpecializationGroup { - private final List assumptions; private final List typeGuards; private final List guards; @@ -49,12 +44,10 @@ private SpecializationGroup(SpecializationData data) { this.node = data.getNode(); - this.assumptions = new ArrayList<>(); this.typeGuards = new ArrayList<>(); this.guards = new ArrayList<>(); this.specialization = data; - this.assumptions.addAll(data.getAssumptions()); TypeSignature sig = data.getTypeSignature(); for (int i = 1; i < sig.size(); i++) { typeGuards.add(new TypeGuard(sig.get(i), i - 1)); @@ -62,9 +55,8 @@ this.guards.addAll(data.getGuards()); } - public SpecializationGroup(List children, List assumptionMatches, List typeGuardsMatches, List guardMatches) { + public SpecializationGroup(List children, List typeGuardsMatches, List guardMatches) { assert !children.isEmpty() : "children must not be empty"; - this.assumptions = assumptionMatches; this.typeGuards = typeGuardsMatches; this.guards = guardMatches; this.node = children.get(0).node; @@ -81,17 +73,8 @@ return collectedGuards; } - public TypeGuard findTypeGuard(int signatureIndex) { - for (TypeGuard guard : typeGuards) { - if (guard.getSignatureIndex() == signatureIndex) { - return guard; - } - } - return null; - } - public List findElseConnectableGuards() { - if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) { + if (!getTypeGuards().isEmpty()) { return Collections.emptyList(); } @@ -126,7 +109,7 @@ } GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size()); - if (guard.getResolvedGuard().getMethod().equals(previousGuard.getResolvedGuard().getMethod()) && guard.isNegated() != previousGuard.isNegated()) { + if (guard.equalsNegated(previousGuard)) { return guard; } return null; @@ -146,10 +129,6 @@ return parent; } - public List getAssumptions() { - return assumptions; - } - public List getTypeGuards() { return typeGuards; } @@ -174,23 +153,12 @@ return null; } - List assumptionMatches = new ArrayList<>(); List typeGuardsMatches = new ArrayList<>(); List guardMatches = new ArrayList<>(); SpecializationGroup first = groups.get(0); List others = groups.subList(1, groups.size()); - outer: for (String assumption : first.assumptions) { - for (SpecializationGroup other : others) { - if (!other.assumptions.contains(assumption)) { - // assumptions can be combined unordered - continue outer; - } - } - assumptionMatches.add(assumption); - } - outer: for (TypeGuard typeGuard : first.typeGuards) { for (SpecializationGroup other : others) { if (!other.typeGuards.contains(typeGuard)) { @@ -214,71 +182,23 @@ // check for guards for required type casts for (Iterator iterator = guardMatches.iterator(); iterator.hasNext();) { GuardExpression guardMatch = iterator.next(); - - int signatureIndex = 0; - for (Parameter parameter : guardMatch.getResolvedGuard().getParameters()) { - signatureIndex++; - if (!parameter.getSpecification().isSignature()) { - continue; - } - - TypeMirror guardType = parameter.getType(); - - // object guards can be safely moved up - if (ElementUtils.isObject(guardType)) { - continue; - } - - // generic guards can be safely moved up - SpecializationData generic = first.node.getGenericSpecialization(); - if (generic != null) { - Parameter genericParameter = generic.findParameter(parameter.getLocalName()); - if (genericParameter != null && ElementUtils.typeEquals(genericParameter.getType(), guardType)) { - continue; - } - } - - // signature index required for moving up guards - if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) { - continue; - } - + if (!guardMatch.getExpression().findBoundVariables().isEmpty()) { iterator.remove(); - break; } + // TODO we need to be smarter here with bound parameters. } - if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) { + if (typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) { return null; } for (SpecializationGroup group : groups) { - group.assumptions.removeAll(assumptionMatches); group.typeGuards.removeAll(typeGuardsMatches); group.guards.removeAll(guardMatches); } List newChildren = new ArrayList<>(groups); - return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches); - } - - private boolean containsTypeGuardIndex(int index) { - if (containsIndex(typeGuards, index)) { - return true; - } - if (parent != null) { - return parent.containsTypeGuardIndex(index); - } - return false; - } - - private static boolean containsIndex(List typeGuards, int signatureIndex) { - for (TypeGuard guard : typeGuards) { - if (guard.signatureIndex == signatureIndex) { - return true; - } - } - return false; + return new SpecializationGroup(newChildren, typeGuardsMatches, guardMatches); } public static SpecializationGroup create(SpecializationData specialization) { @@ -290,12 +210,12 @@ for (SpecializationData specialization : specializations) { groups.add(new SpecializationGroup(specialization)); } - return new SpecializationGroup(createCombinationalGroups(groups), Collections. emptyList(), Collections. emptyList(), Collections. emptyList()); + return new SpecializationGroup(createCombinationalGroups(groups), Collections. emptyList(), Collections. emptyList()); } @Override public String toString() { - return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]"; + return "SpecializationGroup [typeGuards=" + typeGuards + ", guards=" + guards + "]"; } private static List createCombinationalGroups(List groups) { @@ -423,26 +343,16 @@ } } - public boolean isTypeGuardUsedInAnyGuardBelow(ProcessorContext context, SpecializationData source, TypeGuard typeGuard) { - NodeExecutionData execution = source.getNode().getChildExecutions().get(typeGuard.getSignatureIndex()); - - for (GuardExpression guard : guards) { - List guardParameters = guard.getResolvedGuard().findByExecutionData(execution); - Parameter sourceParameter = source.getSignatureParameter(typeGuard.getSignatureIndex()); - for (Parameter guardParameter : guardParameters) { - if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) { - return true; - } - } + public SpecializationGroup getPrevious() { + if (getParent() == null) { + return null; } - for (SpecializationGroup group : getChildren()) { - if (group.isTypeGuardUsedInAnyGuardBelow(context, source, typeGuard)) { - return true; - } + List parentChildren = getParent().getChildren(); + int index = parentChildren.indexOf(this); + if (index <= 0) { + return null; } - - return false; + return parentChildren.get(index - 1); } - } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -42,7 +42,9 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, true, null); + MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); + spec.getAnnotations().add(new AnnotatedParameterSpec(getContext().getDeclaredType(Cached.class))); + return spec; } @Override @@ -92,13 +94,6 @@ specialization.setInsertBeforeName(insertBeforeName); } - List guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); - List guardExpressions = new ArrayList<>(); - for (String guardDef : guardDefs) { - guardExpressions.add(new GuardExpression(guardDef, true)); - } - specialization.setGuards(guardExpressions); - List containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains"); Set containsNames = specialization.getContainsNames(); containsNames.clear(); @@ -114,15 +109,6 @@ } - List assumptionDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions"); - specialization.setAssumptions(assumptionDefs); - - for (String assumption : assumptionDefs) { - if (!getNode().getAssumptions().contains(assumption)) { - specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption); - } - } - return specialization; } } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java Sat Feb 21 19:55:33 2015 +0100 @@ -132,7 +132,7 @@ return null; } - public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List parameterTypes) { + public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List parameterTypes) { TemplateMethod method = parser.parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes); if (method != null) { return create(method, method.hasErrors()); diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java --- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java Sat Feb 21 19:55:33 2015 +0100 @@ -30,7 +30,7 @@ import com.oracle.truffle.object.Locations.ValueLocation; import com.oracle.truffle.object.debug.*; -public abstract class DynamicObjectImpl implements DynamicObject, Cloneable { +public abstract class DynamicObjectImpl extends DynamicObject implements Cloneable { private ShapeImpl shape; public static final DebugCounter reshapeCount = DebugCounter.create("Reshape count"); @@ -49,6 +49,7 @@ return getShape(); } + @Override public ShapeImpl getShape() { return shape; } @@ -64,6 +65,7 @@ setShapeAndResize(getShape(), newShape); } + @Override public final void setShapeAndResize(Shape oldShape, Shape newShape) { assert getShape() == oldShape : "wrong old shape"; if (oldShape != newShape) { @@ -81,6 +83,7 @@ * * @see #setShapeAndResize(Shape, Shape) */ + @Override public final void setShapeAndGrow(Shape oldShape, Shape newShape) { assert getShape() == oldShape : "wrong old shape"; if (oldShape != newShape) { @@ -183,6 +186,7 @@ } } + @Override @TruffleBoundary public boolean changeFlags(Object id, int newFlags) { Shape oldShape = getShape(); @@ -199,6 +203,7 @@ } } + @Override @TruffleBoundary public boolean changeFlags(Object id, FlagsFunction updateFunction) { Shape oldShape = getShape(); @@ -271,6 +276,7 @@ return getShape().getObjectType().hashCode(this); } + @Override @TruffleBoundary public Object get(Object id, Object defaultValue) { Property existing = getShape().getProperty(id); @@ -281,6 +287,7 @@ } } + @Override @TruffleBoundary public boolean set(Object id, Object value) { Property existing = getShape().getProperty(id); @@ -292,6 +299,7 @@ } } + @Override @TruffleBoundary public void define(Object id, Object value, int flags) { ShapeImpl oldShape = getShape(); @@ -318,6 +326,7 @@ } } + @Override @TruffleBoundary public void define(Object id, Object value, int flags, LocationFactory locationFactory) { ShapeImpl oldShape = getShape(); @@ -333,6 +342,7 @@ } } + @Override @TruffleBoundary public boolean delete(Object id) { ShapeImpl oldShape = getShape(); @@ -347,14 +357,17 @@ } } + @Override public int size() { return getShape().getPropertyCount(); } + @Override public boolean isEmpty() { return size() == 0; } + @Override public final boolean updateShape() { return getShape().getLayout().getStrategy().updateShape(this); } diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Sat Feb 21 19:55:33 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; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java --- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Sat Feb 21 19:55:33 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 @@ -218,8 +218,8 @@ // Attach an instrument to every probe tagged as an assignment for (Probe probe : Probe.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) { - SLPrintAssigmentValueReciever slPrintAssigmentValueReceiver = new SLPrintAssigmentValueReciever(printer); - probe.attach(Instrument.create(slPrintAssigmentValueReceiver, "SL print assignment value")); + SLPrintAssigmentValueListener slPrintAssigmentValueListener = new SLPrintAssigmentValueListener(printer); + probe.attach(Instrument.create(slPrintAssigmentValueListener, "SL print assignment value")); } SLFunction main = slContext.getFunctionRegistry().lookup("main"); @@ -271,16 +271,16 @@ } /** - * This sample instrument receiver provides prints the value of an assignment (after the + * This sample instrument listener provides prints the value of an assignment (after the * assignment is complete) to the {@link PrintStream} specified in the constructor. This * instrument can only be attached to a wrapped {@link SLWriteLocalVariableNode}, but provides * no guards to protect it from being attached elsewhere. */ - public final class SLPrintAssigmentValueReciever extends DefaultEventReceiver { + public final class SLPrintAssigmentValueListener extends DefaultEventListener { private PrintStream output; - public SLPrintAssigmentValueReciever(PrintStream output) { + public SLPrintAssigmentValueListener(PrintStream output) { this.output = output; } diff -r 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -94,7 +94,7 @@ * To implement these semantics, we tell the Truffle DSL to use a custom guard. The guard * function is defined in {@link #isString this class}, but could also be in any superclass. */ - @Specialization(guards = "isString") + @Specialization(guards = "isString(left, right)") @TruffleBoundary protected String add(Object left, Object right) { return left.toString() + right.toString(); diff -r 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c 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 Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java Sat Feb 21 19:55:33 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 82b5899f20cb -r db19eba20b9c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java Sat Feb 21 19:47:33 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java Sat Feb 21 19:55:33 2015 +0100 @@ -49,15 +49,15 @@ /** * Specialized method to write a primitive {@code long} value. This is only possible if the * local variable also has currently the type {@code long}, therefore a Truffle DSL - * {@link #isLongKind() custom guard} is specified. + * {@link #isLongKind(VirtualFrame) custom guard} is specified. */ - @Specialization(guards = "isLongKind") + @Specialization(guards = "isLongKind(frame)") protected long writeLong(VirtualFrame frame, long value) { frame.setLong(getSlot(), value); return value; } - @Specialization(guards = "isBooleanKind") + @Specialization(guards = "isBooleanKind(frame)") protected boolean writeBoolean(VirtualFrame frame, boolean value) { frame.setBoolean(getSlot(), value); return value; @@ -91,11 +91,13 @@ /** * Guard function that the local variable has the type {@code long}. */ - protected boolean isLongKind() { + @SuppressWarnings("unused") + protected boolean isLongKind(VirtualFrame frame) { return isKind(FrameSlotKind.Long); } - protected boolean isBooleanKind() { + @SuppressWarnings("unused") + protected boolean isBooleanKind(VirtualFrame frame) { return isKind(FrameSlotKind.Boolean); } diff -r 82b5899f20cb -r db19eba20b9c hotspot/.cproject --- a/hotspot/.cproject Sat Feb 21 19:47:33 2015 +0100 +++ b/hotspot/.cproject Sat Feb 21 19:55:33 2015 +0100 @@ -45,7 +45,6 @@ -