Mercurial > hg > truffle
changeset 19312:a8d128366ebf
Merge
author | Andreas Woess <andreas.woess@jku.at> |
---|---|
date | Thu, 12 Feb 2015 04:01:46 +0100 |
parents | a0a760b0fb5f (diff) b54b548047ac (current diff) |
children | a7247418a58b |
files | graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java |
diffstat | 189 files changed, 7180 insertions(+), 5096 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGELOG.md Thu Feb 12 03:42:51 2015 +0100 +++ b/CHANGELOG.md Thu Feb 12 04:01:46 2015 +0100 @@ -19,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)
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Thu Feb 12 04:01:46 2015 +0100 @@ -29,16 +29,16 @@ import com.oracle.graal.api.meta.*; /** - * Class for recording assumptions made during compilation. {@link OptimisticAssumption}s can only - * be recorded in an {@link Assumptions} object if it {@linkplain #useOptimisticAssumptions() - * allows} them. + * Class for recording assumptions made during compilation. */ public final class Assumptions implements Serializable, Iterable<Assumptions.Assumption> { 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 { @@ -46,23 +46,9 @@ } /** - * Abstract base class for optimistic assumptions. An optimistic 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()}). A non-optimistic - * assumption assumes a property that will most likely only be invalidated by an external - * interface to the runtime (e.g., a {@linkplain MethodContents breakpoint is set or a class is - * redefined}). + * An assumption that a given class has no subclasses implementing {@link Object#finalize()}). */ - public abstract static class OptimisticAssumption extends Assumption { - - private static final long serialVersionUID = -1936652569665112932L; - } - - /** - * An optimistic assumption that a given class has no subclasses implementing - * {@link Object#finalize()}). - */ - public static final class NoFinalizableSubclass extends OptimisticAssumption { + public static final class NoFinalizableSubclass extends Assumption { private static final long serialVersionUID = 6451169735564055081L; @@ -94,9 +80,9 @@ } /** - * An optimistic assumption that a given type has a given unique subtype. + * An assumption that a given type has a given unique subtype. */ - public static final class ConcreteSubtype extends OptimisticAssumption { + public static final class ConcreteSubtype extends Assumption { private static final long serialVersionUID = -1457173265437676252L; @@ -142,9 +128,9 @@ } /** - * An optimistic assumption that a given virtual method has a given unique implementation. + * An assumption that a given virtual method has a given unique implementation. */ - public static final class ConcreteMethod extends OptimisticAssumption { + public static final class ConcreteMethod extends Assumption { private static final long serialVersionUID = -7636746737947390059L; @@ -196,49 +182,9 @@ } /** - * An non-optimistic assumption that the bytecodes of a given method used during compilation - * will not change. This kind of dependency may be used to invalidate and deoptimize compiled - * code when: - * <ul> - * <li>one of its constituent methods is redefined or</li> - * <li>a breakpoint is set in one of its constituent methods and the runtime only implements - * breakpoint support in non-compiled code. - * </ul> + * An assumption that a given call site's method handle did not change. */ - 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)%r") + "]"; - } - } - - /** - * An optimistic assumption that a given call site's method handle did not change. - */ - public static final class CallSiteTargetValue extends OptimisticAssumption { + public static final class CallSiteTargetValue extends Assumption { private static final long serialVersionUID = 1732459941784550371L; @@ -274,26 +220,7 @@ } } - private Set<Assumption> assumptions; - - /** - * Specifies whether {@link OptimisticAssumption}s can be made. - */ - private boolean allowOptimisticAssumptions; - - public static final boolean ALLOW_OPTIMISTIC_ASSUMPTIONS = true; - public static final boolean DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS = false; - - /** - * Creates an object for recording assumptions. - * - * @param allowOptimisticAssumptions specifies whether {@link OptimisticAssumption}s can be - * recorded in this object - */ - public Assumptions(boolean allowOptimisticAssumptions) { - this.allowOptimisticAssumptions = allowOptimisticAssumptions; - assumptions = new HashSet<>(); - } + private final Set<Assumption> assumptions = new HashSet<>(); /** * Returns whether any assumptions have been registered. @@ -304,13 +231,6 @@ return assumptions.isEmpty(); } - /** - * Determines whether {@link OptimisticAssumption}s can be made. - */ - public boolean useOptimisticAssumptions() { - return allowOptimisticAssumptions; - } - @Override public int hashCode() { throw new UnsupportedOperationException("hashCode"); @@ -323,7 +243,7 @@ } if (obj instanceof Assumptions) { Assumptions that = (Assumptions) obj; - if (this.allowOptimisticAssumptions != that.allowOptimisticAssumptions || !this.assumptions.equals(that.assumptions)) { + if (!this.assumptions.equals(that.assumptions)) { return false; } return true; @@ -368,17 +288,7 @@ 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) { - assert allowOptimisticAssumptions || !(assumption instanceof OptimisticAssumption) : "cannot make optimistic assumption: " + assumption; assumptions.add(assumption); } @@ -399,6 +309,6 @@ @Override public String toString() { - return "Assumptions{optimistic=" + allowOptimisticAssumptions + ", assumptions=" + assumptions + "}"; + return "Assumptions[" + assumptions + "]"; } }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Thu Feb 12 04:01:46 2015 +0100 @@ -531,6 +531,11 @@ private Assumption[] assumptions; + /** + * The list of the methods whose bytecodes were used as input to the compilation. + */ + private ResolvedJavaMethod[] methods; + public CompilationResult() { this(null); } @@ -607,18 +612,36 @@ this.entryBCI = entryBCI; } + /** + * Sets the assumptions made during compilation. + */ public void setAssumptions(Assumption[] assumptions) { this.assumptions = assumptions; } /** - * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the assumptions recorded in - * this object. + * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the assumptions made during + * compilation. */ public Collection<Assumption> 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<ResolvedJavaMethod> getMethods() { + return methods == null ? Collections.emptyList() : Arrays.asList(methods); + } + public DataSection getDataSection() { return dataSection; }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Thu Feb 12 04:01:46 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 {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -306,7 +305,7 @@ } private void processMethod(final String snippet) { - graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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,7 +316,7 @@ } private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) { - graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context); @@ -332,7 +331,7 @@ new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); - StructuredGraph referenceGraph = parseEager(referenceSnippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); new InliningPhase(new CanonicalizerPhase(true)).apply(referenceGraph, context); new DeadCodeEliminationPhase().apply(referenceGraph); new CanonicalizerPhase(true).apply(referenceGraph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*; import java.io.*; @@ -45,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.*; @@ -139,7 +139,7 @@ if (matches(filters, methodName)) { executor.execute(() -> { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,12 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import org.junit.*; 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,7 +35,7 @@ public class CompareCanonicalizerTest extends GraalCompilerTest { private StructuredGraph getCanonicalizedGraph(String name) { - StructuredGraph graph = parseEager(name, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(name, AllowAssumptions.YES); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); return graph; } @@ -48,9 +48,9 @@ @Test public void testCanonicalComparison() { - StructuredGraph referenceGraph = parseEager("referenceCanonicalComparison", DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager("referenceCanonicalComparison", AllowAssumptions.NO); for (int i = 1; i < 4; i++) { - StructuredGraph graph = parseEager("canonicalCompare" + i, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("canonicalCompare" + i, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders()));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,11 +22,10 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - 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.*; @@ -92,7 +91,7 @@ @Test public void testRedundantCompares() { - StructuredGraph graph = parseEager("testRedundantComparesSnippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("testRedundantComparesSnippet", AllowAssumptions.YES); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); PhaseContext context = new PhaseContext(getProviders()); @@ -115,7 +114,7 @@ @Test @Ignore public void testInstanceOfCheckCastLowered() { - StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", AllowAssumptions.YES); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); PhaseContext context = new PhaseContext(getProviders());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,13 +22,12 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -82,12 +81,12 @@ private void test(final String snippet) { try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); Debug.dump(referenceGraph, "ReferenceGraph"); assertEquals(referenceGraph, graph); } catch (Throwable e) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,13 +22,12 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -107,7 +106,7 @@ } private StructuredGraph compileSnippet(final String snippet, final int checkcasts, final int afterCanon) { - final StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,20 +22,20 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import java.io.*; import java.lang.reflect.*; import java.util.*; import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.api.code.Assumptions.NoFinalizableSubclass; import com.oracle.graal.api.meta.*; 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.*; @@ -61,11 +61,11 @@ } } - private StructuredGraph parseAndProcess(Class<?> cl, boolean allowsOptimisticAssumptions) { + 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, allowsOptimisticAssumptions); + StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(); new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), conf, OptimisticOptimizations.ALL).apply(graph); @@ -75,13 +75,16 @@ return graph; } - private void checkForRegisterFinalizeNode(Class<?> cl, boolean shouldContainFinalizer, boolean allowsOptimisticAssumptions) { - StructuredGraph graph = parseAndProcess(cl, allowsOptimisticAssumptions); + 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 : graph.getAssumptions()) { - 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, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); - checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, ALLOW_OPTIMISTIC_ASSUMPTIONS); + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, AllowAssumptions.NO); + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, AllowAssumptions.YES); - checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), false, ALLOW_OPTIMISTIC_ASSUMPTIONS); + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), false, AllowAssumptions.YES); - checkForRegisterFinalizeNode(loader.findClass("WithFinalizerAAAA"), true, ALLOW_OPTIMISTIC_ASSUMPTIONS); - checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), true, ALLOW_OPTIMISTIC_ASSUMPTIONS); + checkForRegisterFinalizeNode(loader.findClass("WithFinalizerAAAA"), true, AllowAssumptions.YES); + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), true, AllowAssumptions.YES); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -59,7 +58,7 @@ private void test(final String snippet) { try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.compiler.common.GraalOptions.*; @@ -54,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.*; @@ -72,7 +72,7 @@ * <p> * White box tests for Graal compiler transformations use this pattern: * <ol> - * <li>Create a graph by {@linkplain #parseEager(String, boolean) parsing} a method.</li> + * <li>Create a graph by {@linkplain #parseEager(String, AllowAssumptions) parsing} a method.</li> * <li>Manually modify the graph (e.g. replace a parameter node with a constant).</li> * <li>Apply a transformation to the graph.</li> * <li>Assert that the transformed graph is equal to an expected graph.</li> @@ -662,7 +662,7 @@ /** * Gets installed code for a given method, compiling it first if necessary. The graph is parsed - * {@link #parseEager(ResolvedJavaMethod, boolean) eagerly}. + * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions) eagerly}. */ protected InstalledCode getCode(ResolvedJavaMethod method) { return getCode(method, null); @@ -736,10 +736,10 @@ * is null. * * The default implementation in {@link GraalCompilerTest} is to call - * {@link #parseEager(ResolvedJavaMethod, boolean)}. + * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions)}. */ protected StructuredGraph parseForCompile(ResolvedJavaMethod method) { - return parseEager(method, ALLOW_OPTIMISTIC_ASSUMPTIONS); + return parseEager(method, AllowAssumptions.YES); } /** @@ -816,16 +816,16 @@ * * @param methodName the name of the method in {@code this.getClass()} to be parsed */ - protected StructuredGraph parseProfiled(String methodName, boolean allowOptimisticAssumptions) { - return parseProfiled(getResolvedJavaMethod(methodName), allowOptimisticAssumptions); + 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, boolean allowOptimisticAssumptions) { - return parse1(m, getDefaultGraphBuilderSuite(), allowOptimisticAssumptions); + protected StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + return parse1(m, getDefaultGraphBuilderSuite(), allowAssumptions); } /** @@ -834,30 +834,30 @@ * * @param methodName the name of the method in {@code this.getClass()} to be parsed */ - protected StructuredGraph parseEager(String methodName, boolean allowOptimisticAssumptions) { - return parseEager(getResolvedJavaMethod(methodName), allowOptimisticAssumptions); + 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, boolean allowOptimisticAssumptions) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerDefault()), allowOptimisticAssumptions); + 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, boolean allowOptimisticAssumptions) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()), allowOptimisticAssumptions); + protected StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { + return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()), allowAssumptions); } - private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite<HighTierContext> graphBuilderSuite, boolean allowOptimisticAssumptions) { + private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite<HighTierContext> 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, allowOptimisticAssumptions); + StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions); graphBuilderSuite.apply(graph, new HighTierContext(providers, null, graphBuilderSuite, OptimisticOptimizations.ALL)); return graph; } catch (Throwable e) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.graph.iterators.NodePredicates.*; import org.junit.*; @@ -30,6 +29,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.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -180,7 +180,7 @@ } private void testCombinedIf(String snippet, int count) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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); @@ -193,7 +193,7 @@ } private void test(String snippet) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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()) { @@ -205,7 +205,7 @@ fs.replaceFirstInput(param, null); param.safeDelete(); } - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.compiler.common.GraalOptions.*; @@ -38,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.*; @@ -60,7 +60,7 @@ @Test public void callInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseEager(method, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); @@ -75,7 +75,7 @@ @Test public void lineInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseDebug(method, OptAssumptions.getValue()); + 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) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,11 +22,10 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - 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.*; @@ -114,7 +113,7 @@ } private StructuredGraph getCanonicalizedGraph(String snippet) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,12 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import java.util.*; import org.junit.*; 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,7 +61,7 @@ } private void test(String snippet) { - StructuredGraph graph = parseProfiled(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseProfiled(snippet, AllowAssumptions.NO); Map<Invoke, Double> hints = new HashMap<>(); for (Invoke invoke : graph.getInvokes()) { hints.put(invoke, 1000d);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,13 +22,12 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import java.util.*; import org.junit.*; 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.*; @@ -72,7 +71,7 @@ } private void test(String snippet) { - StructuredGraph graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); Map<Invoke, Double> hints = new HashMap<>(); for (Invoke invoke : graph.getInvokes()) { hints.put(invoke, 1000d); @@ -82,7 +81,7 @@ new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -89,7 +88,7 @@ private StructuredGraph getGraph(String snippet) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - StructuredGraph graph = parseEager(method, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; import com.oracle.graal.debug.*; @@ -31,6 +29,7 @@ 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.*; @@ -122,8 +121,8 @@ } private void test(String snippet, String referenceSnippet) { - final StructuredGraph graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); - final StructuredGraph referenceGraph = parseEager(referenceSnippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + final StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); new LoopUnswitchingPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import static org.junit.Assert.*; @@ -35,6 +34,7 @@ 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,7 +596,7 @@ } private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { - final StructuredGraph graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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)) { HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -58,7 +57,7 @@ } private void testReturnCount(String snippet, int returnCount) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.graph.iterators.NodePredicates.*; import java.util.*; @@ -32,6 +31,7 @@ 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, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); ParameterNode param = graph.getNodes(ParameterNode.class).first(); if (param != null) { ConstantNode constant = ConstantNode.forInt(0, graph); @@ -105,7 +105,7 @@ private void test(String snippet) { StructuredGraph graph = parseAndProcess(snippet); - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; import com.oracle.graal.compiler.common.cfg.*; 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.*; @@ -147,7 +146,7 @@ } private void test(String snippet, int rootExits, int nestedExits, int innerExits) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); Debug.dump(graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PhiCreationTests.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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. @@ -42,7 +41,7 @@ @Test public void test1() { - StructuredGraph graph = parseEager("test1Snippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.YES); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -55,7 +54,7 @@ @Test public void test2() { - StructuredGraph graph = parseEager("test2Snippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("test2Snippet", AllowAssumptions.YES); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -68,7 +67,7 @@ @Test public void test3() { - StructuredGraph graph = parseEager("test3Snippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES); Debug.dump(graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -84,7 +83,7 @@ @Test public void test4() { - StructuredGraph graph = parseEager("test4Snippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES); Debug.dump(graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; import com.oracle.graal.api.meta.*; @@ -31,6 +29,7 @@ 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.*; @@ -92,7 +91,7 @@ } private StructuredGraph compileTestSnippet(final String snippet) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -58,7 +57,7 @@ } private void test(String snippet, String reference) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); Debug.dump(graph, "Graph"); for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) { fs.replaceAtUsages(null); @@ -67,7 +66,7 @@ new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); - StructuredGraph referenceGraph = parseEager(reference, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES); for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,13 +22,12 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -82,7 +81,7 @@ 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, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -244,9 +243,9 @@ } private <T extends Node & IterableNodeType> void test(String test, String ref) { - StructuredGraph testGraph = parseEager(test, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph testGraph = parseEager(test, AllowAssumptions.NO); new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(getProviders())); - StructuredGraph refGraph = parseEager(ref, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph refGraph = parseEager(ref, AllowAssumptions.NO); new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(getProviders())); assertEquals(testGraph, refGraph); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -131,11 +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, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); Debug.dump(graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); new CanonicalizerPhase(true).apply(graph, context); - StructuredGraph referenceGraph = parseEager(referenceSnippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); assertEquals(referenceGraph, graph); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import java.util.*; @@ -31,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.*; @@ -52,7 +52,7 @@ @Test public void testValueProxyInputs() { - StructuredGraph graph = parseEager("testValueProxyInputsSnippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("testValueProxyInputsSnippet", AllowAssumptions.YES); for (FrameState fs : graph.getNodes().filter(FrameState.class).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import java.util.*; @@ -31,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 { @@ -41,7 +41,7 @@ @Test public void testImplies() { - StructuredGraph graph = new StructuredGraph(ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES); AbstractEndNode trueEnd = graph.add(new EndNode()); AbstractEndNode falseEnd = graph.add(new EndNode());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -110,7 +109,7 @@ } private void testZeroReturn(String methodName) { - StructuredGraph graph = parseEager(methodName, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -88,10 +87,10 @@ private void test(final String snippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); Debug.dump(graph, "Graph"); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); - StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.api.code.Assumptions.*; - import java.io.*; import org.junit.*; @@ -32,6 +30,7 @@ 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.*; @@ -171,7 +170,7 @@ } private void test(String snippet, String referenceSnippet) { - StructuredGraph graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); Debug.dump(graph, "Graph"); /* * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, @@ -182,7 +181,7 @@ 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())); - StructuredGraph referenceGraph = parseEager(referenceSnippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders())); assertEquals(referenceGraph, graph); } @@ -230,7 +229,7 @@ } private <T extends Node> void testHelper(String snippet, Class<T> clazz) { - StructuredGraph graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test.backend; -import static com.oracle.graal.api.code.Assumptions.*; - import java.util.*; import org.junit.*; @@ -36,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, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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)) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.test.backend; import static com.oracle.graal.api.code.CodeUtil.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.compiler.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.compiler.test.deopt; -import static com.oracle.graal.api.code.Assumptions.*; - 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.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -53,7 +52,7 @@ @Test public void test1() { final ResolvedJavaMethod javaMethod = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseEager(javaMethod, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + final StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.NO); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders())); new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/MonitorDeoptTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -24,14 +24,13 @@ */ package com.oracle.graal.compiler.test.deopt; -import static com.oracle.graal.api.code.Assumptions.*; - 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; public final class MonitorDeoptTest extends GraalCompilerTest { @@ -136,7 +135,7 @@ public void run0() throws Throwable { ResolvedJavaMethod javaMethod = getResolvedJavaMethod("test"); - StructuredGraph graph = parseEager(javaMethod, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.YES); removeLoopSafepoint(graph); CompilationResult compilationResult = compile(javaMethod, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test.ea; -import static com.oracle.graal.api.code.Assumptions.*; - import java.util.*; import org.junit.*; @@ -34,6 +32,7 @@ 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.*; @@ -150,7 +149,7 @@ protected void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - graph = new StructuredGraph(method, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + graph = new StructuredGraph(method, AllowAssumptions.NO); try (Scope s = Debug.scope(getClass(), graph, method, getCodeCache())) { new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,10 +22,9 @@ */ package com.oracle.graal.compiler.test.ea; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; +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.*; @@ -41,7 +40,7 @@ @Override protected void processMethod(final String snippet) { - graph = parseEager(getResolvedJavaMethod(snippet), DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test.ea; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import java.util.concurrent.*; @@ -32,6 +31,7 @@ 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,7 +84,7 @@ } private void processMethod(final String snippet) { - graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + graph = parseEager(snippet, AllowAssumptions.YES); HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new IterativeInliningPhase(new CanonicalizerPhase(true)).apply(graph, context); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test.ea; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import java.util.*; @@ -31,6 +30,7 @@ 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,7 +244,7 @@ } protected void processMethod(final String snippet) { - graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test.ea; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; import com.oracle.graal.compiler.test.*; @@ -31,6 +29,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.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -60,7 +59,7 @@ private void test(final String snippet) { try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parseEager(snippet, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.compiler.test.inlining; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import org.junit.*; @@ -35,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.*; @@ -232,7 +232,7 @@ 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, ALLOW_OPTIMISTIC_ASSUMPTIONS) : parseEager(method, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = eagerInfopointMode ? parseDebug(method, AllowAssumptions.YES) : parseEager(method, AllowAssumptions.YES); PhaseSuite<HighTierContext> graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite(); HighTierContext context = new HighTierContext(getProviders(), null, graphBuilderSuite, OptimisticOptimizations.ALL); Debug.dump(graph, "Graph");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test.tutorial; -import static com.oracle.graal.api.code.Assumptions.*; - import java.lang.reflect.*; import java.util.*; import java.util.concurrent.atomic.*; @@ -39,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.*; @@ -84,7 +83,7 @@ * that we want the compilation to make optimistic assumptions about runtime state such * as the loaded class hierarchy. */ - StructuredGraph graph = new StructuredGraph(method, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.YES); /* * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test.tutorial; -import static com.oracle.graal.api.code.Assumptions.*; - import java.util.*; import com.oracle.graal.api.meta.*; @@ -34,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.*; @@ -211,7 +210,7 @@ * Build the Graal graph for the method using the bytecode parser provided by Graal. */ - StructuredGraph graph = new StructuredGraph(method, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO); /* * Support for graph dumping, IGV uses this information to show the method name of a * graph.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Feb 12 04:01:46 2015 +0100 @@ -279,7 +279,7 @@ LIRGenerationResult lirGen = null; lirGen = emitLIR(backend, target, schedule, graph, stub, cc, registerConfig, lirSuites); try (Scope s = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { - emitCode(backend, graph.getAssumptions(), lirGen, compilationResult, installedCodeOwner, factory); + emitCode(backend, graph.getAssumptions(), graph.getMethods(), lirGen, compilationResult, installedCodeOwner, factory); } catch (Throwable e) { throw Debug.handle(e); } @@ -363,15 +363,18 @@ 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<ResolvedJavaMethod> 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()) { + if (assumptions != null && !assumptions.isEmpty()) { compilationResult.setAssumptions(assumptions.toArray()); } + if (methods != null) { + compilationResult.setMethods(methods.toArray(new ResolvedJavaMethod[methods.size()])); + } if (Debug.isMeterEnabled()) { List<DataPatch> ldp = compilationResult.getDataPatches();
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.compiler.common.GraalOptions.*; @@ -42,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; @@ -205,7 +205,7 @@ } private StructuredGraph compile(String test, boolean compileAOT) { - StructuredGraph graph = parseEager(test, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(test, AllowAssumptions.YES); ResolvedJavaMethod method = graph.method(); try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java Thu Feb 12 04:01:46 2015 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import org.junit.*; @@ -33,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 { @@ -44,7 +44,7 @@ protected StructuredGraph test(final String snippet) { try (Scope s = Debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); Debug.dump(graph, snippet);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.api.code.Assumptions.*; - 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.hotspot.meta.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; public class HotSpotNmethodTest extends GraalCompilerTest { @@ -38,7 +37,7 @@ @Test public void testInstallCodeInvalidation() { final ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod("foo"); - final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", ALLOW_OPTIMISTIC_ASSUMPTIONS)); + final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", AllowAssumptions.YES)); Assert.assertTrue(nmethod.isValid()); Object result; try { @@ -61,7 +60,7 @@ @Test public void testInstallCodeInvalidationWhileRunning() { final ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod("foo"); - final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", ALLOW_OPTIMISTIC_ASSUMPTIONS)); + final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", AllowAssumptions.YES)); Object result; try { result = nmethod.executeVarargs(nmethod, null, null); @@ -75,7 +74,7 @@ @Test public void testInstalledCodeCalledFromCompiledCode() { final ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod("foo"); - final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", ALLOW_OPTIMISTIC_ASSUMPTIONS)); + final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, parseEager("otherFoo", AllowAssumptions.YES)); Assert.assertTrue(nmethod.isValid()); try { for (int i = 0; i < ITERATION_COUNT; ++i) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNodeSubstitutionsTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.replacements.test.*; /** @@ -37,7 +36,7 @@ @Test public void test() { - StructuredGraph graph = new StructuredGraph(ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES); test("getNodeClass", ConstantNode.forInt(42, graph)); }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Thu Feb 12 04:01:46 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, boolean allowOptimisticAssumptions) { - StructuredGraph graph = super.parseEager(m, allowOptimisticAssumptions); + 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);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.debug.internal.MemUseTrackerImpl.*; import static com.oracle.graal.hotspot.CompileTheWorld.*; import static com.oracle.graal.hotspot.CompileTheWorld.Options.*; @@ -35,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.*; /** @@ -165,7 +165,7 @@ private void compileAndTime(String methodName) { // Parse in eager mode to resolve methods/fields/classes - parseEager(methodName, ALLOW_OPTIMISTIC_ASSUMPTIONS); + parseEager(methodName, AllowAssumptions.YES); // Warm up and initialize compiler phases used by this compilation for (int i = 0; i < 10; i++) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.api.code.Assumptions.*; - import java.lang.ref.*; import org.junit.*; @@ -40,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.*; @@ -245,7 +244,7 @@ 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, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.api.code.Assumptions.*; - import java.util.*; import org.junit.*; @@ -38,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.*; @@ -627,7 +626,7 @@ 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, ALLOW_OPTIMISTIC_ASSUMPTIONS); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); HighTierContext highTierContext = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu Feb 12 04:01:46 2015 +0100 @@ -213,10 +213,10 @@ Replacements replacements = providers.getReplacements(); graph = replacements.getMethodSubstitution(method); if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { - graph = new StructuredGraph(method, entryBCI, OptAssumptions.getValue()); + graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue())); } else { // Compiling method substitution - must clone the graph - graph = graph.copy(); + graph = graph.copy(graph.name, method, AllowAssumptions.from(OptAssumptions.getValue())); } InlinedBytecodes.add(method.getCodeSize()); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Thu Feb 12 04:01:46 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));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.nfi; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.util.*; @@ -33,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.*; @@ -53,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, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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)));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Thu Feb 12 04:01:46 2015 +0100 @@ -32,6 +32,7 @@ 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.*; @@ -72,7 +73,7 @@ Assumptions assumptions = graph().getAssumptions(); type = getConcreteType(getObject().stamp(), assumptions, tool.getMetaAccess()); if (type != null) { - StructuredGraph newGraph = new StructuredGraph(assumptions.useOptimisticAssumptions()); + 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);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; @@ -37,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.*; @@ -191,7 +191,7 @@ Class<?>[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = linkage.getOutgoingCallingConvention().getReturn().getKind() == Kind.Object; - StructuredGraph graph = new StructuredGraph(toString(), null, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO); GraphKit kit = new HotSpotGraphKit(graph, providers); ParameterNode[] params = createParameters(kit, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Feb 12 04:01:46 2015 +0100 @@ -157,7 +157,7 @@ if (code == null) { try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { final StructuredGraph graph = getGraph(); - assert !graph.getAssumptions().useOptimisticAssumptions(); + assert graph.getAssumptions() == null; if (!(graph.start() instanceof StubStartNode)) { StubStartNode newStart = graph.add(new StubStartNode(Stub.this)); newStart.setStateAfter(graph.start().stateAfter());
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Thu Feb 12 04:01:46 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, boolean allowOptimisticAssumptions) { - StructuredGraph graph = super.parseEager(m, allowOptimisticAssumptions); + 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);
--- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeVerifier.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeVerifier.java Thu Feb 12 04:01:46 2015 +0100 @@ -117,7 +117,7 @@ List<? extends AnnotationMirror> 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;
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.test; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import org.junit.*; @@ -32,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. @@ -46,7 +46,7 @@ @Before public void before() { - graph = new StructuredGraph(ALLOW_OPTIMISTIC_ASSUMPTIONS); + graph = new StructuredGraph(AllowAssumptions.YES); } @Test
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,13 +22,12 @@ */ package com.oracle.graal.nodes.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -58,7 +57,7 @@ @Test public void test() { - StructuredGraph graph = parseEager("loopSnippet", ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager("loopSnippet", AllowAssumptions.YES); NodePredicate loopPhis = node -> node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode; PhaseContext context = new PhaseContext(getProviders());
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.test; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import org.junit.*; @@ -30,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. @@ -40,7 +40,7 @@ @Before public void before() { - graph = new StructuredGraph(ALLOW_OPTIMISTIC_ASSUMPTIONS); + graph = new StructuredGraph(AllowAssumptions.YES); } @Test
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Thu Feb 12 04:01:46 2015 +0100 @@ -26,7 +26,7 @@ import java.util.concurrent.atomic.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Assumptions.OptimisticAssumption; +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.*; @@ -82,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; @@ -101,50 +112,41 @@ private final Assumptions assumptions; /** + * The methods whose bytecodes are used while constructing this graph. + */ + private Set<ResolvedJavaMethod> methods = new HashSet<>(); + + /** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() * start} node. - * - * @param allowOptimisticAssumptions specifies whether {@link OptimisticAssumption}s can be made - * while processing the graph */ - public StructuredGraph(boolean allowOptimisticAssumptions) { - this(null, null, allowOptimisticAssumptions); + public StructuredGraph(AllowAssumptions allowAssumptions) { + this(null, null, allowAssumptions); } /** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() * start} node. - * - * @param allowOptimisticAssumptions specifies whether {@link OptimisticAssumption}s can be made - * while processing the graph */ - public StructuredGraph(String name, ResolvedJavaMethod method, boolean allowOptimisticAssumptions) { - this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI, null, allowOptimisticAssumptions); + public StructuredGraph(String name, ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI, allowAssumptions); } - /** - * @param allowOptimisticAssumptions specifies whether {@link OptimisticAssumption}s can be made - * while processing the graph - */ - public StructuredGraph(ResolvedJavaMethod method, boolean allowOptimisticAssumptions) { - this(null, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI, null, allowOptimisticAssumptions); + public StructuredGraph(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + this(null, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI, allowAssumptions); } - /** - * @param allowOptimisticAssumptions specifies whether {@link OptimisticAssumption}s can be made - * while processing the graph - */ - public StructuredGraph(ResolvedJavaMethod method, int entryBCI, boolean allowOptimisticAssumptions) { - this(null, method, uniqueGraphIds.incrementAndGet(), entryBCI, null, allowOptimisticAssumptions); + 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, Assumptions assumptions, boolean allowOptimisticAssumptions) { + 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 = assumptions == null ? new Assumptions(allowOptimisticAssumptions) : assumptions; + this.assumptions = allowAssumptions == AllowAssumptions.YES ? new Assumptions() : null; } public Stamp getReturnStamp() { @@ -218,9 +220,17 @@ } public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod) { - final boolean ignored = true; - StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI, assumptions, ignored); - assert copy.assumptions.equals(assumptions); + return copy(newName, newMethod, AllowAssumptions.from(assumptions != null)); + } + + public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod, AllowAssumptions allowAssumptions) { + StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI, allowAssumptions); + if (allowAssumptions == AllowAssumptions.YES && assumptions != null) { + copy.assumptions.record(assumptions); + } + if (!isMethodRecordingEnabled()) { + copy.disableMethodRecording(); + } copy.setGuardsStage(getGuardsStage()); copy.isAfterFloatingReadPhase = isAfterFloatingReadPhase; copy.hasValueProxies = hasValueProxies; @@ -492,7 +502,36 @@ 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<ResolvedJavaMethod> getMethods() { + return methods; + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Thu Feb 12 04:01:46 2015 +0100 @@ -73,7 +73,7 @@ ResolvedJavaType exactType; if (objectStamp.isExactType()) { exactType = objectStamp.type(); - } else if (objectStamp.type() != null && graph().getAssumptions().useOptimisticAssumptions()) { + } else if (objectStamp.type() != null && graph().getAssumptions() != null) { exactType = objectStamp.type().findUniqueConcreteSubtype(); if (exactType != null) { graph().getAssumptions().recordConcreteSubtype(objectStamp.type(), exactType);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Thu Feb 12 04:01:46 2015 +0100 @@ -70,7 +70,7 @@ return resolveExactMethod(tool, type); } Assumptions assumptions = graph().getAssumptions(); - if (type != null && assumptions.useOptimisticAssumptions()) { + if (type != null && assumptions != null) { ResolvedJavaMethod resolvedMethod = type.findUniqueConcreteMethod(method); if (resolvedMethod != null && !type.isInterface() && method.getDeclaringClass().isAssignableFrom(type)) { assumptions.recordConcreteMethod(method, type, resolvedMethod);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Thu Feb 12 04:01:46 2015 +0100 @@ -159,7 +159,7 @@ } Assumptions assumptions = graph().getAssumptions(); - if (assumptions.useOptimisticAssumptions()) { + if (assumptions != null) { ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); if (exactType != null && !exactType.equals(type)) { // Propagate more precise type information to usages of the checkcast.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Thu Feb 12 04:01:46 2015 +0100 @@ -79,7 +79,7 @@ return result; } Assumptions assumptions = graph().getAssumptions(); - if (assumptions.useOptimisticAssumptions()) { + if (assumptions != null) { ResolvedJavaType exact = stampType.findUniqueConcreteSubtype(); if (exact != null) { result = checkInstanceOf(forValue, exact, objectStamp.nonNull(), true);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Thu Feb 12 04:01:46 2015 +0100 @@ -124,7 +124,7 @@ return resolvedMethod; } Assumptions assumptions = receiver.graph().getAssumptions(); - if (assumptions.useOptimisticAssumptions()) { + if (assumptions != null) { ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); if (uniqueConcreteType != null) { ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod, contextType);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Thu Feb 12 04:01:46 2015 +0100 @@ -364,7 +364,14 @@ GraphUtil.killCFG(invokeNode); // Copy assumptions from inlinee to caller - graph.getAssumptions().record(inlineGraph.getAssumptions()); + 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; + } return duplicates; }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Thu Feb 12 04:01:46 2015 +0100 @@ -24,15 +24,13 @@ import java.util.*; -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 { @@ -67,7 +65,10 @@ } InliningUtil.InlinedBytecodes.add(concrete.getCodeSize()); - invoke.asNode().graph().getAssumptions().recordMethodContents(concrete); + StructuredGraph graph = invoke.asNode().graph(); + if (graph.isMethodRecordingEnabled()) { + graph.getMethods().add(concrete); + } return canonicalizeNodes; }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Thu Feb 12 04:01:46 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.*; @@ -198,7 +199,7 @@ * for cloning before modification.</p> */ private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { - StructuredGraph newGraph = new StructuredGraph(method, caller.getAssumptions().useOptimisticAssumptions()); + StructuredGraph newGraph = new StructuredGraph(method, AllowAssumptions.from(caller.getAssumptions() != null)); try (Debug.Scope s = Debug.scope("InlineGraph", newGraph)) { if (context.getGraphBuilderSuite() != null) { context.getGraphBuilderSuite().apply(newGraph, context);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Thu Feb 12 04:01:46 2015 +0100 @@ -193,7 +193,7 @@ } } - if (callTarget.graph().getAssumptions().useOptimisticAssumptions()) { + if (callTarget.graph().getAssumptions() != null) { ResolvedJavaType uniqueSubtype = holder.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { ResolvedJavaMethod resolvedMethod = uniqueSubtype.resolveConcreteMethod(targetMethod, contextType);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,13 +22,12 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.api.code.Assumptions.*; - import java.util.*; import org.junit.*; 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.*; @@ -331,7 +330,7 @@ @Test public void testCanonicalLength() { - StructuredGraph graph = parseEager("testCanonicalLengthSnippet", DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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())); @@ -347,7 +346,7 @@ @Test public void testCanonicalEqual() { - StructuredGraph graph = parseEager("testCanonicalEqualSnippet", DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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())); @@ -361,7 +360,7 @@ @Test public void testVirtualEqual() { - StructuredGraph graph = parseEager("testVirtualEqualSnippet", DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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())); @@ -379,7 +378,7 @@ @Test public void testVirtualNotEqual() { - StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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()));
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -248,7 +247,7 @@ * @return the returned value or null if {@code expectedClass} is not found in the graph. */ private ValueNode parseAndInline(String name, Class<? extends ValueNode> expectedClass) { - StructuredGraph graph = parseEager(name, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(name, AllowAssumptions.YES); HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Thu Feb 12 04:01:46 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, boolean allowOptimisticAssumptions) { - StructuredGraph graph = super.parseEager(m, allowOptimisticAssumptions); + 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;
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.api.code.Assumptions.*; - import java.lang.reflect.*; import org.junit.*; @@ -34,6 +32,7 @@ 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.*; @@ -55,7 +54,7 @@ } - StructuredGraph graph = new StructuredGraph(DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO); TestNode node; ConstantNode i1; ConstantNode i2; @@ -114,7 +113,7 @@ } ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); - StructuredGraph g = parseProfiled(javaMethod, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.api.code.Assumptions.*; import static org.junit.Assert.*; import java.lang.reflect.*; @@ -35,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.*; @@ -49,7 +49,7 @@ protected StructuredGraph test(final String snippet) { try (Scope s = Debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) { - StructuredGraph graph = parseEager(snippet, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.api.code.Assumptions.*; - 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.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.replacements.*; @@ -53,49 +52,49 @@ private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>(); @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, boolean allowOptimisticAssumptions) { + 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), true, LocationIdentity.ANY_LOCATION); + assertWrite(parseEager("write" + kind.name() + "3", AllowAssumptions.YES), true, LocationIdentity.ANY_LOCATION); } }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.api.code.Assumptions.*; - 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.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; @@ -59,49 +58,49 @@ private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>(); @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, boolean allowOptimisticAssumptions) { + 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), 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", ALLOW_OPTIMISTIC_ASSUMPTIONS), true, LocationIdentity.ANY_LOCATION); + assertWrite(parseEager("write" + kind.name() + "3", AllowAssumptions.YES), true, LocationIdentity.ANY_LOCATION); } } @@ -403,7 +402,7 @@ private void assertNumWordCasts(String snippetName, int expectedWordCasts) { HighTierContext context = new HighTierContext(getProviders(), null, null, OptimisticOptimizations.ALL); - StructuredGraph graph = parseEager(snippetName, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(snippetName, AllowAssumptions.YES); new CanonicalizerPhase(false).apply(graph, context); Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count()); }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Thu Feb 12 04:01:46 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.replacements.*; import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; @@ -46,7 +47,7 @@ private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>(); @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, boolean allowOptimisticAssumptions) { + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { return installer.makeGraph(m, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.compiler.common.GraalOptions.*; @@ -48,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.*; @@ -609,7 +609,7 @@ protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod 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, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + final StructuredGraph graph = new StructuredGraph(methodToParse, AllowAssumptions.NO); try (Scope s = Debug.scope("buildInitialGraph", graph)) { MetaAccessProvider metaAccess = replacements.providers.getMetaAccess();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.debug.Debug.*; @@ -50,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.*; @@ -565,7 +565,7 @@ PhaseContext phaseContext = new PhaseContext(providers); // Copy snippet graph, replacing constant parameters with given arguments - final StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method(), DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + final StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method(), AllowAssumptions.NO); Map<Node, Node> nodeReplacements = Node.newIdentityMap(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); @@ -1246,7 +1246,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(), DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph snippetCopy = new StructuredGraph(name, snippet.method(), AllowAssumptions.NO); StartNode entryPointNode = snippet.start(); FixedNode firstCFGNode = entryPointNode.next(); StructuredGraph replaceeGraph = replacee.graph();
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.truffle.hotspot; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.graph.util.CollectionsAccess.*; @@ -48,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.*; @@ -179,7 +179,7 @@ Suites suites = suitesProvider.createSuites(); LIRSuites lirSuites = suitesProvider.createLIRSuites(); removeInliningPhase(suites); - StructuredGraph graph = new StructuredGraph(javaMethod, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(javaMethod, AllowAssumptions.NO); new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); PhaseSuite<HighTierContext> graphBuilderSuite = getGraphBuilderSuite(suitesProvider); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.truffle.test; -import static com.oracle.graal.api.code.Assumptions.*; - import org.junit.*; 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.*; @@ -55,14 +54,14 @@ protected OptimizedCallTarget compileHelper(String methodName, RootNode root, Object[] arguments) { final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); - StructuredGraph actual = partialEval(compilable, arguments, ALLOW_OPTIMISTIC_ASSUMPTIONS); + 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) { final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); - StructuredGraph actual = partialEval(compilable, arguments, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph actual = partialEval(compilable, arguments, AllowAssumptions.YES); truffleCompiler.compileMethodHelper(actual, methodName, null, getSpeculationLog(), compilable); removeFrameStates(actual); StructuredGraph expected = parseForComparison(methodName); @@ -76,21 +75,21 @@ protected void assertPartialEvalNoInvokes(RootNode root, Object[] arguments) { final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root); - StructuredGraph actual = partialEval(compilable, arguments, ALLOW_OPTIMISTIC_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, boolean allowOptimisticAssumptions) { + 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, allowOptimisticAssumptions, null); + return truffleCompiler.getPartialEvaluator().createGraph(compilable, allowAssumptions, null); } catch (Throwable e) { throw Debug.handle(e); } @@ -107,7 +106,7 @@ protected StructuredGraph parseForComparison(final String methodName) { try (Scope s = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName))) { - StructuredGraph graph = parseEager(methodName, ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); compile(graph.method(), graph); return graph; } catch (Throwable e) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Feb 12 04:01:46 2015 +0100 @@ -40,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.*; @@ -96,7 +97,7 @@ } } - public StructuredGraph createGraph(final OptimizedCallTarget callTarget, boolean allowOptimisticAssumptions, GraphBuilderPlugins graalPlugins) { + public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions, GraphBuilderPlugins graalPlugins) { if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) { constantReceivers = new HashSet<>(); } @@ -107,7 +108,7 @@ throw Debug.handle(e); } - final StructuredGraph graph = new StructuredGraph(callTarget.toString(), callRootMethod, allowOptimisticAssumptions); + 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)) { @@ -277,7 +278,7 @@ } public StructuredGraph createInlineGraph(String name, StructuredGraph caller) { - StructuredGraph graph = new StructuredGraph(name, callInlinedMethod, caller.getAssumptions().useOptimisticAssumptions()); + 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; }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.truffle; -import static com.oracle.graal.api.code.Assumptions.*; - import java.util.*; import java.util.Map.Entry; @@ -36,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.*; @@ -61,7 +60,7 @@ private final HashMap<List<Object>, StructuredGraph> cache = new HashMap<>(); private final HashMap<List<Object>, Long> lastUsed = new HashMap<>(); - private final StructuredGraph markerGraph = new StructuredGraph(DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + private final StructuredGraph markerGraph = new StructuredGraph(AllowAssumptions.NO); private final ResolvedJavaType stringBuilderClass; private final ResolvedJavaType runtimeExceptionClass; @@ -120,7 +119,7 @@ lookupExceedsMaxSize(); } - StructuredGraph graph = new StructuredGraph(method, DONT_ALLOW_OPTIMISTIC_ASSUMPTIONS); + StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO); PhaseContext phaseContext = new PhaseContext(providers); try (Scope s = Debug.scope("TruffleCache", providers.getMetaAccess(), method)) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Feb 12 04:01:46 2015 +0100 @@ -22,14 +22,13 @@ */ package com.oracle.graal.truffle; -import static com.oracle.graal.api.code.Assumptions.*; import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; 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.*; @@ -43,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.*; @@ -123,7 +123,7 @@ GraphBuilderSuiteInfo info = createGraphBuilderSuite(); try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) { - graph = partialEvaluator.createGraph(compilable, ALLOW_OPTIMISTIC_ASSUMPTIONS, info.plugins); + graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES, info.plugins); } if (Thread.currentThread().isInterrupted()) { @@ -166,6 +166,13 @@ compilationNotify.notifyCompilationGraalTierFinished((OptimizedCallTarget) predefinedInstalledCode, graph); + if (graph.isMethodRecordingEnabled()) { + Set<ResolvedJavaMethod> methods = graph.getMethods(); + result.setMethods(methods.toArray(new ResolvedJavaMethod[methods.size()])); + } else { + assert result.getMethods() == null; + } + List<AssumptionValidAssumption> validAssumptions = new ArrayList<>(); Set<Assumption> newAssumptions = new HashSet<>(); for (Assumption assumption : graph.getAssumptions()) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java Thu Feb 12 04:01:46 2015 +0100 @@ -25,7 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.truffle.*; -public final class AssumptionValidAssumption extends Assumptions.OptimisticAssumption { +public final class AssumptionValidAssumption extends Assumptions.Assumption { private static final long serialVersionUID = 2010244979610891262L;
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java Thu Feb 12 04:01:46 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<Integer, Assumption> 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)); } - } }
--- /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 04:01:46 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; + } + + } + +}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Thu Feb 12 04:01:46 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; } }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Thu Feb 12 04:01:46 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();
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -104,7 +104,7 @@ return "(int)"; } - @Specialization(guards = "notInt") + @Specialization(guards = "notInt(a)") String f2(Object a) { return "(object)"; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java Thu Feb 12 04:01:46 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; }
--- /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 04:01:46 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; + } + } + +}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java Thu Feb 12 04:01:46 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<Guard1> 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<Guard2> 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"; + } + + } + }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java Thu Feb 12 04:01:46 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;
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java Thu Feb 12 04:01:46 2015 +0100 @@ -45,7 +45,7 @@ return true; } - @Specialization(guards = "!guard") + @Specialization(guards = "!guard()") int do1() { throw new AssertionError(); }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Thu Feb 12 04:01:46 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<TestGrouping> 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(); - } - - } - }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Thu Feb 12 04:01:46 2015 +0100 @@ -84,6 +84,22 @@ return Truffle.getRuntime().createCallTarget(node); } + static RootCallTarget createCallTarget(NodeFactory<? extends ValueNode> 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 extends ValueNode> T getNode(CallTarget target) { + return ((TestRootNode<T>) ((RootCallTarget) target).getRootNode()).getNode(); + } + static <E> Object executeWith(TestRootNode<? extends ValueNode> node, Object... values) { return createCallTarget(node).call(values); }
--- /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 04:01:46 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> 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 + "]"; + } + + } + +}
--- /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 04:01:46 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; + } + +}
--- /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 04:01:46 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; + } + } + +}
--- /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 04:01:46 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; + } + }; + } + } + +}
--- /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 04:01:46 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); + } + } + +}
--- /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 04:01:46 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<Object, InternalMethod> 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() + "]"; + } + + } + +}
--- /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 04:01:46 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(); + } + } + +}
--- /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 04:01:46 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.*; + +/** + * <p> + * A parameter annotated with {@link Cached} in a {@link Specialization} refers to a <b>cached</b> + * 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()}. + * </p> + * <p> + * 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. + * </p> + * <p> + * 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: + * <ol> + * <li>Dynamic and cached parameters of the enclosing specialization.</li> + * <li>Fields defined using {@link NodeField} for the enclosing node.</li> + * <li>Public constructors of the type of the annotated parameter using the <code>new</code> keyword + * as method name.</li> + * <li>Public and static methods or fields of the type of the annotated parameter.</li> + * <li>Non-private, static or virtual methods or fields of enclosing node.</li> + * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li> + * <li>Public and static methods or fields imported using {@link ImportStatic}.</li> + * </ol> + * + * 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: + * </p> + * + * <pre> + * @NodeChild("operand") + * abstract TestNode extends Node { + * abstract void execute(Object operandValue); + * // ... example here ... + * } + * </pre> + * + * <ol> + * <li> + * 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). + * + * <pre> + * @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) + * + * </pre> + * + * </li> + * <li> + * 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 <code>int</code> values and for each + * individual <code>int</code> 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 <code>3</code>. + * + * <pre> + * @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 + * + * </pre> + * + * </li> + * <li> + * To handle the limit overflow we extend our example by an additional specialization named + * <code>doNormal</code>. This specialization has the same type restrictions but does not have local + * state nor the operand identity guard. It is also declared after <code>doCached</code> therefore + * it is only instantiated if the limit of the <code>doCached</code> specialization has been + * reached. In other words <code>doNormal</code> is more generic than <code>doCached</code> . The + * <code>doNormal</code> specialization uses <code>contains="doCached"</code> to specify + * that all instantiations of <code>doCached</code> get removed if <code>doNormal</code> is + * instantiated. Alternatively if the <code>contains</code> relation is omitted then all + * <code>doCached</code> instances remain but no new instances are created. + * + * <code> + * @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) + * + * </code> + * + * </li> + * <li> + * 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 <code>private</code>. + * + * <pre> + * @Specialization + * void s(int operand, @Cached("transformLocal(operand)") int cachedOperand) { + * } + * + * int transformLocal(int operand) { + * return operand & 0x42; + * } + * + * </li> + * </pre> + * <li> + * The <code>new</code> keyword can be used to initialize a cached parameter using a constructor of + * the parameter type. + * + * <pre> + * @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(); + * } + * } + * + * </pre> + * + * </li> + * <li> + * 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. + * + * <pre> + * @Specialization + * void s(int operand, @Local("create()") BranchProfile profile) { + * } + * </pre> + * + * </li> + * </ol> + * + * @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(); + +}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java Thu Feb 12 04:01:46 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();
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportGuards.java Thu Feb 12 03:42:51 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(); - -}
--- /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 04:01:46 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 <code>public</code> and <code>static</code> 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(); + +}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java Thu Feb 12 04:01:46 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();
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java Thu Feb 12 04:01:46 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.*; + +/** + * <p> + * 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. + * </p> + * <p> + * 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. + * </p> + * <p> + * The supported kind of input values for a specialization are declared using guards. A + * specialization may provide declarative specifications for four kinds of guards: + * <ul> + * <li><b>Type guards</b> 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.</li> + * + * <li><b>Expression guards</b> optimistically assume the return value of a user-defined expression + * to be <code>true</code>. Expression guards are modeled using Java expressions that return a + * <code>boolean</code> value. If the guard expression returns <code>false</code>, the + * specialization is no longer applicable and the operation is re-specialized. Guard expressions are + * declared using the {@link #guards()} attribute.</li> + * + * <li><b>Event guards</b> 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.</li> + * + * <li><b>Assumption guards</b> optimistically assume that the state of an {@link Assumption} + * remains <code>true</code>. Assumptions can be assigned to specializations using the + * {@link #assumptions()} attribute.</li> + * </ul> + * </p> + * <p> + * The enclosing {@link Node} of a specialization method must have at least one <code>public</code> + * and non-<code>final</code> 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. + * </p> + * <p> + * 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. + * </p> + * <p> + * 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. + * </p> + * <p> + * 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. + * </p> + * + * @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 ""; + /** + * <p> + * 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. + * </p> + * + * <p> + * 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. + * </p> + * + * <b>Example usage:</b> + * + * <pre> + * @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) + * </pre> + * + * </p> + * + * @see ExactMath#addExact(int, int) + */ Class<? extends Throwable>[] 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. + * <p> + * 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. + * </p> + * <b>Example usage:</b> + * + * <pre> + * @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) + * </pre> + * + * </p> + * + * @see #guards() */ String[] contains() default {}; + /** + * <p> + * Declares <code>boolean</code> 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. + * </p> + * <p> + * 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). + * </p> + * <p> + * 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 <code>boolean</code>. Bound elements without receivers are resolved using + * the following order: + * <ol> + * <li>Dynamic and cached parameters of the enclosing specialization.</li> + * <li>Fields defined using {@link NodeField} for the enclosing node.</li> + * <li>Non-private, static or virtual methods or fields of enclosing node.</li> + * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li> + * <li>Public and static methods or fields imported using {@link ImportStatic}.</li> + * </ol> + * </p> + * <p> + * <b>Example usage:</b> + * + * <pre> + * static boolean acceptOperand(int operand) { + * assert operand <= 42; + * return operand & 1 == 1; + * } + * @Specialization(guards = {"operand <= 42", "acceptOperand(operand)"}) + * void doSpecialization(int operand) {...} + * </pre> + * + * </p> + * + * @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. + * <p> + * 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. + * </p> + * <p> + * 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: + * <ol> + * <li>Cached parameters of the enclosing specialization.</li> + * <li>Fields defined using {@link NodeField} for the enclosing node.</li> + * <li>Non-private, static or virtual methods or fields of enclosing node.</li> + * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li> + * <li>Public and static methods or fields imported using {@link ImportStatic}.</li> + * </ol> + * </p> + * + * <p> + * <b>Example usage:</b> + * + * <pre> + * 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) {...} + * </pre> + * + * </p> + * + * @see Cached + * @see ImportStatic */ String[] assumptions() default {}; + /** + * <p> + * Declares the expression that limits the number of specialization instantiations. The default + * limit for specialization instantiations is defined as <code>"3"</code>. If the limit is + * exceeded no more instantiations of the enclosing specialization method are created. Please + * note that the existing specialization instantiations are <b>not</b> removed from the + * specialization chain. You can use {@link #contains()} to remove unnecessary specializations + * instances. + * </p> + * <p> + * 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 <code>int</code>. Limit expressions are not allowed to bind to dynamic + * parameter values of the specialization. Bound elements without receivers are resolved using + * the following order: + * <ol> + * <li>Cached parameters of the enclosing specialization.</li> + * <li>Fields defined using {@link NodeField} for the enclosing node.</li> + * <li>Non-private, static or virtual methods or fields of enclosing node.</li> + * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li> + * <li>Public and static methods or fields imported using {@link ImportStatic}.</li> + * </ol> + * </p> + * + * <p> + * <b>Example usage:</b> + * + * <pre> + * static int getCacheLimit() { + * return Integer.parseInt(System.getProperty("language.cacheLimit")); + * } + * @Specialization(guards = "operand == cachedOperand", limit = "getCacheLimit()") + * void doCached(Object operand, @Cached("operand") Object cachedOperand) {...} + * </pre> + * + * </p> + * + * @see #guards() + * @see #contains() + * @see Cached + * @see ImportStatic + */ + String limit() default ""; + }
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java Thu Feb 12 04:01:46 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.
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Thu Feb 12 04:01:46 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<SpecializationNode>() { 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; + } + }
--- a/graal/com.oracle.truffle.api/.checkstyle_checks.xml Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api/.checkstyle_checks.xml Thu Feb 12 04:01:46 2015 +0100 @@ -198,6 +198,11 @@ <property name="checkFormat" value=".*Header"/> <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/> </module> + <module name="SuppressionCommentFilter"> + <property name="offCommentFormat" value="CheckStyle: start generated"/> + <property name="onCommentFormat" value="CheckStyle: stop generated"/> + <property name="checkFormat" value=".*Name|.*LineLength"/> + </module> <module name="RegexpSingleline"> <property name="format" value="System\.(out|err)\.print"/> <property name="fileExtensions" value="java"/>
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Thu Feb 12 04:01:46 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); + } + }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java Thu Feb 12 04:01:46 2015 +0100 @@ -48,4 +48,8 @@ */ public abstract Object call(VirtualFrame frame, CallTarget target, Object[] arguments); + public static IndirectCallNode create() { + return Truffle.getRuntime().createIndirectCallNode(); + } + }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Thu Feb 12 04:01:46 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; }
--- /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 04:01:46 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.
--- /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 04:01:46 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<VariableElement> findBoundVariableElements() { + final Set<VariableElement> 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<Variable> findBoundVariables() { + final Set<Variable> 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<DSLExpression> parameters; + + private ExecutableElement resolvedMethod; + + public Call(DSLExpression receiver, String name, List<DSLExpression> 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<DSLExpression> 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); + + } + +}
--- /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 04:01:46 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<String> LOGIC_OPERATORS = Arrays.asList("||"); + private static final List<String> COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">="); + private static final List<String> IDENTITY_OPERATORS = Arrays.asList("==", "!="); + private static final String CONSTRUCTOR_KEYWORD = "new"; + + private final List<VariableElement> variables = new ArrayList<>(); + private final List<ExecutableElement> methods = new ArrayList<>(); + private final ProcessorContext context; + + private DSLExpressionResolver(ProcessorContext context) { + this.context = context; + } + + public DSLExpressionResolver(ProcessorContext context, List<? extends Element> lookupElements) { + this(context); + lookup(lookupElements); + } + + public DSLExpressionResolver copy(List<? extends Element> prefixElements) { + DSLExpressionResolver resolver = new DSLExpressionResolver(context); + lookup(prefixElements); + resolver.variables.addAll(variables); + resolver.methods.addAll(methods); + return resolver; + } + + private void lookup(List<? extends Element> lookupElements) { + variablesIn(variables, lookupElements, false); + methodsIn(lookupElements); + } + + private void methodsIn(List<? extends Element> 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<VariableElement> variables, List<? extends Element> 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<ExecutableElement> 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<? extends VariableElement> 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<VariableElement> 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.<VariableElement> 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())); + } + } + +}
--- /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 04:01:46 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<out DSLExpression result> += +LogicFactor<out result> +. + + +LogicFactor<out DSLExpression result> += +ComparisonFactor<out result> +[ + ("||") (. Token op = t; .) + ComparisonFactor<out DSLExpression right> (. result = new Binary(op.val, result, right); .) +] +. + +ComparisonFactor<out DSLExpression result> += +NegateFactor<out result> +[ + ("<" | "<=" | ">" | ">=" | "==" | "!=" ) (. Token op = t; .) + NegateFactor<out DSLExpression right> (. result = new Binary(op.val, result, right); .) +] +. + + +NegateFactor<out DSLExpression result> += (. boolean negated = false; .) +[ + "!" (. negated = true; .) +] + Factor<out result> (. result = negated ? new Negate(result) : result;.) +. + + +Factor<out DSLExpression result> += (. result = null; .) + +( + MemberExpression<out result, result> +| + numericLiteral (. result = new IntLiteral(t.val); .) +| + "(" + Expression<out result> + ")" + +) +. + +MemberExpression<out DSLExpression result, DSLExpression receiver> += (. result = null; .) +( + + identifier (. Variable variable = new Variable(receiver, t.val); .) + (. result = variable; .) +[ + + "(" (. List<DSLExpression> parameters = new ArrayList<>(); + DSLExpression parameter; .) + [ + Expression<out parameter> (. parameters.add(parameter); .) + { + "," + Expression<out parameter> (. parameters.add(parameter); .) + } + ] + ")" (. result = new Call(variable.getReceiver(), variable.getName(), parameters); .) +] + +) +[ + "." MemberExpression<out result, result> +] +. +END Expression. + + +
--- /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 04:01:46 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); + } +}
--- /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 04:01:46 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<String> 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); + } +}
--- /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 04:01:46 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<DSLExpression> 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<String> 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); + } +}
--- /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 04:01:46 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
--- /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 04:01:46 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
--- /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 04:01:46 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<Variable, CodeTree> bindings; + private final CodeTree root; + private final Deque<CodeTree> stack = new ArrayDeque<>(); + + public DSLExpressionGenerator(CodeTree root, Map<Variable, CodeTree> 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<Variable, CodeTree> bindings) { + DSLExpressionGenerator writer = new DSLExpressionGenerator(root, bindings); + expression.accept(writer); + return combine(string("("), writer.pop(), string(")")); + } + +}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java Thu Feb 12 04:01:46 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<ExecutableElement> findUserConstructors(TypeMirror nodeType) { + List<ExecutableElement> 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<TypeElement> 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; + } + }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java Thu Feb 12 03:42:51 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<ExecutableElement> findUserConstructors(TypeMirror nodeType) { - TypeElement type = ElementUtils.fromTypeMirror(nodeType); - List<ExecutableElement> 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<TypeElement> 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<NodeExecutionData> 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<CodeExecutableElement> createImplicitChildrenAccessors() { - List<Set<TypeData>> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null); - List<Set<TypeData>> 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<TypeData> types = expectTypes.get(i); - if (types == null) { - types = new TreeSet<>(); - expectTypes.set(i, types); - } - types.add(parameter.getTypeSystemType()); - } - } - - List<CodeExecutableElement> methods = new ArrayList<>(); - List<Set<TypeData>> visitedList = new ArrayList<>(prototype); - for (SpecializationData spec : node.getSpecializations()) { - int signatureIndex = -1; - for (Parameter param : spec.getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - signatureIndex++; - Set<TypeData> 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<TypeData> 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<ExecutableElement> 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<SpecializationData> specializations = node.getSpecializations(); - List<SpecializationData> 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<SpecializationData>() { - - 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<TypeData> 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<SpecializationData> guardedblock, - final CodeTree elseBlock, boolean forceElse, final boolean emitAssumptions, final boolean typedCasts, final boolean castForGuardsOnly) { - return guard(outerParent, source, group, new CodeBlock<Integer>() { - - 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<Integer> 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<GuardExpression> 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<GuardExpression> 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<TypeData> 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<TypeData> 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<TypeData> 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<Parameter> 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<Parameter> 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<TypeData> 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<Parameter> getImplicitTypeParameters(SpecializationData model) { - List<Parameter> parameter = new ArrayList<>(); - for (Parameter param : model.getSignatureParameters()) { - NodeChildData child = param.getSpecification().getExecution().getChild(); - List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); - if (types.size() > 1) { - parameter.add(param); - } - } - return parameter; - } - - private List<TypeData> lookupPolymorphicTargetTypes(Parameter param) { - Set<TypeData> 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<TypeData> 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<TypeData> 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<TypeData> 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<CodeExecutableElement> createExecuteChilds(Parameter param, Set<TypeData> expectTypes) { - CodeExecutableElement executeMethod = createExecuteChild(param, null); - if (executeMethod == null) { - return Collections.emptyList(); - } - List<CodeExecutableElement> 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<TypeData> 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<CodeTree> 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<TypeData> 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<TypeData> 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<Parameter> 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<Parameter> 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<String, String> 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; - } - - /** - * <pre> - * variant1 $condition != null - * - * $type $name = defaultValue($type); - * if ($condition) { - * $name = $value; - * } - * - * variant2 $condition != null - * $type $name = $value; - * </pre> - * - * . - */ - 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<T> { - - CodeTree create(CodeTreeBuilder parent, T value); - - } - -}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Thu Feb 12 04:01:46 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<CodeTypeElement> 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<CodeTypeElement> generateNodesOld(ProcessorContext context, NodeData node) { - List<CodeTypeElement> 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) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java Thu Feb 12 04:01:46 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<ExecutableElement> constructors = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType()); + List<ExecutableElement> 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<ExecutableElement> signatures = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType()); + List<ExecutableElement> signatures = GeneratorUtils.findUserConstructors(createdFactoryElement.asType()); boolean ifStarted = false; for (ExecutableElement element : signatures) { @@ -230,7 +225,7 @@ } public void createFactoryMethods(CodeTypeElement clazz) { - List<ExecutableElement> constructors = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType()); + List<ExecutableElement> 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()); }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Thu Feb 12 04:01:46 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<SpecializationData> 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<SpecializationData> 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<SpecializationData> 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<SpecializationData, CodeTypeElement> 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<GuardExpression> ignoreGuards) { for (TypeGuard guard : group.getTypeGuards()) { if (currentValues.getValue(guard.getSignatureIndex()) == null) { // not evaluated @@ -1051,22 +1130,44 @@ } } - List<GuardExpression> expressions = new ArrayList<>(group.getGuards()); - expressions.removeAll(group.findElseConnectableGuards()); - if (!expressions.isEmpty()) { + List<GuardExpression> guards = new ArrayList<>(group.getGuards()); + List<GuardExpression> elseConnectable = group.findElseConnectableGuards(); + guards.removeAll(elseConnectable); + if (ignoreGuards != null) { + guards.removeAll(ignoreGuards); + } + SpecializationData specialization = group.getSpecialization(); + if (specialization != null && fastPath) { + for (ListIterator<GuardExpression> 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<SpecializationGroup> 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<String> 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<GuardExpression> elseGuardExpressions = group.findElseConnectableGuards(); List<GuardExpression> 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<String> 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<String> 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<Parameter> 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<Variable, LocalVariable> 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<GuardExpression> guardExpressions, LocalContext currentValues) { - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + private CodeTree[] createMethodGuardCheck(List<GuardExpression> 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<Variable, CodeTree> 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<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues, SpecializationExecution specializationExecution) { + private static Map<Variable, CodeTree> castBoundTypes(Map<Variable, LocalVariable> bindings) { + Map<Variable, CodeTree> 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<Variable, LocalVariable> bindExpressionValues(DSLExpression expression, SpecializationData specialization, LocalContext currentValues) throws AssertionError { + Map<Variable, LocalVariable> bindings = new HashMap<>(); + + Set<Variable> 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<TypeGuard> typeGuards, Set<TypeGuard> 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<Modifier> 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 {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/PolymorphicNodeFactory.java Thu Feb 12 03:42:51 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<TypeData> 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; - } - -}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/SpecializedNodeFactory.java Thu Feb 12 03:42:51 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<SpecializationData> 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<TypeMirror> 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<SpecializationData> 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<ExecutableTypeData> 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<SpecializationData>() { - - 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<ExecutableTypeData> 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<Parameter> 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<ExecutableTypeData> findFunctionalExecutableType(int evaluatedCount) { - TypeData primaryType = specialization.getReturnType().getTypeSystemType(); - List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); - - List<ExecutableTypeData> 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<SpecializationData>() { - - 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<Parameter> 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<? extends VariableElement> 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; - } -}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Thu Feb 12 04:01:46 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<TypeData> 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<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); + if (sourceTypes.size() > 1) { + clazz.add(new ImplicitCastNodeFactory(context, type).create()); } } }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Thu Feb 12 04:01:46 2015 +0100 @@ -119,16 +119,6 @@ return b.toString(); } - public static VariableElement findVariableElement(DeclaredType type, String name) { - List<? extends VariableElement> 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) { @@ -588,29 +587,6 @@ return types; } - public static List<TypeMirror> 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<TypeElement> types = getSuperTypes(typeElement); - List<TypeMirror> 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<? extends AnnotationMirror> mirrors, Class<?> annotationClass) { TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); - return findAnnotationMirror(mirrors, expectedAnnotationType); + return findAnnotationMirror(mirrors, expectedAnnotationType.asType()); } public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) { + return findAnnotationMirror(mirrors, expectedAnnotationType.asType()); + } + + public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> 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<Modifier> includeModifiers, Set<Modifier> excludeModifiers, String methodName, List<TypeMirror> 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<TypeMirror> asTypes(List<? extends Element> elements) { - List<TypeMirror> 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"); + } + } }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Thu Feb 12 04:01:46 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(); }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java Thu Feb 12 04:01:46 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<ExecutableElement> getMethods() { return ElementFilter.methodsIn(getEnclosedElements()); }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java Thu Feb 12 04:01:46 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;
--- /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 04:01:46 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.<TypeMirror> 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; + } + +}
--- /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 04:01:46 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; + } + +}
--- /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 04:01:46 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; + } + +}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Thu Feb 12 04:01:46 2015 +0100 @@ -85,12 +85,4 @@ return super.equals(obj); } - public boolean hasFrame() { - return getFrame() != null; - } - - public Parameter getFrame() { - return findParameter("frameValue"); - } - }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardData.java Thu Feb 12 03:42:51 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<GuardExpression> impliesExpressions; - - public GuardData(TemplateMethod method, List<GuardExpression> impliesExpressions) { - super(method); - this.impliesExpressions = impliesExpressions; - } - - public List<GuardExpression> 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(); - } - -}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java Thu Feb 12 04:01:46 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; - } - }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java Thu Feb 12 04:01:46 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<String> 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<String> expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value"); boolean found = false;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java Thu Feb 12 04:01:46 2015 +0100 @@ -33,6 +33,7 @@ private final ParameterSpec returnType; private final List<ParameterSpec> optional = new ArrayList<>(); private final List<ParameterSpec> required = new ArrayList<>(); + private final List<ParameterSpec> annotations = new ArrayList<>(); private boolean ignoreAdditionalParameters; private boolean ignoreAdditionalSpecifications; @@ -69,6 +70,10 @@ return spec; } + public List<ParameterSpec> 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); }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java Thu Feb 12 04:01:46 2015 +0100 @@ -52,7 +52,7 @@ private final Element accessElement; private final Cardinality cardinality; - private List<NodeChildData> executeWith = Collections.emptyList(); + private List<NodeExecutionData> executeWith = Collections.emptyList(); private NodeData childNode; @@ -66,11 +66,11 @@ this.cardinality = cardinality; } - public List<NodeChildData> getExecuteWith() { + public List<NodeExecutionData> getExecuteWith() { return executeWith; } - public void setExecuteWith(List<NodeChildData> executeWith) { + public void setExecuteWith(List<NodeExecutionData> executeWith) { this.executeWith = executeWith; }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Thu Feb 12 04:01:46 2015 +0100 @@ -42,7 +42,6 @@ private final List<NodeChildData> children; private final List<NodeExecutionData> childExecutions; private final List<NodeFieldData> fields; - private final List<String> 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<CreateCastData> getCasts() { return casts; } @@ -221,10 +215,6 @@ return getTemplateType().asType(); } - public List<String> 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) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java Thu Feb 12 04:01:46 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 + "]";
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java Thu Feb 12 04:01:46 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() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java Thu Feb 12 04:01:46 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 + "]"; } + }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Thu Feb 12 04:01:46 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
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Thu Feb 12 04:01:46 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<SpecializationThrowsData> exceptions; private List<GuardExpression> guards = Collections.emptyList(); + private List<CacheExpression> caches = Collections.emptyList(); + private List<AssumptionExpression> assumptionExpressions = Collections.emptyList(); private List<ShortCircuitData> shortCircuits; - private List<String> assumptions = Collections.emptyList(); private final Set<SpecializationData> contains = new TreeSet<>(); private final Set<String> containsNames = new TreeSet<>(); private final Set<SpecializationData> 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<SpecializationThrowsData> 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<VariableElement> 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<VariableElement> 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<Parameter> getDynamicParameters() { + List<Parameter> uncachedParameters = new ArrayList<>(getParameters()); + for (CacheExpression cacheExpression : getCaches()) { + uncachedParameters.remove(cacheExpression.getParameter()); + } + return uncachedParameters; + } + @Override protected List<MessageContainer> findChildContainers() { List<MessageContainer> 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<Parameter> currentSignature = getSignatureParameters().iterator(); - Iterator<Parameter> 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<GuardExpression> 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<String> getAssumptions() { - return assumptions; - } - - public void setAssumptions(List<String> assumptions) { - this.assumptions = assumptions; - } - public SpecializationData findNextSpecialization() { List<SpecializationData> 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<CacheExpression> getCaches() { + return caches; + } + + public void setCaches(List<CacheExpression> caches) { + this.caches = caches; + } + + public void setAssumptionExpressions(List<AssumptionExpression> assumptionExpressions) { + this.assumptionExpressions = assumptionExpressions; + } - for (Parameter param : guard.getResolvedGuard().getParameters()) { - if (ElementUtils.typeEquals(param.getType(), getNode().getFrameType())) { - return true; + public List<AssumptionExpression> getAssumptionExpressions() { + return assumptionExpressions; + } + + public boolean hasMultipleInstances() { + if (!getCaches().isEmpty()) { + for (GuardExpression guard : getGuards()) { + DSLExpression guardExpression = guard.getExpression(); + Set<VariableElement> 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<GuardExpression> 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; + } + }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Thu Feb 12 04:01:46 2015 +0100 @@ -35,6 +35,7 @@ */ public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> { + 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<Parameter> getRequiredParameters() { - List<Parameter> requiredParameters = new ArrayList<>(); - for (Parameter parameter : getParameters()) { - if (getSpecification().getRequired().contains(parameter.getSpecification())) { - requiredParameters.add(parameter); - } - } - return requiredParameters; - } - public Iterable<Parameter> getSignatureParameters() { return new FilteredIterable<>(getParameters(), new Predicate<Parameter>() { public boolean evaluate(Parameter value) { @@ -157,16 +152,6 @@ return parameters; } - public List<Parameter> findParameters(ParameterSpec spec) { - List<Parameter> 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<Parameter> getParametersAfter(Parameter genericParameter) { - boolean found = false; - List<Parameter> 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()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Thu Feb 12 04:01:46 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;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Thu Feb 12 04:01:46 2015 +0100 @@ -36,9 +36,11 @@ public class ExecutableTypeMethodParser extends NodeMethodParser<ExecutableTypeData> { private final List<TypeMirror> frameTypes; + private final NodeChildData child; - public ExecutableTypeMethodParser(ProcessorContext context, NodeData node, List<TypeMirror> frameTypes) { + public ExecutableTypeMethodParser(ProcessorContext context, NodeData node, NodeChildData child, List<TypeMirror> frameTypes) { super(context, node); + this.child = child; this.frameTypes = frameTypes; setParseNullOnError(false); getParser().setEmitErrors(false); @@ -54,9 +56,19 @@ TypeSystemData typeSystem = getNode().getTypeSystem(); List<TypeMirror> allowedTypes = typeSystem.getPrimitiveTypeMirrors(); Set<String> 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);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java Thu Feb 12 03:42:51 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<GuardData> { - - 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<Parameter> 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<TypeMirror> typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType()); - Set<String> 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<TypeMirror> nodeTypeMirrors(NodeData nodeData) { - Set<TypeMirror> typeMirrors = new LinkedHashSet<>(); - typeMirrors.addAll(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); - typeMirrors.addAll(nodeData.getTypeSystem().getBoxedTypeMirrors()); - return new ArrayList<>(typeMirrors); - } - - @Override - protected Set<String> 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<GuardExpression> guardExpressions = new ArrayList<>(); - for (String string : impliesExpressions) { - guardExpressions.add(new GuardExpression(string, false)); - } - return new GuardData(method, guardExpressions); - } - - @Override - public Class<? extends Annotation> getAnnotationType() { - return null; - } - -}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java Thu Feb 12 04:01:46 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<TypeMirror> 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<TypeMirror> parameterTypes) { + List<? extends VariableElement> 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.<Parameter> 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<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) { + private List<Parameter> parseParameters(MethodSpec spec, List<? extends VariableElement> parameterTypes, boolean varArgs) { List<Parameter> parsedRequired = null; int offset = 0; for (; offset <= parameterTypes.size(); offset++) { - List<TypeMirror> parameters = new ArrayList<>(); + List<VariableElement> 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<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset); + List<? extends VariableElement> potentialOptionals = parameterTypes.subList(0, offset); List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals); if (parsedOptionals == null) { return null; @@ -170,7 +166,7 @@ return finalParameters; } - private List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) { + private List<Parameter> parseParametersOptional(MethodSpec spec, List<? extends VariableElement> types) { List<Parameter> 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<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) { + private List<Parameter> parseParametersRequired(MethodSpec spec, List<VariableElement> types, boolean typeVarArgs) { List<Parameter> parsedParams = new ArrayList<>(); List<ParameterSpec> 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<ParameterSpec> 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<TypeMirror> types, int typeIndex, boolean varArgs) { + private static VariableElement nextActualType(List<VariableElement> 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); } }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Thu Feb 12 04:01:46 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; }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Thu Feb 12 04:01:46 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<Element> loadMembers(TypeElement templateType) { - return new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + private List<Element> loadMembers(TypeElement templateType) { + List<Element> members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + + return members; } private boolean containsSpecializations(List<Element> elements) { @@ -191,7 +200,7 @@ private void initializeImportGuards(NodeData node, List<TypeElement> lookupTypes, List<Element> 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<? extends ExecutableElement> 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<? extends Element> 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<Element> 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<TypeElement> typeHierarchy) { AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); if (typeSystemMirror == null) { @@ -255,24 +279,6 @@ } - private List<String> parseAssumptions(List<TypeElement> typeHierarchy) { - List<String> 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<String> 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<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) { Set<String> 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<String> executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); - AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); - List<NodeChildData> 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<TypeMirror> 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<String> executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith"); + AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); + List<NodeExecutionData> 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<? extends Element> 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<SpecializationData> 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<SpecializationData> 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<SpecializationData> 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<SpecializationData> nextContains = next != null ? next.getContains() : Collections.<SpecializationData> 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<SpecializationData> 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<? extends Element> elements, NodeData node) { - Map<String, List<ExecutableElement>> potentialGuards = new HashMap<>(); - for (SpecializationData specialization : node.getSpecializations()) { - for (GuardExpression exp : specialization.getGuards()) { - potentialGuards.put(exp.getGuardName(), null); - } + private void initializeExpressions(List<? extends Element> elements, NodeData node) { + List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements); + + List<VariableElement> 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<Element> 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<String> assumptionDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions"); + List<AssumptionExpression> 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<ExecutableElement> 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<CacheExpression> 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<VariableElement> 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<String, List<ExecutableElement>> guards, GuardExpression expression) { - List<ExecutableElement> 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<String> guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); + List<GuardExpression> 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<Element> filterNotAccessibleElements(TypeElement templateType, List<? extends Element> elements) { + String packageName = ElementUtils.getPackageName(templateType); + List<Element> 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<GuardData> 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<TypeMirror> parameterTypes = new ArrayList<>(); + List<VariableElement> 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<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName); if (availableCircuits == null || availableCircuits.isEmpty()) { @@ -1252,7 +1343,7 @@ List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size()); for (NodeExecutionData shortCircuit : shortCircuitExecutions) { - List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId()); + List<ShortCircuitData> 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<ExecutableElement> 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<ExecutableElement> constructors = ElementFilter.constructorsIn(nodeData.getTemplateType().getEnclosedElements()); + if (constructors.isEmpty()) { return; } - TypeElement type = ElementUtils.fromTypeMirror(nodeData.getNodeType()); - List<ExecutableElement> 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<? extends Element> elements, Class<? extends Annotation> annotation) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java Thu Feb 12 04:01:46 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()); } } }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java Thu Feb 12 04:01:46 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<String> assumptions; private final List<TypeGuard> typeGuards; private final List<GuardExpression> 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<SpecializationGroup> children, List<String> assumptionMatches, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) { + public SpecializationGroup(List<SpecializationGroup> children, List<TypeGuard> typeGuardsMatches, List<GuardExpression> 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<GuardExpression> 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<String> getAssumptions() { - return assumptions; - } - public List<TypeGuard> getTypeGuards() { return typeGuards; } @@ -174,23 +153,12 @@ return null; } - List<String> assumptionMatches = new ArrayList<>(); List<TypeGuard> typeGuardsMatches = new ArrayList<>(); List<GuardExpression> guardMatches = new ArrayList<>(); SpecializationGroup first = groups.get(0); List<SpecializationGroup> 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<GuardExpression> 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<SpecializationGroup> 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<TypeGuard> 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.<String> emptyList(), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList()); + return new SpecializationGroup(createCombinationalGroups(groups), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList()); } @Override public String toString() { - return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]"; + return "SpecializationGroup [typeGuards=" + typeGuards + ", guards=" + guards + "]"; } private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> 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<Parameter> 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<SpecializationGroup> parentChildren = getParent().getChildren(); + int index = parentChildren.indexOf(this); + if (index <= 0) { + return null; } - - return false; + return parentChildren.get(index - 1); } - }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java Thu Feb 12 04:01:46 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<String> guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); - List<GuardExpression> guardExpressions = new ArrayList<>(); - for (String guardDef : guardDefs) { - guardExpressions.add(new GuardExpression(guardDef, true)); - } - specialization.setGuards(guardExpressions); - List<String> containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains"); Set<String> containsNames = specialization.getContainsNames(); containsNames.clear(); @@ -114,15 +109,6 @@ } - List<String> 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; } }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java Thu Feb 12 04:01:46 2015 +0100 @@ -132,7 +132,7 @@ return null; } - public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) { + public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<VariableElement> parameterTypes) { TemplateMethod method = parser.parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes); if (method != null) { return create(method, method.hasErrors());
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java Thu Feb 12 04:01:46 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();
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java Thu Feb 12 03:42:51 2015 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java Thu Feb 12 04:01:46 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); }
--- a/src/share/vm/classfile/systemDictionary.hpp Thu Feb 12 03:42:51 2015 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Feb 12 04:01:46 2015 +0100 @@ -207,7 +207,6 @@ 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)) \
--- a/src/share/vm/classfile/vmSymbols.hpp Thu Feb 12 03:42:51 2015 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Feb 12 04:01:46 2015 +0100 @@ -321,7 +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_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")) \
--- a/src/share/vm/graal/graalCodeInstaller.cpp Thu Feb 12 03:42:51 2015 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu Feb 12 04:01:46 2015 +0100 @@ -384,7 +384,7 @@ 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); @@ -395,9 +395,7 @@ 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); @@ -412,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 @@ -423,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(); @@ -638,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));
--- a/src/share/vm/graal/graalCodeInstaller.hpp Thu Feb 12 03:42:51 2015 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Thu Feb 12 04:01:46 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);
--- a/src/share/vm/graal/graalJavaAccess.hpp Thu Feb 12 03:42:51 2015 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu Feb 12 04:01:46 2015 +0100 @@ -96,12 +96,10 @@ int_field(CompilationResult, totalFrameSize) \ int_field(CompilationResult, customStackAreaOffset) \ typeArrayOop_field(CompilationResult, targetCode, "[B") \ - objArrayOop_field(CompilationResult, assumptions, "[Lcom/oracle/graal/api/code/Assumptions$Assumption;") \ + 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_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 \