# HG changeset patch # User Thomas Wuerthinger # Date 1423770440 -3600 # Node ID 57c53b1044a769bddb45170af0020608910650e8 # Parent fcefaa7f103d0980d5aa75aa4aeceb91ff521b06# Parent 2778032e1beb9282d2bd41297c696e5a143d3dd7 Merge. diff -r fcefaa7f103d -r 57c53b1044a7 CHANGELOG.md --- a/CHANGELOG.md Thu Feb 12 20:46:56 2015 +0100 +++ b/CHANGELOG.md Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Thu Feb 12 20:47:20 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,12 @@ private ArrayList annotations; - private Assumptions assumptions; + private Assumption[] assumptions; + + /** + * The list of the methods whose bytecodes were used as input to the compilation. + */ + private ResolvedJavaMethod[] methods; public CompilationResult() { this(null); @@ -564,12 +570,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 +612,34 @@ 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. + */ + public void setMethods(ResolvedJavaMethod[] methods) { + this.methods = methods; + } + + /** + * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the methods whose bytecodes + * were used as input to the compilation. + */ + public Collection getMethods() { + return methods == null ? Collections.emptyList() : Arrays.asList(methods); } public DataSection getDataSection() { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Thu Feb 12 20:47:20 2015 +0100 @@ -145,9 +145,9 @@ throw Debug.handle(e); } - try (Scope s = Debug.scope("LowLevelTier", this)) { - LowLevelSuites lowLevelSuites = backend.getSuites().getDefaultLowLevelSuites(); - return GraalCompiler.emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, gen, lowLevelSuites); + try (Scope s = Debug.scope("LIRTier", this)) { + LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(); + return GraalCompiler.emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, gen, lirSuites); } catch (Throwable e) { throw Debug.handle(e); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Thu Feb 12 20:47:20 2015 +0100 @@ -24,6 +24,8 @@ 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.*; @@ -67,8 +69,8 @@ } // emitCode - Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); - GraalCompiler.emitCode(backend, assumptions, res, compilationResult, installedCodeOwner, factory); + Assumptions assumptions = OptAssumptions.getValue() ? new Assumptions() : null; + GraalCompiler.emitCode(backend, assumptions, Collections.emptySet(), res, compilationResult, installedCodeOwner, factory); return compilationResult; } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Thu Feb 12 20:47:20 2015 +0100 @@ -122,23 +122,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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Thu Feb 12 20:47:20 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.*; @@ -305,9 +305,8 @@ } 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Thu Feb 12 20:47:20 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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Feb 12 20:47:20 2015 +0100 @@ -53,6 +53,7 @@ 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.*; @@ -71,7 +72,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. @@ -90,7 +91,7 @@ private final Providers providers; private final Backend backend; private final DerivedOptionValue suites; - private final DerivedOptionValue lowLevelSuites; + private final DerivedOptionValue lirSuites; /** * Can be overridden by unit tests to verify properties of the graph. @@ -166,8 +167,8 @@ return ret; } - protected LowLevelSuites createLowLevelSuites() { - LowLevelSuites ret = backend.getSuites().createLowLevelSuites(); + protected LIRSuites createLIRSuites() { + LIRSuites ret = backend.getSuites().createLIRSuites(); return ret; } @@ -175,7 +176,7 @@ this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); this.providers = getBackend().getProviders(); this.suites = new DerivedOptionValue<>(this::createSuites); - this.lowLevelSuites = new DerivedOptionValue<>(this::createLowLevelSuites); + this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); installSubstitutions(); } @@ -196,7 +197,7 @@ } this.providers = backend.getProviders(); this.suites = new DerivedOptionValue<>(this::createSuites); - this.lowLevelSuites = new DerivedOptionValue<>(this::createLowLevelSuites); + this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); installSubstitutions(); } @@ -364,8 +365,8 @@ return suites.getValue(); } - protected LowLevelSuites getLowLevelSuites() { - return lowLevelSuites.getValue(); + protected LIRSuites getLIRSuites() { + return lirSuites.getValue(); } protected Providers getProviders() { @@ -661,7 +662,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); @@ -735,10 +736,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); } /** @@ -754,7 +755,7 @@ 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(), getLowLevelSuites(), new CompilationResult(), + OptimisticOptimizations.ALL, getProfilingInfo(graphToCompile), getSpeculationLog(), getSuites(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); return GraalCompiler.compile(request); } @@ -815,16 +816,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); } /** @@ -833,31 +834,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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Thu Feb 12 20:47:20 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); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); ParameterNode param = graph.getNodes(ParameterNode.class).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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Thu Feb 12 20:47:20 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(), getLowLevelSuites(), 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(), getLowLevelSuites(), 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java Thu Feb 12 20:47:20 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,8 +113,8 @@ } private StructuredGraph getCanonicalizedGraph(String snippet) { - StructuredGraph graph = parseEager(snippet); - new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders(), null)); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders())); for (FrameState state : graph.getNodes(FrameState.class).snapshot()) { state.replaceAtUsages(null); state.safeDelete(); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Thu Feb 12 20:47:20 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.*; @@ -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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java Thu Feb 12 20:47:20 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,9 +57,9 @@ } 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()); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Thu Feb 12 20:47:20 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.*; @@ -84,7 +84,7 @@ } private StructuredGraph parseAndProcess(String snippet) { - StructuredGraph graph = parseEager(snippet); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); ParameterNode param = graph.getNodes(ParameterNode.class).first(); if (param != null) { ConstantNode constant = ConstantNode.forInt(0, graph); @@ -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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Thu Feb 12 20:47:20 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.*; @@ -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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java Thu Feb 12 20:47:20 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()) { 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); + StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES); for (FrameState fs : referenceGraph.getNodes(FrameState.class).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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Thu Feb 12 20:47:20 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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Thu Feb 12 20:47:20 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,7 +41,7 @@ @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()); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java Thu Feb 12 20:47:20 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, getLowLevelSuites()); + LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), schedule, graph, null, cc, null, getLIRSuites()); return lirGen; } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Thu Feb 12 20:47:20 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,12 +149,11 @@ 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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Thu Feb 12 20:47:20 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.*; @@ -84,8 +84,8 @@ } 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Thu Feb 12 20:47:20 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.*; @@ -244,9 +244,8 @@ } 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java Thu Feb 12 20:47:20 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,11 +59,10 @@ 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. diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java Thu Feb 12 20:47:20 2015 +0100 @@ -37,6 +37,7 @@ 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.*; @@ -78,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 @@ -97,7 +100,7 @@ /* * The low-level phases that are applied to the low-level representation. */ - LowLevelSuites lowLevelSuites = backend.getSuites().createLowLevelSuites(); + LIRSuites lirSuites = backend.getSuites().createLIRSuites(); /* * The calling convention for the machine code. You should have a very good reason @@ -123,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, lowLevelSuites, + GraalCompiler.compileGraph(graph, callingConvention, method, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, lirSuites, compilationResult, factory); /* diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Feb 12 20:47:20 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.*; @@ -45,9 +44,9 @@ import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.phases.*; -import com.oracle.graal.lir.phases.LowLevelHighTierPhase.LowLevelHighTierContext; -import com.oracle.graal.lir.phases.LowLevelLowTierPhase.LowLevelLowTierContext; -import com.oracle.graal.lir.phases.LowLevelMidTierPhase.LowLevelMidTierContext; +import com.oracle.graal.lir.phases.LIRHighTierPhase.LIRHighTierContext; +import com.oracle.graal.lir.phases.LIRLowTierPhase.LIRLowTierContext; +import com.oracle.graal.lir.phases.LIRMidTierPhase.LIRMidTierContext; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; @@ -144,7 +143,7 @@ public final ProfilingInfo profilingInfo; public final SpeculationLog speculationLog; public final Suites suites; - public final LowLevelSuites lowLevelSuites; + public final LIRSuites lirSuites; public final T compilationResult; public final CompilationResultBuilderFactory factory; @@ -162,13 +161,13 @@ * @param profilingInfo * @param speculationLog * @param suites - * @param lowLevelSuites + * @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, LowLevelSuites lowLevelSuites, T compilationResult, CompilationResultBuilderFactory factory) { + SpeculationLog speculationLog, Suites suites, LIRSuites lirSuites, T compilationResult, CompilationResultBuilderFactory factory) { this.graph = graph; this.cc = cc; this.installedCodeOwner = installedCodeOwner; @@ -181,7 +180,7 @@ this.profilingInfo = profilingInfo; this.speculationLog = speculationLog; this.suites = suites; - this.lowLevelSuites = lowLevelSuites; + this.lirSuites = lirSuites; this.compilationResult = compilationResult; this.factory = factory; } @@ -207,8 +206,8 @@ */ 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, LowLevelSuites lowLevelSuites, T compilationResult, CompilationResultBuilderFactory factory) { - return compile(new Request<>(graph, cc, installedCodeOwner, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, lowLevelSuites, + 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)); } @@ -220,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, r.lowLevelSuites); + 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); } @@ -240,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); @@ -258,11 +256,11 @@ 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(); @@ -277,13 +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, - LowLevelSuites lowLevelSuites) { + 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, lowLevelSuites); + lirGen = emitLIR(backend, target, schedule, graph, stub, cc, registerConfig, lirSuites); try (Scope s = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { - emitCode(backend, assumptions, lirGen, compilationResult, installedCodeOwner, factory); + emitCode(backend, graph.getAssumptions(), graph.getMethods(), lirGen, compilationResult, installedCodeOwner, factory); } catch (Throwable e) { throw Debug.handle(e); } @@ -304,7 +301,7 @@ } public static LIRGenerationResult emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc, - RegisterConfig registerConfig, LowLevelSuites lowLevelSuites) { + RegisterConfig registerConfig, LIRSuites lirSuites) { List blocks = schedule.getCFG().getBlocks(); Block startBlock = schedule.getCFG().getStartBlock(); assert startBlock != null; @@ -343,8 +340,8 @@ throw Debug.handle(e); } - try (Scope s = Debug.scope("LowLevelTier", nodeLirGen)) { - return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lowLevelSuites); + try (Scope s = Debug.scope("LIRTier", nodeLirGen)) { + return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lirSuites); } catch (Throwable e) { throw Debug.handle(e); } @@ -354,27 +351,30 @@ } public static > LIRGenerationResult emitLowLevel(TargetDescription target, List codeEmittingOrder, List linearScanOrder, LIRGenerationResult lirGenRes, - LIRGeneratorTool lirGen, LowLevelSuites lowLevelSuites) { - LowLevelHighTierContext highTierContext = new LowLevelHighTierContext(lirGen); - lowLevelSuites.getHighTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, highTierContext); + LIRGeneratorTool lirGen, LIRSuites lirSuites) { + LIRHighTierContext highTierContext = new LIRHighTierContext(lirGen); + lirSuites.getHighTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, highTierContext); - LowLevelMidTierContext midTierContext = new LowLevelMidTierContext(); - lowLevelSuites.getMidTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, midTierContext); + LIRMidTierContext midTierContext = new LIRMidTierContext(); + lirSuites.getMidTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, midTierContext); - LowLevelLowTierContext lowTierContext = new LowLevelLowTierContext(); - lowLevelSuites.getLowTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, lowTierContext); + LIRLowTierContext lowTierContext = new LIRLowTierContext(); + lirSuites.getLowTier().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, lowTierContext); return lirGenRes; } - public static void emitCode(Backend backend, Assumptions assumptions, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, - CompilationResultBuilderFactory factory) { + public static void emitCode(Backend backend, Assumptions assumptions, Set methods, 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 (methods != null) { + compilationResult.setMethods(methods.toArray(new ResolvedJavaMethod[methods.size()])); } if (Debug.isMeterEnabled()) { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java Thu Feb 12 20:47:20 2015 +0100 @@ -24,9 +24,9 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.lir.phases.*; -import com.oracle.graal.lir.phases.LowLevelHighTierPhase.*; -import com.oracle.graal.lir.phases.LowLevelLowTierPhase.*; -import com.oracle.graal.lir.phases.LowLevelMidTierPhase.*; +import com.oracle.graal.lir.phases.LIRHighTierPhase.*; +import com.oracle.graal.lir.phases.LIRLowTierPhase.*; +import com.oracle.graal.lir.phases.LIRMidTierPhase.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -45,16 +45,16 @@ return new LowTier(); } - public LowLevelPhaseSuite createLowLevelHighTier() { - return new LowLevelHighTier(); + public LIRPhaseSuite createLIRHighTier() { + return new LIRHighTier(); } - public LowLevelPhaseSuite createLowLevelMidTier() { - return new LowLevelMidTier(); + public LIRPhaseSuite createLIRMidTier() { + return new LIRMidTier(); } - public LowLevelPhaseSuite createLowLevelLowTier() { - return new LowLevelLowTier(); + public LIRPhaseSuite createLIRLowTier() { + return new LIRLowTier(); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 2015 +0100 @@ -0,0 +1,94 @@ +/* + * 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 (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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/CanonicalizerTool.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Thu Feb 12 20:47:20 2015 +0100 @@ -152,15 +152,12 @@ 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); @@ -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, @@ -251,15 +248,15 @@ } else { /* * System V Application Binary Interface, AMD64 Architecture Processor Supplement - * + * * Draft Version 0.96 - * + * * http://www.uclibc.org/docs/psABI-x86_64.pdf - * + * * 3.2.1 - * + * * ... - * + * * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12 * through %r15 "belong" to the calling function and the called function is required to * preserve their values. In other words, a called function must preserve these diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Thu Feb 12 20:47:20 2015 +0100 @@ -60,12 +60,9 @@ 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); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Thu Feb 12 20:47:20 2015 +0100 @@ -41,6 +41,7 @@ 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; @@ -204,7 +205,7 @@ } 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)) { @@ -212,10 +213,9 @@ // create suites everytime, as we modify options for the compiler SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); final Suites suitesLocal = suitesProvider.createSuites(); - final LowLevelSuites lowLevelSuitesLocal = suitesProvider.createLowLevelSuites(); + final LIRSuites lirSuitesLocal = suitesProvider.createLIRSuites(); final CompilationResult compResult = compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), - OptimisticOptimizations.ALL, getProfilingInfo(graph), getSpeculationLog(), suitesLocal, lowLevelSuitesLocal, new CompilationResult(), - CompilationResultBuilderFactory.Default); + OptimisticOptimizations.ALL, getProfilingInfo(graph), getSpeculationLog(), suitesLocal, lirSuitesLocal, new CompilationResult(), CompilationResultBuilderFactory.Default); addMethod(method, compResult); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java Thu Feb 12 20:47:20 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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java Thu Feb 12 20:47:20 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,7 +36,7 @@ @Test public void test() { - StructuredGraph graph = new StructuredGraph(); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES); test("getNodeClass", ConstantNode.forInt(42, graph)); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu Feb 12 20:47:20 2015 +0100 @@ -97,17 +97,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; } @@ -139,8 +138,8 @@ return providers.getSuites().getDefaultSuites(); } - protected LowLevelSuites getLowLevelSuites(HotSpotProviders providers) { - return providers.getSuites().getDefaultLowLevelSuites(); + protected LIRSuites getLIRSuites(HotSpotProviders providers) { + return providers.getSuites().getDefaultLIRSuites(); } protected PhaseSuite getGraphBuilderSuite(HotSpotProviders providers) { @@ -209,14 +208,19 @@ 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); + graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue())); + if (!recordEvolMethodDeps) { + graph.disableMethodRecording(); + } } else { // Compiling method substitution - must clone the graph - graph = graph.copy(); + 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); @@ -228,7 +232,7 @@ cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0)); } Suites suites = getSuites(providers); - LowLevelSuites lowLevelSuites = getLowLevelSuites(providers); + LIRSuites lirSuites = getLIRSuites(providers); ProfilingInfo profilingInfo = getProfilingInfo(); OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); if (isOSR) { @@ -237,7 +241,7 @@ optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); } result = compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, - method.getSpeculationLog(), suites, lowLevelSuites, new CompilationResult(), CompilationResultBuilderFactory.Default); + method.getSpeculationLog(), suites, lirSuites, new CompilationResult(), CompilationResultBuilderFactory.Default); } result.setId(getId()); result.setEntryBCI(entryBCI); @@ -313,7 +317,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) { @@ -335,7 +341,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); } @@ -354,11 +360,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(); @@ -369,15 +375,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java Thu Feb 12 20:47:20 2015 +0100 @@ -34,17 +34,22 @@ public final HotSpotResolvedJavaMethod method; public final int entryBCI; public final int id; - public final long ctask; + public final long graalEnv; 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 + "]"; } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Thu Feb 12 20:47:20 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().isEmpty() : "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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Thu Feb 12 20:47:20 2015 +0100 @@ -69,10 +69,7 @@ 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); - } + registerGraphBuilderPlugins(providers.getMetaAccess(), plugins); } try (InitTimer st = timer("foreignCalls.initialize")) { @@ -103,4 +100,9 @@ } } } + + protected void registerGraphBuilderPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + StandardGraphBuilderPlugins.registerPlugins(metaAccess, plugins); + HotSpotGraphBuilderPlugins.registerPlugins(metaAccess, plugins); + } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Feb 12 20:47:20 2015 +0100 @@ -1082,6 +1082,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; /** diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Thu Feb 12 20:47:20 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); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 2015 +0100 @@ -0,0 +1,104 @@ +/* + * 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.java.GraphBuilderContext.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.replacements.*; +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.*; +import com.oracle.graal.options.*; + +/** + * Provider of HotSpot specific {@link GraphBuilderPlugin}s. + */ +public class HotSpotGraphBuilderPlugins { + public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + // Object.class + 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; + } + }); + + // Class.class + 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() && object.isConstant()) { + ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); + if (type != null && !type.isPrimitive() && type.isInstance(object.asJavaConstant())) { + builder.push(Kind.Object, object); + 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() && object.isConstant()) { + ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); + if (type != null && !type.isPrimitive()) { + builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(type.isInstance(object.asJavaConstant())))); + return true; + } + } + return false; + } + }); + + // StableOptionValue.class + 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; + } + }); + } +} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPluginsProvider.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +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.meta; - -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.hotspot.replacements.*; -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.*; -import com.oracle.graal.options.*; - -/** - * Provider of HotSpot specific {@link GraphBuilderPlugin}s. - */ -@ServiceProvider(GraphBuilderPluginsProvider.class) -public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { - public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - // Object.class - 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; - } - }); - - // Class.class - 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() && object.isConstant()) { - ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); - if (type != null && !type.isPrimitive() && type.isInstance(object.asJavaConstant())) { - builder.push(Kind.Object, object); - 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() && object.isConstant()) { - ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); - if (type != null && !type.isPrimitive()) { - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(type.isInstance(object.asJavaConstant())))); - return true; - } - } - return false; - } - }); - - // StableOptionValue.class - 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; - } - }); - } -} diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Thu Feb 12 20:47:20 2015 +0100 @@ -183,7 +183,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)); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Thu Feb 12 20:47:20 2015 +0100 @@ -45,7 +45,7 @@ protected final DerivedOptionValue defaultSuites; protected final PhaseSuite defaultGraphBuilderSuite; - private final DerivedOptionValue defaultLowLevelSuites; + private final DerivedOptionValue defaultLIRSuites; protected final HotSpotGraalRuntimeProvider runtime; private class SuitesSupplier implements OptionSupplier { @@ -58,12 +58,12 @@ } - private class LowLevelSuitesSupplier implements OptionSupplier { + private class LIRSuitesSupplier implements OptionSupplier { private static final long serialVersionUID = -1558586374095874299L; - public LowLevelSuites get() { - return createLowLevelSuites(); + public LIRSuites get() { + return createLIRSuites(); } } @@ -72,7 +72,7 @@ this.runtime = runtime; this.defaultGraphBuilderSuite = createGraphBuilderSuite(); this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); - this.defaultLowLevelSuites = new DerivedOptionValue<>(new LowLevelSuitesSupplier()); + this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); } public Suites getDefaultSuites() { @@ -135,12 +135,12 @@ return gbs; } - public LowLevelSuites getDefaultLowLevelSuites() { - return defaultLowLevelSuites.getValue(); + public LIRSuites getDefaultLIRSuites() { + return defaultLIRSuites.getValue(); } - public LowLevelSuites createLowLevelSuites() { - return Suites.createDefaultLowLevelSuites(); + public LIRSuites createLIRSuites() { + return Suites.createDefaultLIRSuites(); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Thu Feb 12 20:47:20 2015 +0100 @@ -161,11 +161,11 @@ private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) { StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes); Suites suites = providers.getSuites().createSuites(); - LowLevelSuites lowLevelSuites = providers.getSuites().createLowLevelSuites(); + 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, lowLevelSuites, 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Thu Feb 12 20:47:20 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.*; @@ -43,10 +42,10 @@ 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 +55,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 +65,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Thu Feb 12 20:47:20 2015 +0100 @@ -226,7 +226,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()); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -26,11 +26,13 @@ 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.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.*; @@ -68,9 +70,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -73,7 +73,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Thu Feb 12 20:47:20 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.disableMethodRecording(); GraphKit kit = new HotSpotGraphKit(graph, providers); ParameterNode[] params = createParameters(kit, args); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Feb 12 20:47:20 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.*; @@ -158,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.isMethodRecordingEnabled() : graph; + if (!(graph.start() instanceof StubStartNode)) { StubStartNode newStart = graph.add(new StubStartNode(Stub.this)); newStart.setStateAfter(graph.start().stateAfter()); @@ -171,14 +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); - LowLevelSuites lowLevelSuites = providers.getSuites().getDefaultLowLevelSuites(); - emitBackEnd(graph, Stub.this, incomingCc, getInstalledCodeOwner(), backend, target, compResult, CompilationResultBuilderFactory.Default, assumptions, schedule, - getRegisterConfig(), lowLevelSuites); + 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java Thu Feb 12 20:47:20 2015 +0100 @@ -55,6 +55,12 @@ return plugins.get(method); } + public DefaultGraphBuilderPlugins copy() { + DefaultGraphBuilderPlugins result = new DefaultGraphBuilderPlugins(); + result.plugins.putAll(plugins); + return result; + } + @Override public String toString() { return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Thu Feb 12 20:47:20 2015 +0100 @@ -32,7 +32,7 @@ private final DerivedOptionValue defaultSuites; private final PhaseSuite defaultGraphBuilderSuite; - private final DerivedOptionValue defaultLowLevelSuites; + private final DerivedOptionValue defaultLIRSuites; private class SuitesSupplier implements OptionSupplier { @@ -44,12 +44,12 @@ } - private class LowLevelSuitesSupplier implements OptionSupplier { + private class LIRSuitesSupplier implements OptionSupplier { private static final long serialVersionUID = 312070237227476252L; - public LowLevelSuites get() { - return createLowLevelSuites(); + public LIRSuites get() { + return createLIRSuites(); } } @@ -57,7 +57,7 @@ public DefaultSuitesProvider() { this.defaultGraphBuilderSuite = createGraphBuilderSuite(); this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); - this.defaultLowLevelSuites = new DerivedOptionValue<>(new LowLevelSuitesSupplier()); + this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); } public Suites getDefaultSuites() { @@ -78,12 +78,12 @@ return suite; } - public LowLevelSuites getDefaultLowLevelSuites() { - return defaultLowLevelSuites.getValue(); + public LIRSuites getDefaultLIRSuites() { + return defaultLIRSuites.getValue(); } - public LowLevelSuites createLowLevelSuites() { - return Suites.createDefaultLowLevelSuites(); + public LIRSuites createLIRSuites() { + return Suites.createDefaultLIRSuites(); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Feb 12 20:47:20 2015 +0100 @@ -78,8 +78,7 @@ @Override protected void run(StructuredGraph graph, HighTierContext context) { - new Instance(context.getMetaAccess(), context.getStampProvider(), context.getAssumptions(), null, context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins, - context.getOptimisticOptimizations()).run(graph); + new Instance(context.getMetaAccess(), context.getStampProvider(), null, context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins, context.getOptimisticOptimizations()).run(graph); } public GraphBuilderConfiguration getGraphBuilderConfig() { @@ -102,7 +101,6 @@ private final GraphBuilderPlugins graphBuilderPlugins; private final OptimisticOptimizations optimisticOpts; private final StampProvider stampProvider; - private final Assumptions assumptions; private final ConstantReflectionProvider constantReflection; private final SnippetReflectionProvider snippetReflectionProvider; @@ -113,22 +111,21 @@ return currentGraph; } - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, SnippetReflectionProvider snippetReflectionProvider, - ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) { + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, ConstantReflectionProvider constantReflection, + GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, 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, null, constantReflection, graphBuilderConfig, null, optimisticOpts); + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, + OptimisticOptimizations optimisticOpts) { + this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, null, optimisticOpts); } @Override @@ -836,7 +833,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; @@ -973,6 +970,11 @@ } calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci())); } + + // Record method dependency in the graph + if (currentGraph.isMethodRecordingEnabled()) { + currentGraph.getMethods().add(targetMethod); + } } protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) { @@ -1691,7 +1693,7 @@ } public Assumptions getAssumptions() { - return assumptions; + return currentGraph.getAssumptions(); } public void push(Kind kind, ValueNode value) { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Thu Feb 12 20:47:20 2015 +0100 @@ -27,7 +27,6 @@ * * Concrete plugins implement one of the sub-interfaces of this interface. * - * @see GraphBuilderPluginsProvider * @see GraphBuilderPlugins * @see GraphBuilderPlugins.Registration */ diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Thu Feb 12 20:47:20 2015 +0100 @@ -296,4 +296,6 @@ * @return the plugin associated with {@code method} or {@code null} if none exists */ InvocationPlugin lookupInvocation(ResolvedJavaMethod method); + + DefaultGraphBuilderPlugins copy(); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java Thu Feb 12 20:47:20 2015 +0100 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java; + +import static com.oracle.graal.java.GraphBuilderContext.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugins.Registration; +import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; + +/** + * Provider of non-runtime specific {@link GraphBuilderPlugin}s. + */ +public class StandardGraphBuilderPlugins { + public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Object.class); + r.register1("", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode object) { + if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { + builder.append(new RegisterFinalizerNode(object)); + } + return true; + } + }); + + for (Kind kind : Kind.values()) { + if (kind.isPrimitive() && kind != Kind.Void) { + new BoxPlugin(kind).register(metaAccess, plugins); + new UnboxPlugin(kind).register(metaAccess, plugins); + } + } + + GraalDirectivePlugins.registerPlugins(metaAccess, plugins); + } + + static class BoxPlugin implements InvocationPlugin { + + private final Kind kind; + + BoxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); + builder.push(Kind.Object, builder.append(new BoxNode(value, resultType, kind))); + return true; + } + + void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass()); + plugins.register(method, this); + } + } + + static class UnboxPlugin implements InvocationPlugin { + + private final Kind kind; + + UnboxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); + builder.push(kind.getStackKind(), builder.append(valueNode)); + return true; + } + + void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + String name = kind.toJavaClass().getSimpleName() + "Value"; + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); + plugins.register(method, this); + } + } +} diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +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) { - ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); - builder.push(kind.getStackKind(), builder.append(valueNode)); - return true; - } - - void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - String name = kind.toJavaClass().getSimpleName() + "Value"; - ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); - plugins.register(method, this); - } - } -} diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java Thu Feb 12 20:47:20 2015 +0100 @@ -35,7 +35,7 @@ /** * This class performs basic optimizations on the control flow graph after LIR generation. */ -public final class ControlFlowOptimizer extends LowLevelLowTierPhase { +public final class ControlFlowOptimizer extends LIRLowTierPhase { /** * Performs control flow optimizations on the given LIR graph. diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java Thu Feb 12 20:47:20 2015 +0100 @@ -48,7 +48,7 @@ * Because this optimization works best when a block contains only a few moves, it has a huge impact * on the number of blocks that are totally empty. */ -public final class EdgeMoveOptimizer extends LowLevelLowTierPhase { +public final class EdgeMoveOptimizer extends LIRLowTierPhase { @Override protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Thu Feb 12 20:47:20 2015 +0100 @@ -31,7 +31,7 @@ import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.phases.*; -public final class NullCheckOptimizer extends LowLevelLowTierPhase { +public final class NullCheckOptimizer extends LIRLowTierPhase { @Override protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Thu Feb 12 20:47:20 2015 +0100 @@ -41,7 +41,7 @@ /** * Removes move instructions, where the destination value is already in place. */ -public final class RedundantMoveElimination extends LowLevelLowTierPhase { +public final class RedundantMoveElimination extends LIRLowTierPhase { @Override protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java Thu Feb 12 20:47:20 2015 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.phases.*; -public final class LinearScanPhase extends LowLevelMidTierPhase { +public final class LinearScanPhase extends LIRMidTierPhase { @Override protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Thu Feb 12 20:47:20 2015 +0100 @@ -42,7 +42,7 @@ * Mark all live references for a frame state. The frame state use this information to build the OOP * maps. */ -public final class LocationMarker extends LowLevelMidTierPhase { +public final class LocationMarker extends LIRMidTierPhase { public static class Options { // @formatter:off diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java Thu Feb 12 20:47:20 2015 +0100 @@ -47,12 +47,12 @@ * a constant, which is potentially scheduled into a block with high probability, with one or more * definitions in blocks with a lower probability. */ -public final class ConstantLoadOptimization extends LowLevelHighTierPhase { +public final class ConstantLoadOptimization extends LIRHighTierPhase { 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 } diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTier.java Thu Feb 12 20:47:20 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.LIRHighTierPhase.*; + +public class LIRHighTier extends LIRPhaseSuite { + public LIRHighTier() { + if (ConstantLoadOptimization.Options.LIROptConstantLoadOptimization.getValue()) { + appendPhase(new ConstantLoadOptimization()); + } + } +} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTierPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRHighTierPhase.java Thu Feb 12 20:47:20 2015 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.phases; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.gen.*; + +public abstract class LIRHighTierPhase extends LIRPhase { + + public static final class LIRHighTierContext { + private final LIRGeneratorTool lirGen; + + public LIRHighTierContext(LIRGeneratorTool lirGen) { + this.lirGen = lirGen; + } + + } + + @Override + protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRHighTierContext context) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.lirGen); + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRGeneratorTool lirGen); + +} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTier.java Thu Feb 12 20:47:20 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.LIRLowTierPhase.*; +import com.oracle.graal.options.*; + +public class LIRLowTier extends LIRPhaseSuite { + public static class Options { + // @formatter:off + @Option(help = "", type = OptionType.Debug) + public static final OptionValue LIROptEdgeMoveOptimizer = new OptionValue<>(true); + @Option(help = "", type = OptionType.Debug) + public static final OptionValue LIROptControlFlowOptmizer = new OptionValue<>(true); + @Option(help = "", type = OptionType.Debug) + public static final OptionValue LIROptRedundantMoveElimination = new OptionValue<>(true); + @Option(help = "", type = OptionType.Debug) + public static final OptionValue LIROptNullCheckOptimizer = new OptionValue<>(true); + // @formatter:on + } + + public LIRLowTier() { + if (Options.LIROptEdgeMoveOptimizer.getValue()) { + appendPhase(new EdgeMoveOptimizer()); + } + if (Options.LIROptControlFlowOptmizer.getValue()) { + appendPhase(new ControlFlowOptimizer()); + } + if (Options.LIROptRedundantMoveElimination.getValue()) { + appendPhase(new RedundantMoveElimination()); + } + if (Options.LIROptNullCheckOptimizer.getValue()) { + appendPhase(new NullCheckOptimizer()); + } + } +} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTierPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRLowTierPhase.java Thu Feb 12 20:47:20 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 LIRLowTierPhase extends LIRPhase { + + public static final class LIRLowTierContext { + } + + @Override + protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRLowTierContext context) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder); + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); + +} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTier.java Thu Feb 12 20:47:20 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.LIRMidTierPhase.*; +import com.oracle.graal.lir.stackslotalloc.*; + +public class LIRMidTier extends LIRPhaseSuite { + public LIRMidTier() { + appendPhase(new LinearScanPhase()); + + // build frame map + if (LSStackSlotAllocator.Options.LIROptLSStackSlotAllocator.getValue()) { + appendPhase(new LSStackSlotAllocator()); + } else { + appendPhase(new SimpleStackSlotAllocator()); + } + // currently we mark locations only if we do register allocation + appendPhase(new LocationMarker()); + } +} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTierPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRMidTierPhase.java Thu Feb 12 20:47:20 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 LIRMidTierPhase extends LIRPhase { + + public static final class LIRMidTierContext { + } + + @Override + protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRMidTierContext context) { + run(target, lirGenRes, codeEmittingOrder, linearScanOrder); + } + + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); + +} diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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.LIRHighTierPhase.LIRHighTierContext; +import com.oracle.graal.lir.phases.LIRLowTierPhase.LIRLowTierContext; +import com.oracle.graal.lir.phases.LIRMidTierPhase.LIRMidTierContext; + +public class LIRSuites { + + private final LIRPhaseSuite highTier; + private final LIRPhaseSuite midTier; + private final LIRPhaseSuite lowTier; + + public LIRSuites(LIRPhaseSuite highTier, LIRPhaseSuite midTier, LIRPhaseSuite lowTier) { + this.highTier = highTier; + this.midTier = midTier; + this.lowTier = lowTier; + } + + /** + * {@link LIRHighTierPhase}s are executed between {@link LIR} generation and register + * allocation. + *

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

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

    + * A {@link LIRLowTierPhase} must not introduce new {@link Variable}s, {@link VirtualStackSlot}s + * or {@link StackSlot}s. + */ + public LIRPhaseSuite getLowTier() { + return lowTier; + } + +} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelHighTier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelHighTier.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import com.oracle.graal.lir.constopt.*; -import com.oracle.graal.lir.phases.LowLevelHighTierPhase.*; - -public class LowLevelHighTier extends LowLevelPhaseSuite { - public LowLevelHighTier() { - if (ConstantLoadOptimization.Options.ConstantLoadOptimization.getValue()) { - appendPhase(new ConstantLoadOptimization()); - } - } -} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelHighTierPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelHighTierPhase.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.gen.*; - -public abstract class LowLevelHighTierPhase extends LowLevelPhase { - - public static final class LowLevelHighTierContext { - private final LIRGeneratorTool lirGen; - - public LowLevelHighTierContext(LIRGeneratorTool lirGen) { - this.lirGen = lirGen; - } - - } - - @Override - protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LowLevelHighTierContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.lirGen); - } - - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LIRGeneratorTool lirGen); - -} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelLowTier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelLowTier.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.phases.LowLevelLowTierPhase.*; - -public class LowLevelLowTier extends LowLevelPhaseSuite { - public LowLevelLowTier() { - appendPhase(new EdgeMoveOptimizer()); - appendPhase(new ControlFlowOptimizer()); - appendPhase(new RedundantMoveElimination()); - appendPhase(new NullCheckOptimizer()); - } -} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelLowTierPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelLowTierPhase.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.gen.*; - -public abstract class LowLevelLowTierPhase extends LowLevelPhase { - - public static final class LowLevelLowTierContext { - } - - @Override - protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LowLevelLowTierContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder); - } - - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); - -} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelMidTier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelMidTier.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import com.oracle.graal.lir.alloc.lsra.*; -import com.oracle.graal.lir.phases.LowLevelMidTierPhase.*; -import com.oracle.graal.lir.stackslotalloc.*; - -public class LowLevelMidTier extends LowLevelPhaseSuite { - public LowLevelMidTier() { - appendPhase(new LinearScanPhase()); - - // build frame map - if (LSStackSlotAllocator.Options.LSStackSlotAllocation.getValue()) { - appendPhase(new LSStackSlotAllocator()); - } else { - appendPhase(new SimpleStackSlotAllocator()); - } - // currently we mark locations only if we do register allocation - appendPhase(new LocationMarker()); - } -} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelMidTierPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelMidTierPhase.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.gen.*; - -public abstract class LowLevelMidTierPhase extends LowLevelPhase { - - public static final class LowLevelMidTierContext { - } - - @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, LowLevelMidTierContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder); - } - - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); - -} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelPhase.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import java.util.*; -import 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 LowLevelPhase { - - 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 LowLevelPhase() { - timer = Debug.timer("LowLevelPhaseTime_%s", getClass()); - memUseTracker = Debug.memUseTracker("LowLevelPhaseMemUse_%s", getClass()); - } - - protected LowLevelPhase(String name) { - assert checkName(name); - this.name = name; - timer = Debug.timer("LowLevelPhaseTime_%s", getClass()); - memUseTracker = Debug.memUseTracker("LowLevelPhaseMemUse_%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 = LowLevelPhase.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 fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelPhaseSuite.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelPhaseSuite.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.lir.gen.*; - -public abstract class LowLevelPhaseSuite extends LowLevelPhase { - private final List> phases; - - public LowLevelPhaseSuite() { - phases = new ArrayList<>(); - } - - /** - * Add a new phase at the beginning of this suite. - */ - public final void prependPhase(LowLevelPhase phase) { - phases.add(0, phase); - } - - /** - * Add a new phase at the end of this suite. - */ - public final void appendPhase(LowLevelPhase 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()) { - LowLevelPhase 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 (LowLevelPhase phase : phases) { - phase.apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context); - } - } - -} diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelSuites.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LowLevelSuites.java Thu Feb 12 20:46:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.phases; - -import com.oracle.graal.lir.phases.LowLevelHighTierPhase.LowLevelHighTierContext; -import com.oracle.graal.lir.phases.LowLevelLowTierPhase.LowLevelLowTierContext; -import com.oracle.graal.lir.phases.LowLevelMidTierPhase.LowLevelMidTierContext; - -public class LowLevelSuites { - - private final LowLevelPhaseSuite highTier; - private final LowLevelPhaseSuite midTier; - private final LowLevelPhaseSuite lowTier; - - public LowLevelSuites(LowLevelPhaseSuite highTier, LowLevelPhaseSuite midTier, LowLevelPhaseSuite lowTier) { - this.highTier = highTier; - this.midTier = midTier; - this.lowTier = lowTier; - } - - public LowLevelPhaseSuite getHighTier() { - return highTier; - } - - public LowLevelPhaseSuite getMidTier() { - return midTier; - } - - public LowLevelPhaseSuite getLowTier() { - return lowTier; - } - -} diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Thu Feb 12 20:47:20 2015 +0100 @@ -51,12 +51,12 @@ * {@link OperandFlag#UNINITIALIZED}. Otherwise the stack slot might be reused and its content * destroyed. */ -public final class LSStackSlotAllocator extends LowLevelMidTierPhase implements StackSlotAllocator { +public final class LSStackSlotAllocator extends LIRMidTierPhase 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 } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java Thu Feb 12 20:47:20 2015 +0100 @@ -36,7 +36,7 @@ import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.phases.*; -public class SimpleStackSlotAllocator extends LowLevelMidTierPhase implements StackSlotAllocator { +public class SimpleStackSlotAllocator extends LIRMidTierPhase implements StackSlotAllocator { @Override protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Thu Feb 12 20:47:20 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"); } } @@ -121,27 +112,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopUnswitchingPhase.java Thu Feb 12 20:47:20 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) { @@ -57,6 +58,8 @@ break; } } + } else { + UNSWITCH_EARLY_REJECTS.increment(); } } } while (unswitched); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeVerifier.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -189,6 +189,10 @@ return; } + if (splitIfAtPhi(tool)) { + return; + } + if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) { AbstractBeginNode intermediateBegin = falseSuccessor(); IfNode nextIf = (IfNode) intermediateBegin.next(); @@ -602,6 +606,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 (AbstractEndNode 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: * diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Thu Feb 12 20:47:20 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,35 +107,46 @@ private boolean hasValueProxies = true; /** + * The assumptions made while constructing and transforming this graph. + */ + private final Assumptions assumptions; + + /** + * The methods whose bytecodes are used while constructing this graph. + */ + private Set methods = 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() { @@ -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), isMethodRecordingEnabled()); + } + + public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod, AllowAssumptions allowAssumptions, boolean enableMethodRecording) { + StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI, allowAssumptions); + if (allowAssumptions == AllowAssumptions.YES && assumptions != null) { + copy.assumptions.record(assumptions); + } + if (!enableMethodRecording) { + copy.disableMethodRecording(); + } copy.setGuardsStage(getGuardsStage()); copy.isAfterFloatingReadPhase = isAfterFloatingReadPhase; copy.hasValueProxies = hasValueProxies; @@ -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 method used while constructing this graph. This can be done at most + * once and must be done before any methods are recorded. + */ + public void disableMethodRecording() { + assert methods != null : "cannot disable method recording more than once"; + assert methods.isEmpty() : "cannot disable method recording once methods have been recorded"; + methods = null; + } + + public boolean isMethodRecordingEnabled() { + return methods != null; + } + + /** + * Gets the methods whose bytecodes are used while constructing this graph. + * + * @return {@code null} if method recording has been {@linkplain #disableMethodRecording() + * disabled} + */ + public Set getMethods() { + return methods; + } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Thu Feb 12 20:47:20 2015 +0100 @@ -275,7 +275,7 @@ 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); + Debug.log(3, "Unexpected loop exit with %s, including whole branch in the loop", sux); unexpected.add(sux); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -73,10 +73,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -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.*; @@ -68,10 +69,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Thu Feb 12 20:47:20 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.*; @@ -157,11 +158,12 @@ return synonym; } - 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); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -22,6 +22,7 @@ */ 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.spi.*; @@ -77,12 +78,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; } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -94,7 +94,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 +119,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 +145,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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -67,7 +67,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 +80,7 @@ if (!(forValue.stamp() instanceof ObjectStamp)) { return this; } - if (!mayHaveFinalizer(forValue, tool.assumptions())) { + if (!mayHaveFinalizer(forValue, graph().getAssumptions())) { return null; } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Thu Feb 12 20:47:20 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.*; @@ -83,11 +82,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Thu Feb 12 20:47:20 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.graph.iterators.*; @@ -473,22 +472,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 +510,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Thu Feb 12 20:47:20 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.*; @@ -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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Thu Feb 12 20:47:20 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(); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Thu Feb 12 20:47:20 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.compiler.common.type.*; import com.oracle.graal.graph.Graph.Mark; @@ -120,11 +119,6 @@ return createGuard(before, condition, deoptReason, action, false); } - @Override - public Assumptions assumptions() { - return context.getAssumptions(); - } - public StampProvider getStampProvider() { return context.getStampProvider(); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Thu Feb 12 20:47:20 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]); } } @@ -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 method dependencies from inlinee to caller + if (inlineGraph.isMethodRecordingEnabled() && graph.isMethodRecordingEnabled()) { + graph.getMethods().addAll(inlineGraph.getMethods()); + } + return duplicates; } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Thu Feb 12 20:47:20 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,7 +65,10 @@ } InliningUtil.InlinedBytecodes.add(concrete.getCodeSize()); - assumptions.recordMethodContents(concrete); + StructuredGraph graph = invoke.asNode().graph(); + if (graph.isMethodRecordingEnabled()) { + graph.getMethods().add(concrete); + } return canonicalizeNodes; } @@ -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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/ExactInlineInfo.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/InlineInfo.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Thu Feb 12 20:47:20 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) { @@ -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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Thu Feb 12 20:47:20 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); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Thu Feb 12 20:47:20 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); } /** @@ -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.isMethodRecordingEnabled()) { + // Don't record method dependencies in the inlinee 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.disableMethodRecording(); + } if (context.getGraphBuilderSuite() != null) { context.getGraphBuilderSuite().apply(newGraph, context); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Thu Feb 12 20:47:20 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()} *
  11. - * {@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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java Thu Feb 12 20:47:20 2015 +0100 @@ -24,9 +24,9 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.lir.phases.*; -import com.oracle.graal.lir.phases.LowLevelHighTierPhase.*; -import com.oracle.graal.lir.phases.LowLevelLowTierPhase.*; -import com.oracle.graal.lir.phases.LowLevelMidTierPhase.*; +import com.oracle.graal.lir.phases.LIRHighTierPhase.*; +import com.oracle.graal.lir.phases.LIRLowTierPhase.*; +import com.oracle.graal.lir.phases.LIRMidTierPhase.*; import com.oracle.graal.phases.*; public interface CompilerConfiguration extends Service { @@ -37,9 +37,9 @@ PhaseSuite createLowTier(); - LowLevelPhaseSuite createLowLevelHighTier(); + LIRPhaseSuite createLIRHighTier(); - LowLevelPhaseSuite createLowLevelMidTier(); + LIRPhaseSuite createLIRMidTier(); - LowLevelPhaseSuite createLowLevelLowTier(); + LIRPhaseSuite createLIRLowTier(); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Thu Feb 12 20:47:20 2015 +0100 @@ -130,21 +130,21 @@ return new Suites(config); } - public static LowLevelSuites createDefaultLowLevelSuites() { + public static LIRSuites createDefaultLIRSuites() { String selected = CompilerConfiguration.getValue(); if (selected.equals("")) { - return new LowLevelSuites(defaultConfiguration.createLowLevelHighTier(), defaultConfiguration.createLowLevelMidTier(), defaultConfiguration.createLowLevelLowTier()); + return new LIRSuites(defaultConfiguration.createLIRHighTier(), defaultConfiguration.createLIRMidTier(), defaultConfiguration.createLIRLowTier()); } else { - return createLowLevelSuites(selected); + return createLIRSuites(selected); } } - public static LowLevelSuites createLowLevelSuites(String name) { + public static LIRSuites createLIRSuites(String name) { CompilerConfiguration config = configurations.get(name); if (config == null) { throw new GraalInternalError("unknown compiler configuration: " + name); } - return new LowLevelSuites(config.createLowLevelHighTier(), config.createLowLevelMidTier(), config.createLowLevelLowTier()); + return new LIRSuites(config.createLIRHighTier(), config.createLIRMidTier(), config.createLIRLowTier()); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java Thu Feb 12 20:47:20 2015 +0100 @@ -46,12 +46,12 @@ /** * Get the default phase suites of this compiler. */ - LowLevelSuites getDefaultLowLevelSuites(); + LIRSuites getDefaultLIRSuites(); /** * Create a new set of low-level phase suites. Initially, the suites are the same as the - * {@link #getDefaultLowLevelSuites default} suites. + * {@link #getDefaultLIRSuites default} suites. */ - LowLevelSuites createLowLevelSuites(); + LIRSuites createLIRSuites(); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Thu Feb 12 20:47:20 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,11 +330,10 @@ @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); } @@ -347,11 +346,10 @@ @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); } @@ -362,13 +360,12 @@ @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); } @@ -381,13 +378,12 @@ @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); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Thu Feb 12 20:47:20 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,8 +247,8 @@ * @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); diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Thu Feb 12 20:47:20 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.*; @@ -54,7 +54,7 @@ } - StructuredGraph graph = new StructuredGraph(); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO); TestNode node; ConstantNode i1; ConstantNode i2; @@ -113,9 +113,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Feb 12 20:47:20 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,6 @@ public final Providers providers; public final SnippetReflectionProvider snippetReflection; public final TargetDescription target; - public final Assumptions assumptions; /** * The preprocessed replacement graphs. @@ -219,13 +219,12 @@ // 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(); } @@ -287,7 +286,7 @@ // Do deferred intrinsification of node intrinsics createNodeIntrinsificationPhase().apply(specializedSnippet); - new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers, assumptions)); + new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers)); NodeIntrinsificationVerificationPhase.verify(specializedSnippet); } @@ -319,10 +318,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(); @@ -612,20 +607,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.disableMethodRecording(); + 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 +634,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 +658,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)); } } @@ -668,7 +669,7 @@ replacements.createNodeIntrinsificationPhase().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)); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Feb 12 20:47:20 2015 +0100 @@ -49,6 +49,7 @@ 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.*; @@ -561,10 +562,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.isMethodRecordingEnabled()) { + snippetCopy.disableMethodRecording(); + } + Map nodeReplacements = Node.newIdentityMap(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); @@ -1245,7 +1250,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -61,7 +61,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 +105,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -129,7 +129,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Feb 12 20:47:20 2015 +0100 @@ -47,6 +47,7 @@ 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.*; @@ -176,17 +177,16 @@ MetaAccessProvider metaAccess = providers.getMetaAccess(); SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); Suites suites = suitesProvider.createSuites(); - LowLevelSuites lowLevelSuites = suitesProvider.createLowLevelSuites(); + 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, lowLevelSuites, new CompilationResult(), factory); + suites, lirSuites, new CompilationResult(), factory); } private static Providers getGraalProviders() { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Thu Feb 12 20:47:20 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,23 +74,22 @@ } 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)) { 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, null); } catch (Throwable e) { throw Debug.handle(e); } @@ -103,13 +100,13 @@ 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Thu Feb 12 20:47:20 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.*; @@ -107,9 +105,9 @@ } private byte getByteUnsafe(FrameSlot slot) { - long offset = alignPrimitive(slot, Kind.Byte); + long offset = getPrimitiveOffset(slot); boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Byte.ordinal(); - return unsafeGetByte(getPrimitiveLocals(), offset, condition, slot); + return (byte) unsafeGetInt(getPrimitiveLocals(), offset, condition, slot); } @Override @@ -119,8 +117,8 @@ } private void setByteUnsafe(FrameSlot slot, byte value) { - long offset = alignPrimitive(slot, Kind.Boolean); - unsafePutByte(getPrimitiveLocals(), offset, value, slot); + long offset = getPrimitiveOffset(slot); + unsafePutInt(getPrimitiveLocals(), offset, value, slot); } @Override @@ -130,9 +128,9 @@ } private boolean getBooleanUnsafe(FrameSlot slot) { - long offset = alignPrimitive(slot, Kind.Boolean); + long offset = getPrimitiveOffset(slot); boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Boolean.ordinal(); - return unsafeGetBoolean(getPrimitiveLocals(), offset, condition, slot); + return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot) != 0; } @Override @@ -142,8 +140,8 @@ } private void setBooleanUnsafe(FrameSlot slot, boolean value) { - long offset = alignPrimitive(slot, Kind.Boolean); - unsafePutBoolean(getPrimitiveLocals(), offset, value, slot); + long offset = getPrimitiveOffset(slot); + unsafePutInt(getPrimitiveLocals(), offset, value ? 1 : 0, slot); } @Override @@ -153,7 +151,7 @@ } private float getFloatUnsafe(FrameSlot slot) { - long offset = alignPrimitive(slot, Kind.Float); + long offset = getPrimitiveOffset(slot); boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Float.ordinal(); return unsafeGetFloat(getPrimitiveLocals(), offset, condition, slot); } @@ -165,7 +163,7 @@ } private void setFloatUnsafe(FrameSlot slot, float value) { - long offset = alignPrimitive(slot, Kind.Float); + long offset = getPrimitiveOffset(slot); unsafePutFloat(getPrimitiveLocals(), offset, value, slot); } @@ -176,7 +174,7 @@ } private long getLongUnsafe(FrameSlot slot) { - long offset = alignPrimitive(slot, Kind.Long); + long offset = getPrimitiveOffset(slot); boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Long.ordinal(); return unsafeGetLong(getPrimitiveLocals(), offset, condition, slot); } @@ -188,7 +186,7 @@ } private void setLongUnsafe(FrameSlot slot, long value) { - long offset = alignPrimitive(slot, Kind.Long); + long offset = getPrimitiveOffset(slot); unsafePutLong(getPrimitiveLocals(), offset, value, slot); } @@ -199,7 +197,7 @@ } private int getIntUnsafe(FrameSlot slot) { - long offset = alignPrimitive(slot, Kind.Int); + long offset = getPrimitiveOffset(slot); boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Int.ordinal(); return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot); } @@ -211,7 +209,7 @@ } private void setIntUnsafe(FrameSlot slot, int value) { - long offset = alignPrimitive(slot, Kind.Int); + long offset = getPrimitiveOffset(slot); unsafePutInt(getPrimitiveLocals(), offset, value, slot); } @@ -222,7 +220,7 @@ } private double getDoubleUnsafe(FrameSlot slot) { - long offset = alignPrimitive(slot, Kind.Double); + long offset = getPrimitiveOffset(slot); boolean condition = this.getTags()[slot.getIndex()] == FrameSlotKind.Double.ordinal(); return unsafeGetDouble(getPrimitiveLocals(), offset, condition, slot); } @@ -234,7 +232,7 @@ } private void setDoubleUnsafe(FrameSlot slot, double value) { - long offset = alignPrimitive(slot, Kind.Double); + long offset = getPrimitiveOffset(slot); unsafePutDouble(getPrimitiveLocals(), offset, value, slot); } @@ -269,14 +267,8 @@ } } - 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(FrameSlot slot) { + return Unsafe.ARRAY_LONG_BASE_OFFSET + slot.getIndex() * (long) Unsafe.ARRAY_LONG_INDEX_SCALE; } @Override @@ -368,16 +360,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 +385,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Thu Feb 12 20:47:20 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 { @@ -181,6 +183,9 @@ } public T getCapability(Class capability) { + if (capability == UnsafeAccessFactory.class) { + return capability.cast(new UnsafeAccessFactoryImpl()); + } return null; } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Feb 12 20:47:20 2015 +0100 @@ -30,7 +30,6 @@ 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.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; @@ -41,6 +40,7 @@ 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 +97,7 @@ } } - public StructuredGraph createGraph(final OptimizedCallTarget callTarget, final Assumptions assumptions) { + public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions, GraphBuilderPlugins graalPlugins) { if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) { constantReceivers = new HashSet<>(); } @@ -108,7 +108,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 +117,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, graalPlugins); } else { createRootGraph(graph); - partialEvaluation(callTarget, assumptions, graph, baseContext, tierContext); + partialEvaluation(callTarget, graph, baseContext, tierContext); } if (Thread.currentThread().isInterrupted()) { @@ -207,20 +207,16 @@ } @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, GraphBuilderPlugins graalPlugins) { GraphBuilderConfiguration newConfig = configForRoot.copy(); newConfig.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); newConfig.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); newConfig.setInlineInvokePlugin(new InlineInvokePlugin()); newConfig.setLoopExplosionPlugin(new LoopExplosionPlugin()); - DefaultGraphBuilderPlugins plugins = new DefaultGraphBuilderPlugins(); - Iterable sl = Services.load(GraphBuilderPluginsProvider.class); - for (GraphBuilderPluginsProvider p : sl) { - p.registerPlugins(providers.getMetaAccess(), plugins); - } + DefaultGraphBuilderPlugins plugins = graalPlugins == null ? new DefaultGraphBuilderPlugins() : graalPlugins.copy(); TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins); long ms = System.currentTimeMillis(); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(true), this.snippetReflection, providers.getConstantReflection(), newConfig, plugins, + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig, plugins, TruffleCompilerImpl.Optimizations).apply(graph); System.out.println("# ms: " + (System.currentTimeMillis() - ms)); Debug.dump(graph, "After FastPE"); @@ -234,7 +230,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"); @@ -244,7 +240,7 @@ expansionLogger = new TruffleExpansionLogger(providers, graph); } - expandTree(graph, assumptions, expansionLogger); + expandTree(graph, expansionLogger); TruffleInliningCache inliningCache = null; if (TruffleFunctionInlining.getValue()) { @@ -254,7 +250,7 @@ } } - expandDirectCalls(graph, assumptions, expansionLogger, callTarget.getInlining(), inliningCache); + expandDirectCalls(graph, expansionLogger, callTarget.getInlining(), inliningCache); if (Thread.currentThread().isInterrupted()) { return; @@ -269,7 +265,7 @@ } catch (Throwable t) { Debug.handle(t); } - } while (expandTree(graph, assumptions, expansionLogger)); + } while (expandTree(graph, expansionLogger)); if (expansionLogger != null) { expansionLogger.print(callTarget); @@ -277,15 +273,13 @@ } 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; } @@ -341,8 +335,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<>(); @@ -483,18 +477,18 @@ } } - 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); + 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); } @@ -507,7 +501,7 @@ 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) { @@ -536,13 +530,13 @@ StructuredGraph graph; if (decision != null && decision.isInline()) { if (inliningCache == null) { - graph = createInlineGraph(phaseContext, assumptions, null, decision); + graph = createInlineGraph(phaseContext, caller, null, decision); } else { - graph = inliningCache.getCachedGraph(phaseContext, assumptions, decision); + graph = inliningCache.getCachedGraph(phaseContext, caller, decision); } decision.getProfile().setGraalDeepNodeCount(graph.getNodeCount()); - assumptions.record(new AssumptionValidAssumption((OptimizedAssumption) decision.getTarget().getNodeRewritingAssumption())); + 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); @@ -591,17 +585,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); @@ -632,11 +626,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Thu Feb 12 20:47:20 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; } @@ -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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Feb 12 20:47:20 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.*; @@ -42,6 +42,7 @@ 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.*; @@ -60,7 +61,7 @@ private final Providers providers; private final Suites suites; - private final LowLevelSuites lowLevelSuites; + private final LIRSuites lirSuites; private final PartialEvaluator partialEvaluator; private final Backend backend; private final GraphBuilderConfiguration config; @@ -83,7 +84,7 @@ ConstantReflectionProvider constantReflection = new TruffleConstantReflectionProvider(backend.getProviders().getConstantReflection(), backend.getProviders().getMetaAccess()); this.providers = backend.getProviders().copyWith(truffleReplacements).copyWith(constantReflection); this.suites = backend.getSuites().getDefaultSuites(); - this.lowLevelSuites = backend.getSuites().getDefaultLowLevelSuites(); + this.lirSuites = backend.getSuites().getDefaultLIRSuites(); ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault().withSkippedExceptionTypes(skippedExceptionTypes); @@ -119,10 +120,10 @@ compilationNotify.notifyCompilationStarted(compilable); try { - Assumptions assumptions = new Assumptions(true); + GraphBuilderSuiteInfo info = createGraphBuilderSuite(); try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) { - graph = partialEvaluator.createGraph(compilable, assumptions); + graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES, info.plugins); } if (Thread.currentThread().isInterrupted()) { @@ -137,7 +138,7 @@ } compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph); - CompilationResult compilationResult = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog(), compilable); + CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), info.suite, compilable.getSpeculationLog(), compilable); compilationNotify.notifyCompilationSuccess(compilable, graph, compilationResult); } catch (Throwable t) { compilationNotify.notifyCompilationFailed(compilable, graph, t); @@ -145,7 +146,7 @@ } } - 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) { @@ -157,29 +158,34 @@ 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, lowLevelSuites, compilationResult, CompilationResultBuilderFactory.Default); + result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, graphBuilderSuite == null ? createGraphBuilderSuite().suite : graphBuilderSuite, + Optimizations, getProfilingInfo(graph), speculationLog, suites, lirSuites, compilationResult, CompilationResultBuilderFactory.Default); } catch (Throwable e) { throw Debug.handle(e); } compilationNotify.notifyCompilationGraalTierFinished((OptimizedCallTarget) predefinedInstalledCode, graph); + if (graph.isMethodRecordingEnabled()) { + Set methods = graph.getMethods(); + result.setMethods(methods.toArray(new ResolvedJavaMethod[methods.size()])); + } 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()) { @@ -198,22 +204,33 @@ return result; } - private PhaseSuite createGraphBuilderSuite() { + static class GraphBuilderSuiteInfo { + final PhaseSuite suite; + final GraphBuilderPlugins plugins; + + public GraphBuilderSuiteInfo(PhaseSuite suite, GraphBuilderPlugins plugins) { + this.suite = suite; + this.plugins = plugins; + } + } + + private GraphBuilderSuiteInfo 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())); - return suite; + GraphBuilderPlugins plugins = graphBuilderPhase.getGraphBuilderPlugins(); + iterator.add(new GraphBuilderPhase(config, plugins)); + return new GraphBuilderSuiteInfo(suite, plugins); } - 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Thu Feb 12 20:47:20 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,7 +43,7 @@ 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(); @@ -55,6 +56,7 @@ registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class); registerSubstitutions(FrameWithoutBoxing.class, FrameWithoutBoxingSubstitutions.class); + registerSubstitutions(UnsafeAccessImpl.class, UnsafeAccessSubstitutions.class); } @Override diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -22,6 +22,7 @@ */ 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.*; @@ -62,14 +63,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 fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -172,7 +172,7 @@ for (int i = 0; i < frameSize; i++) { primitiveArrayEntryState[i] = initialPrimitiveValue(frameDescriptor.getSlots().get(i).getKind()); } - tool.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); + graph().getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); } tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, Collections. emptyList()); @@ -195,11 +195,7 @@ Kind graalKind = null; switch (kind) { case Boolean: - graalKind = Kind.Boolean; - break; case Byte: - graalKind = Kind.Byte; - break; case Int: graalKind = Kind.Int; break; diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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) { - LogicNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection()); - 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Thu Feb 12 20:47:20 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) @@ -77,100 +76,8 @@ @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); - } - @MethodSubstitution public static void materialize(Object obj) { ForceMaterializeNode.force(obj); } - } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Thu Feb 12 20:47:20 2015 +0100 @@ -42,6 +42,7 @@ 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.*; @@ -189,7 +190,16 @@ 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}) { + + registerUnsafeLoadStorePlugins(r, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object); + + // CompilerDirectives.class + r = new Registration(plugins, metaAccess, UnsafeAccessImpl.class); + registerUnsafeLoadStorePlugins(r, Kind.Boolean, Kind.Byte, Kind.Int, Kind.Short, Kind.Long, Kind.Float, Kind.Double, Kind.Object); + } + + protected static void registerUnsafeLoadStorePlugins(Registration r, Kind... kinds) { + for (Kind kind : kinds) { String kindName = kind.getJavaName(); kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); String getName = "unsafeGet" + kindName; diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu Feb 12 20:47:20 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.*; @@ -94,8 +93,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 +108,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); } /** diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Thu Feb 12 20:47:20 2015 +0100 @@ -104,7 +104,7 @@ return "(int)"; } - @Specialization(guards = "notInt") + @Specialization(guards = "notInt(a)") String f2(Object a) { return "(object)"; } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Thu Feb 12 20:47:20 2015 +0100 @@ -45,7 +45,7 @@ return true; } - @Specialization(guards = "!guard") + @Specialization(guards = "!guard()") int do1() { throw new AssertionError(); } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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. + * + *
      9. + * 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();
        + *     }
        + * }
        + *
        + * 
        + * + *
      10. + *
      11. + * 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) {
        + * }
        + * 
        + * + *
      12. + *
      + * + * @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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java Thu Feb 12 20:47:20 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(); @@ -588,7 +588,7 @@ public final Instrument instrument; public TestCounter() { - instrument = Instrument.create(new SimpleEventReceiver() { + instrument = Instrument.create(new SimpleEventListener() { @Override public void enter(Node node, VirtualFrame frame) { @@ -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,7 +692,7 @@ // 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) { diff -r fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.truffle.api/.checkstyle_checks.xml --- a/graal/com.oracle.truffle.api/.checkstyle_checks.xml Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/.checkstyle_checks.xml Thu Feb 12 20:47:20 2015 +0100 @@ -198,6 +198,11 @@ + + + + + diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Thu Feb 12 20:47:20 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. @@ -203,464 +184,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 fcefaa7f103d -r 57c53b1044a7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Thu Feb 12 20:47:20 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; @@ -287,28 +287,28 @@ } public void enter(Node node, VirtualFrame frame) { - Instrument.this.toolEventreceiver.enter(node, frame); + Instrument.this.toolEventListener.enter(node, frame); if (nextInstrument != null) { nextInstrument.enter(node, frame); } } public void returnVoid(Node node, VirtualFrame frame) { - Instrument.this.toolEventreceiver.returnVoid(node, frame); + Instrument.this.toolEventListener.returnVoid(node, frame); if (nextInstrument != null) { nextInstrument.returnVoid(node, frame); } } public void returnValue(Node node, VirtualFrame frame, Object result) { - Instrument.this.toolEventreceiver.returnValue(node, frame, result); + Instrument.this.toolEventListener.returnValue(node, frame, result); if (nextInstrument != null) { nextInstrument.returnValue(node, frame, result); } } public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { - Instrument.this.toolEventreceiver.returnExceptional(node, frame, exception); + Instrument.this.toolEventListener.returnExceptional(node, frame, exception); if (nextInstrument != null) { nextInstrument.returnExceptional(node, frame, exception); } @@ -318,7 +318,7 @@ if (Instrument.this.instrumentInfo != null) { return Instrument.this.instrumentInfo; } - return toolEventreceiver.getClass().getSimpleName(); + return toolEventListener.getClass().getSimpleName(); } } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Thu Feb 12 20:47:20 2015 +0100 @@ -40,7 +40,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. *

    diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java Thu Feb 12 20:47:20 2015 +0100 @@ -35,7 +35,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 +85,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 +120,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); } @@ -277,15 +277,15 @@ /** * 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 @@ -306,19 +306,19 @@ } public void enter(Node node, VirtualFrame frame) { - eventReceiver.enter(node, frame); + eventListener.enter(node, frame); } public void returnVoid(Node node, VirtualFrame frame) { - eventReceiver.returnVoid(node, frame); + eventListener.returnVoid(node, frame); } public void returnValue(Node node, VirtualFrame frame, Object result) { - eventReceiver.returnValue(node, frame, result); + eventListener.returnValue(node, frame, result); } public void returnExceptional(Node node, VirtualFrame frame, Exception exception) { - eventReceiver.returnExceptional(node, frame, exception); + eventListener.returnExceptional(node, frame, exception); } public String instrumentationInfo() { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Thu Feb 12 20:47:20 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,12 +244,11 @@ */ private final AtomicLong count; - CoverageEventReceiver(AtomicLong count) { + CoverageEventListener(AtomicLong count) { this.count = count; } @Override - @TruffleBoundary public void enter(Node node, VirtualFrame frame) { if (isEnabled()) { count.getAndIncrement(); @@ -259,9 +256,9 @@ } } - 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java Thu Feb 12 20:47:20 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); + 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 2015 +0100 @@ -0,0 +1,413 @@ +/* + * 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.*; + +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 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; + } + + @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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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("||"); + private static final List COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">="); + private 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Thu Feb 12 20:47:20 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)); } @@ -240,7 +238,7 @@ 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 +330,7 @@ List generateSpecializations = new ArrayList<>(); generateSpecializations.add(node.getUninitializedSpecialization()); - if (needsPolymorphic(reachableSpecializations)) { + if (needsPolymorphic()) { generateSpecializations.add(node.getPolymorphicSpecialization()); } generateSpecializations.addAll(reachableSpecializations); @@ -348,6 +346,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 +508,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 +530,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 +576,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 +620,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 +630,7 @@ builder.tree(execution); - if (hasFallthrough(group, genericType, locals, false)) { + if (hasFallthrough(group, genericType, locals, false, null)) { builder.returnNull(); } return method; @@ -711,8 +719,6 @@ return evaluatedCount; } - // create specialization - private Element createUnsupported() { SpecializationData fallback = node.getGenericSpecialization(); if (fallback == null || optimizeFallback(fallback) || fallback.getMethod() == null) { @@ -736,12 +742,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 +829,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 +987,8 @@ continue; } } - builder.string(parameter.getLocalName()); + + builder.defaultValue(parameter.getType()); } builder.end(); return builder.build(); @@ -1012,9 +1032,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 +1084,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 +1118,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 +1130,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 +1218,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 +1314,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 +1398,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 +1443,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 +1455,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 +1481,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 +1499,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 +1550,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 +1594,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 +1633,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 +1651,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 +1664,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 +1672,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 +1698,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 +2100,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 +2234,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 +2270,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 +2482,11 @@ return values.get(shortCircuitName(execution)); } + @Override + public String toString() { + return "LocalContext [values=" + values + "]"; + } + } public static final class LocalVariable { @@ -2329,6 +2578,11 @@ return newType(type.getTypeSystem().getGenericTypeData()); } + @Override + public String toString() { + return "Local[type = " + getTypeMirror() + ", name = " + name + ", accessWith = " + accessorTree + "]"; + } + } private interface SpecializationExecution { diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Thu Feb 12 20:47:20 2015 +0100 @@ -85,12 +85,4 @@ return super.equals(obj); } - public boolean hasFrame() { - return getFrame() != null; - } - - public Parameter getFrame() { - return findParameter("frameValue"); - } - } diff -r fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Thu Feb 12 20:47:20 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,74 +936,193 @@ 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) { @@ -1068,10 +1159,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 +1287,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 +1343,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 +1483,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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 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 Thu Feb 12 20:46:56 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java Thu Feb 12 20:47:20 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 fcefaa7f103d -r 57c53b1044a7 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Feb 12 20:47:20 2015 +0100 @@ -204,11 +204,9 @@ GRAAL_ONLY(do_klass(HotSpotMetaspaceConstantImpl_klass, com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstantImpl, Graal)) \ GRAAL_ONLY(do_klass(HotSpotStackFrameReference_klass, com_oracle_graal_hotspot_HotSpotStackFrameReference, Graal)) \ GRAAL_ONLY(do_klass(CompilationTask_klass, com_oracle_graal_hotspot_CompilationTask, Graal)) \ - GRAAL_ONLY(do_klass(Assumptions_klass, com_oracle_graal_api_code_Assumptions, Graal)) \ GRAAL_ONLY(do_klass(Assumptions_ConcreteMethod_klass, com_oracle_graal_api_code_Assumptions_ConcreteMethod, Graal)) \ GRAAL_ONLY(do_klass(Assumptions_NoFinalizableSubclass_klass, com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, Graal))\ GRAAL_ONLY(do_klass(Assumptions_ConcreteSubtype_klass, com_oracle_graal_api_code_Assumptions_ConcreteSubtype, Graal)) \ - GRAAL_ONLY(do_klass(Assumptions_MethodContents_klass, com_oracle_graal_api_code_Assumptions_MethodContents, Graal)) \ GRAAL_ONLY(do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue, Graal)) \ GRAAL_ONLY(do_klass(BytecodePosition_klass, com_oracle_graal_api_code_BytecodePosition, Graal)) \ GRAAL_ONLY(do_klass(DebugInfo_klass, com_oracle_graal_api_code_DebugInfo, Graal)) \ diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Feb 12 20:47:20 2015 +0100 @@ -321,8 +321,6 @@ GRAAL_ONLY(template(com_oracle_graal_api_meta_Kind, "com/oracle/graal/api/meta/Kind")) \ GRAAL_ONLY(template(com_oracle_graal_api_meta_LIRKind, "com/oracle/graal/api/meta/LIRKind")) \ GRAAL_ONLY(template(com_oracle_graal_api_meta_AbstractValue, "com/oracle/graal/api/meta/AbstractValue")) \ - GRAAL_ONLY(template(com_oracle_graal_api_code_Assumptions, "com/oracle/graal/api/code/Assumptions")) \ - GRAAL_ONLY(template(com_oracle_graal_api_code_Assumptions_MethodContents, "com/oracle/graal/api/code/Assumptions$MethodContents")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype, "com/oracle/graal/api/code/Assumptions$ConcreteSubtype")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/code/Assumptions$NoFinalizableSubclass")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_Assumptions_ConcreteMethod, "com/oracle/graal/api/code/Assumptions$ConcreteMethod")) \ diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Feb 12 20:47:20 2015 +0100 @@ -1987,6 +1987,11 @@ int compilable = ciEnv::MethodCompilable; AbstractCompiler *comp = compiler(task_level); + int system_dictionary_modification_counter; + { + MutexLocker locker(Compile_lock, thread); + system_dictionary_modification_counter = SystemDictionary::number_of_modifications(); + } #ifdef COMPILERGRAAL if (comp != NULL && comp->is_graal()) { GraalCompiler* graal = (GraalCompiler*) comp; @@ -1994,17 +1999,13 @@ TraceTime t1("compilation", &time); EventCompilation event; - graal->compile_method(target_handle, osr_bci, task); + GraalEnv env(task, system_dictionary_modification_counter); + graal->compile_method(target_handle, osr_bci, &env); post_compile(thread, task, event, task->code() != NULL, NULL); } else #endif // COMPILERGRAAL { - int system_dictionary_modification_counter; - { - MutexLocker locker(Compile_lock, thread); - system_dictionary_modification_counter = SystemDictionary::number_of_modifications(); - } NoHandleMark nhm; ThreadToNativeFromVM ttn(thread); diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu Feb 12 20:47:20 2015 +0100 @@ -384,21 +384,18 @@ return new MonitorValue(owner_value, lock_data_loc, eliminated); } -void CodeInstaller::initialize_assumptions(oop compiled_code) { +void CodeInstaller::initialize_dependencies(oop compiled_code) { JavaThread* thread = JavaThread::current(); CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL; _oop_recorder = new OopRecorder(&_arena, true); _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL); - Handle assumptions_handle = CompilationResult::assumptions(HotSpotCompiledCode::comp(compiled_code)); - if (!assumptions_handle.is_null()) { - objArrayHandle assumptions(Thread::current(), Assumptions::list(assumptions_handle())); + objArrayHandle assumptions = CompilationResult::assumptions(HotSpotCompiledCode::comp(compiled_code)); + if (!assumptions.is_null()) { int length = assumptions->length(); for (int i = 0; i < length; ++i) { Handle assumption = assumptions->obj_at(i); if (!assumption.is_null()) { - if (assumption->klass() == Assumptions_MethodContents::klass()) { - assumption_MethodContents(assumption); - } else if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) { + if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) { assumption_NoFinalizableSubclass(assumption); } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) { assumption_ConcreteSubtype(assumption); @@ -413,6 +410,15 @@ } } } + objArrayHandle methods = CompilationResult::methods(HotSpotCompiledCode::comp(compiled_code)); + if (!methods.is_null()) { + int length = methods->length(); + for (int i = 0; i < length; ++i) { + Handle method_handle = methods->obj_at(i); + methodHandle method = getMethodFromHotSpotMethod(method_handle()); + _dependencies->assert_evol_method(method()); + } + } } // constructor used to create a method @@ -424,7 +430,7 @@ CodeBuffer buffer(buffer_blob); jobject compiled_code_obj = JNIHandles::make_local(compiled_code()); - initialize_assumptions(JNIHandles::resolve(compiled_code_obj)); + initialize_dependencies(JNIHandles::resolve(compiled_code_obj)); // Get instructions and constants CodeSections early because we need it. _instructions = buffer.insts(); @@ -456,13 +462,13 @@ methodHandle method = getMethodFromHotSpotMethod(HotSpotCompiledNmethod::method(compiled_code)); jint entry_bci = HotSpotCompiledNmethod::entryBCI(compiled_code); jint id = HotSpotCompiledNmethod::id(compiled_code); - CompileTask* task = (CompileTask*) (address) HotSpotCompiledNmethod::ctask(compiled_code); + GraalEnv* env = (GraalEnv*) (address) HotSpotCompiledNmethod::graalEnv(compiled_code); if (id == -1) { // Make sure a valid compile_id is associated with every compile id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci); } result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, - GraalCompiler::instance(), _debug_recorder, _dependencies, task, id, false, installed_code, speculation_log); + GraalCompiler::instance(), _debug_recorder, _dependencies, env, id, false, installed_code, speculation_log); cb = nm; } @@ -639,12 +645,6 @@ return true; } -void CodeInstaller::assumption_MethodContents(Handle assumption) { - Handle method_handle = Assumptions_MethodContents::method(assumption()); - methodHandle method = getMethodFromHotSpotMethod(method_handle()); - _dependencies->assert_evol_method(method()); -} - void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) { Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption()); Klass* receiverType = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(receiverType_handle)); diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Thu Feb 12 20:47:20 2015 +0100 @@ -122,14 +122,13 @@ private: // extract the fields of the CompilationResult void initialize_fields(oop target_method); - void initialize_assumptions(oop target_method); + void initialize_dependencies(oop target_method); int estimate_stub_entries(); // perform data and call relocation on the CodeBuffer bool initialize_buffer(CodeBuffer& buffer); - void assumption_MethodContents(Handle assumption); void assumption_NoFinalizableSubclass(Handle assumption); void assumption_ConcreteSubtype(Handle assumption); void assumption_ConcreteMethod(Handle assumption); diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Thu Feb 12 20:47:20 2015 +0100 @@ -105,7 +105,7 @@ _bootstrapping = false; } -void GraalCompiler::compile_method(methodHandle method, int entry_bci, CompileTask* task) { +void GraalCompiler::compile_method(methodHandle method, int entry_bci, GraalEnv* env) { GRAAL_EXCEPTION_CONTEXT bool is_osr = entry_bci != InvocationEntryBci; @@ -122,8 +122,8 @@ JavaCallArguments args; args.push_long((jlong) (address) method()); args.push_int(entry_bci); - args.push_long((jlong) (address) task); - args.push_int(task->compile_id()); + args.push_long((jlong) (address) env); + args.push_int(env->task()->compile_id()); JavaCalls::call_static(&result, SystemDictionary::CompilationTask_klass(), vmSymbols::compileMetaspaceMethod_name(), vmSymbols::compileMetaspaceMethod_signature(), &args, CHECK_ABORT); _methodsCompiled++; diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/graalCompiler.hpp Thu Feb 12 20:47:20 2015 +0100 @@ -25,6 +25,7 @@ #define SHARE_VM_GRAAL_GRAAL_COMPILER_HPP #include "compiler/abstractCompiler.hpp" +#include "graal/graalEnv.hpp" class GraalCompiler : public AbstractCompiler { @@ -72,7 +73,7 @@ // Compilation entry point for methods virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); - void compile_method(methodHandle target, int entry_bci, CompileTask* task); + void compile_method(methodHandle target, int entry_bci, GraalEnv* env); // Print compilation timers and statistics virtual void print_timers(); diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/graalEnv.cpp --- a/src/share/vm/graal/graalEnv.cpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/graalEnv.cpp Thu Feb 12 20:47:20 2015 +0100 @@ -45,6 +45,18 @@ #include "graal/graalRuntime.hpp" #include "graal/graalJavaAccess.hpp" +GraalEnv::GraalEnv(CompileTask* task, int system_dictionary_modification_counter) { + _task = task; + _system_dictionary_modification_counter = system_dictionary_modification_counter; + { + // Get Jvmti capabilities under lock to get consistent values. + MutexLocker mu(JvmtiThreadState_lock); + _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint(); + _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables(); + _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions(); + } +} + // ------------------------------------------------------------------ // Note: the logic of this method should mirror the logic of // constantPoolOopDesc::verify_constant_pool_resolve. @@ -409,19 +421,23 @@ // ------------------------------------------------------------------ // Check for changes to the system dictionary during compilation // class loads, evolution, breakpoints -bool GraalEnv::check_for_system_dictionary_modification(Dependencies* dependencies) { - // Dependencies must be checked when the system dictionary changes. - // If logging is enabled all violated dependences will be recorded in - // the log. In debug mode check dependencies even if the system - // dictionary hasn't changed to verify that no invalid dependencies - // were inserted. Any violated dependences in this case are dumped to - // the tty. +bool GraalEnv::check_for_system_dictionary_modification(Dependencies* dependencies, GraalEnv* env) { + // If JVMTI capabilities were enabled during compile, the compilation is invalidated. + if (env != NULL) { + if (!env->_jvmti_can_hotswap_or_post_breakpoint && JvmtiExport::can_hotswap_or_post_breakpoint()) { + // Hotswapping or breakpointing was enabled during compilation + return false; + } + } - // TODO (thomaswue): Always check dependency for now. - //bool counter_changed = system_dictionary_modification_counter_changed(); - //bool test_deps = counter_changed; - //DEBUG_ONLY(test_deps = true); - //if (!test_deps) return; + // Dependencies must be checked when the system dictionary changes + // or if we don't know whether it has changed (i.e., env == NULL). + // In debug mode, always check dependencies. + bool counter_changed = env != NULL && env->_system_dictionary_modification_counter != SystemDictionary::number_of_modifications(); + bool verify_deps = env == NULL || trueInDebug; + if (!counter_changed && !verify_deps) { + return true; + } for (Dependencies::DepStream deps(dependencies); deps.next(); ) { Klass* witness = deps.check_dependency(); @@ -450,7 +466,7 @@ AbstractCompiler* compiler, DebugInformationRecorder* debug_info, Dependencies* dependencies, - CompileTask* task, + GraalEnv* env, int compile_id, bool has_unsafe_access, Handle installed_code, @@ -471,7 +487,7 @@ dependencies->encode_content_bytes(); // Check for {class loads, evolution, breakpoints} during compilation - if (!check_for_system_dictionary_modification(dependencies)) { + if (!check_for_system_dictionary_modification(dependencies, env)) { // While not a true deoptimization, it is a preemptive decompile. MethodData* mdp = method()->method_data(); if (mdp != NULL) { @@ -516,6 +532,7 @@ // Record successful registration. // (Put nm into the task handle *before* publishing to the Java heap.) + CompileTask* task = env == NULL ? NULL : env->task(); if (task != NULL) task->set_code(nm); if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) { diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/graalEnv.hpp --- a/src/share/vm/graal/graalEnv.hpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/graalEnv.hpp Thu Feb 12 20:47:20 2015 +0100 @@ -50,7 +50,7 @@ // // This class is the top level broker for requests from the compiler // to the VM. -class GraalEnv : AllStatic { +class GraalEnv : StackObj { CI_PACKAGE_ACCESS_TO friend class CompileBroker; @@ -92,7 +92,16 @@ int method_index, Bytecodes::Code bc, instanceKlassHandle& loading_klass); + GraalEnv(CompileTask* task, int system_dictionary_modification_counter); + private: + CompileTask* _task; + int _system_dictionary_modification_counter; + + // Cache JVMTI state + bool _jvmti_can_hotswap_or_post_breakpoint; + bool _jvmti_can_access_local_variables; + bool _jvmti_can_post_on_exceptions; // Implementation methods for loading and constant pool access. static KlassHandle get_klass_by_name_impl(KlassHandle& accessing_klass, @@ -124,9 +133,11 @@ // Helper routine for determining the validity of a compilation // with respect to concurrent class loading. - static bool check_for_system_dictionary_modification(Dependencies* target); + static bool check_for_system_dictionary_modification(Dependencies* target, GraalEnv* env); public: + CompileTask* task() { return _task; } + // Register the result of a compilation. static GraalEnv::CodeInstallResult register_method( methodHandle& target, @@ -141,7 +152,7 @@ AbstractCompiler* compiler, DebugInformationRecorder* debug_info, Dependencies* dependencies, - CompileTask* task, + GraalEnv* env, int compile_id, bool has_unsafe_access, Handle installed_code, diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu Feb 12 20:47:20 2015 +0100 @@ -84,7 +84,7 @@ oop_field(HotSpotCompiledNmethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ int_field(HotSpotCompiledNmethod, entryBCI) \ int_field(HotSpotCompiledNmethod, id) \ - long_field(HotSpotCompiledNmethod, ctask) \ + long_field(HotSpotCompiledNmethod, graalEnv) \ end_class \ start_class(HotSpotCompiledRuntimeStub) \ oop_field(HotSpotCompiledRuntimeStub, stubName, "Ljava/lang/String;") \ @@ -96,15 +96,10 @@ int_field(CompilationResult, totalFrameSize) \ int_field(CompilationResult, customStackAreaOffset) \ typeArrayOop_field(CompilationResult, targetCode, "[B") \ - oop_field(CompilationResult, assumptions, "Lcom/oracle/graal/api/code/Assumptions;") \ + objArrayOop_field(CompilationResult, assumptions, "[Lcom/oracle/graal/api/code/Assumptions$Assumption;") \ + objArrayOop_field(CompilationResult, methods, "[Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ int_field(CompilationResult, targetCodeSize) \ end_class \ - start_class(Assumptions) \ - objArrayOop_field(Assumptions, list, "[Lcom/oracle/graal/api/code/Assumptions$Assumption;") \ - end_class \ - start_class(Assumptions_MethodContents) \ - oop_field(Assumptions_MethodContents, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ - end_class \ start_class(Assumptions_NoFinalizableSubclass) \ oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ end_class \ diff -r fcefaa7f103d -r 57c53b1044a7 src/share/vm/graal/vmStructs_graal.hpp --- a/src/share/vm/graal/vmStructs_graal.hpp Thu Feb 12 20:46:56 2015 +0100 +++ b/src/share/vm/graal/vmStructs_graal.hpp Thu Feb 12 20:47:20 2015 +0100 @@ -36,6 +36,8 @@ nonstatic_field(ThreadShadow, _pending_failed_speculation, oop) \ nonstatic_field(ThreadShadow, _pending_transfer_to_interpreter, bool) \ nonstatic_field(MethodData, _graal_node_count, int) \ + nonstatic_field(GraalEnv, _task, CompileTask*) \ + nonstatic_field(GraalEnv, _jvmti_can_hotswap_or_post_breakpoint, bool) \ #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type) \