# HG changeset patch # User Christian Humer # Date 1420417868 -3600 # Node ID c0fb706346408129c1faef492d9d6712c6e6d459 # Parent a069a87b9a0230688e7b3732399e4bddbeefabc5 Truffle-DSL: support for frame types Frame, MaterializedFrame. Added validation for frame type consistency. Some refactorings along the way. diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Mon Jan 05 01:31:08 2015 +0100 @@ -147,6 +147,11 @@ abstract static class TestEvaluatedVarArgs0 extends ChildrenNode { + @Override + public final Object execute(VirtualFrame frame) { + return execute1(frame); + } + public abstract Object execute1(VirtualFrame frame, Object... value); @Specialization @@ -247,6 +252,11 @@ abstract static class TestEvaluatedVarArgs5 extends ValueNode { + @Override + public final Object execute(VirtualFrame frame) { + return execute1(frame); + } + public abstract Object execute1(VirtualFrame frame, Object... value); @Specialization diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java Mon Jan 05 01:31:08 2015 +0100 @@ -23,26 +23,28 @@ package com.oracle.truffle.api.dsl.test; 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.*; public class ExecuteMethodTest { - private static final String NO_EXECUTE = "No accessible and overridable generic execute method found. Generic execute methods usually have the signature 'public abstract {Type} " - + "executeGeneric(VirtualFrame)' and must not throw any checked exceptions."; + private static final String ERROR_NO_EXECUTE = "No accessible and overridable generic execute method found. Generic execute methods usually have the signature 'public abstract {Type} " + + "execute(VirtualFrame)' and must not throw any checked exceptions."; - @TypeSystem({int.class, Object[].class}) - static class ExecuteTypeSystem { - + @TypeSystem({int.class}) + @DSLOptions(useNewLayout = true) + static class ExecuteMethodTypes { } - @TypeSystemReference(ExecuteTypeSystem.class) - abstract static class ValidChildNode extends Node { + @TypeSystemReference(ExecuteMethodTypes.class) + abstract static class ChildNoFrame extends Node { abstract Object execute(); } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) - @ExpectError(NO_EXECUTE) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + @ExpectError(ERROR_NO_EXECUTE) abstract static class ExecuteThis1 extends Node { @Specialization @@ -51,9 +53,9 @@ } } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) - @ExpectError(NO_EXECUTE) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + @ExpectError(ERROR_NO_EXECUTE) abstract static class ExecuteThis2 extends Node { abstract Object execute() throws UnexpectedResultException; @@ -64,9 +66,9 @@ } } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) - @ExpectError(NO_EXECUTE) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + @ExpectError(ERROR_NO_EXECUTE) abstract static class ExecuteThis3 extends Node { abstract int execute() throws UnexpectedResultException; @@ -77,8 +79,8 @@ } } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) abstract static class ExecuteThis4 extends Node { protected abstract Object execute(); @@ -89,8 +91,8 @@ } } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) abstract static class ExecuteThis5 extends Node { public abstract Object execute(); @@ -101,9 +103,9 @@ } } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) - @ExpectError(NO_EXECUTE) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + @ExpectError(ERROR_NO_EXECUTE) abstract static class ExecuteThis6 extends Node { @SuppressWarnings({"unused", "static-method"}) @@ -117,9 +119,9 @@ } } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) - @ExpectError(NO_EXECUTE) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + @ExpectError(ERROR_NO_EXECUTE) abstract static class ExecuteThis7 extends Node { @SuppressWarnings("static-method") @@ -133,8 +135,8 @@ } } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) @ExpectError("Multiple accessible and overridable generic execute methods found [executeInt(), executeObject()]. Remove all but one or mark all but one as final.") abstract static class ExecuteThis8 extends Node { @@ -149,8 +151,8 @@ } - @TypeSystemReference(ExecuteTypeSystem.class) - @NodeChild(value = "a", type = ValidChildNode.class) + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) abstract static class ExecuteThis9 extends Node { abstract int executeInt(); @@ -166,4 +168,270 @@ } } + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteThisVoid1 extends Node { + + abstract void executeVoid(); + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteThisVoid2 extends Node { + + // allow one execute void + abstract void executeVoid(); + + abstract Object executeObject(); + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + @ExpectError("Multiple accessible and overridable generic execute methods found [executeObject(), executeVoid1(), executeVoid2()]. Remove all but one or mark all but one as final.") + abstract static class ExecuteThisVoid3 extends Node { + + // allow only one execute void + abstract void executeVoid1(); + + abstract void executeVoid2(); + + abstract Object executeObject(); + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteWithFrame1 extends Node { + + // no frame in execute. no parameter in specializations + abstract Object executeNoFrame(); + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteWithFrame2 extends Node { + + // frame in execute also usable in specialization + abstract Object executeWithFrame(VirtualFrame frame); + + @Specialization + int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteWithFrame3 extends Node { + + abstract Object executeWithFrame(Frame frame); + + @Specialization + int doInt(@SuppressWarnings("unused") Frame frame, int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ExecuteWithFrame4.class) + abstract static class ExecuteWithFrame4 extends Node { + + abstract Object executeWithFrame(MaterializedFrame frame); + + @Specialization + int doInt(@SuppressWarnings("unused") MaterializedFrame frame, int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteWithFrameError1 extends Node { + + abstract Object executeNoFrame(); + + @Specialization + @ExpectError("Method signature (VirtualFrame, int) does not match to the expected signature:%") + int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteWithFrameError2 extends Node { + + abstract Object executeFrame(MaterializedFrame frame); + + @Specialization + @ExpectError("Method signature (VirtualFrame, int) does not match to the expected signature:%") + int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteWithFrameError3 extends Node { + + abstract Object executeFrame(VirtualFrame frame); + + @Specialization + @ExpectError("Method signature (MaterializedFrame, int) does not match to the expected signature:%") + int doInt(@SuppressWarnings("unused") MaterializedFrame frame, int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + @ExpectError("Invalid inconsistent frame types [MaterializedFrame, VirtualFrame] found for the declared execute methods.%") + abstract static class ExecuteWithFrameError4 extends Node { + + abstract Object execute(VirtualFrame frame); + + abstract int executeInt(MaterializedFrame frame) throws UnexpectedResultException; + + @Specialization + int doInt(int a) { + return a; + } + } + + @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(); + + abstract int executeInt(MaterializedFrame frame) throws UnexpectedResultException; + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + abstract static class ChildVirtualFrame extends Node { + abstract Object execute(VirtualFrame frame); + } + + @TypeSystemReference(ExecuteMethodTypes.class) + abstract static class ChildMaterializedFrame extends Node { + abstract Object execute(MaterializedFrame frame); + } + + @TypeSystemReference(ExecuteMethodTypes.class) + abstract static class ChildFrame extends Node { + abstract Object execute(Frame frame); + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildNoFrame.class) + abstract static class ExecuteChildFrame1 extends Node { + + abstract Object execute(VirtualFrame frame); + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildFrame.class) + abstract static class ExecuteChildFrame2 extends Node { + + abstract Object execute(VirtualFrame frame); + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildFrame.class) + abstract static class ExecuteChildFrame3 extends Node { + + abstract Object execute(MaterializedFrame frame); + + @Specialization + int doInt(int a) { + return a; + } + } + + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildFrame.class) + abstract static class ExecuteChildFrame4 extends Node { + + abstract Object execute(Frame frame); + + @Specialization + int doInt(int a) { + return a; + } + } + + @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildVirtualFrame and frame types [com.oracle.truffle.api.frame.Frame].") + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildVirtualFrame.class) + abstract static class ExecuteChildFrameError1 extends Node { + + abstract Object execute(Frame frame); + + @Specialization + int doInt(int a) { + return a; + } + } + + @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildFrame and frame types [].") + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildFrame.class) + abstract static class ExecuteChildFrameError2 extends Node { + + abstract Object execute(); + + @Specialization + int doInt(int a) { + return a; + } + } + + @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildVirtualFrame and frame types [].") + @TypeSystemReference(ExecuteMethodTypes.class) + @NodeChild(value = "a", type = ChildVirtualFrame.class) + abstract static class ExecuteChildFrameError3 extends Node { + + abstract Object execute(); + + @Specialization + int doInt(int a) { + return a; + } + } + } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java --- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Mon Jan 05 01:31:08 2015 +0100 @@ -175,27 +175,27 @@ return start; } - public Object acceptAndExecute(VirtualFrame frame) { + public Object acceptAndExecute(Frame frame) { throw new UnsupportedOperationException(); } - public Object acceptAndExecute(VirtualFrame frame, Object o1) { + public Object acceptAndExecute(Frame frame, Object o1) { throw new UnsupportedOperationException(); } - public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2) { + public Object acceptAndExecute(Frame frame, Object o1, Object o2) { throw new UnsupportedOperationException(); } - public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2, Object o3) { + public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3) { throw new UnsupportedOperationException(); } - public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3, Object o4) { throw new UnsupportedOperationException(); } - public Object acceptAndExecute(VirtualFrame frame, Object... args) { + public Object acceptAndExecute(Frame frame, Object... args) { throw new UnsupportedOperationException(); } @@ -207,31 +207,31 @@ return null; } - protected SpecializationNode createNext(VirtualFrame frame) { + protected SpecializationNode createNext(Frame frame) { throw new UnsupportedOperationException(); } - protected SpecializationNode createNext(VirtualFrame frame, Object o1) { + protected SpecializationNode createNext(Frame frame, Object o1) { throw new UnsupportedOperationException(); } - protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2) { + protected SpecializationNode createNext(Frame frame, Object o1, Object o2) { throw new UnsupportedOperationException(); } - protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2, Object o3) { + protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3) { throw new UnsupportedOperationException(); } - protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3, Object o4) { throw new UnsupportedOperationException(); } - protected SpecializationNode createNext(VirtualFrame frame, Object... args) { + protected SpecializationNode createNext(Frame frame, Object... args) { throw new UnsupportedOperationException(); } - protected final Object uninitialized(VirtualFrame frame) { + protected final Object uninitialized(Frame frame) { CompilerDirectives.transferToInterpreterAndInvalidate(); SpecializationNode nextSpecialization = createNext(frame); if (nextSpecialization == null) { @@ -243,7 +243,7 @@ return insertSpecialization(nextSpecialization, new RewriteEvent0(findParentNode(), "inserted new specialization")).acceptAndExecute(frame); } - protected final Object uninitialized(VirtualFrame frame, Object o1) { + protected final Object uninitialized(Frame frame, Object o1) { CompilerDirectives.transferToInterpreterAndInvalidate(); SpecializationNode nextSpecialization = createNext(frame, o1); if (nextSpecialization == null) { @@ -255,7 +255,7 @@ return insertSpecialization(nextSpecialization, new RewriteEvent1(findParentNode(), "inserted new specialization", o1)).acceptAndExecute(frame, o1); } - protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2) { + protected final Object uninitialized(Frame frame, Object o1, Object o2) { CompilerDirectives.transferToInterpreterAndInvalidate(); SpecializationNode nextSpecialization = createNext(frame, o1, o2); if (nextSpecialization == null) { @@ -267,7 +267,7 @@ return insertSpecialization(nextSpecialization, new RewriteEvent2(findParentNode(), "inserted new specialization", o1, o2)).acceptAndExecute(frame, o1, o2); } - protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2, Object o3) { + protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3) { CompilerDirectives.transferToInterpreterAndInvalidate(); SpecializationNode nextSpecialization = createNext(frame, o1, o2, o3); if (nextSpecialization == null) { @@ -279,7 +279,7 @@ return insertSpecialization(nextSpecialization, new RewriteEvent3(findParentNode(), "inserted new specialization", o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3); } - protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3, Object o4) { CompilerDirectives.transferToInterpreterAndInvalidate(); SpecializationNode nextSpecialization = createNext(frame, o1, o2, o3, o4); if (nextSpecialization == null) { @@ -291,7 +291,7 @@ return insertSpecialization(nextSpecialization, new RewriteEvent4(findParentNode(), "inserts new specialization", o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4); } - protected final Object uninitialized(VirtualFrame frame, Object... args) { + protected final Object uninitialized(Frame frame, Object... args) { CompilerDirectives.transferToInterpreterAndInvalidate(); SpecializationNode nextSpecialization = createNext(frame, args); if (nextSpecialization == null) { @@ -307,51 +307,51 @@ return findStart().count() == 2; } - protected final Object remove(String reason, VirtualFrame frame) { + protected final Object remove(String reason, Frame frame) { return removeSame(new RewriteEvent0(findParentNode(), reason)).acceptAndExecute(frame); } - protected final Object remove(String reason, VirtualFrame frame, Object o1) { + protected final Object remove(String reason, Frame frame, Object o1) { return removeSame(new RewriteEvent1(findParentNode(), reason, o1)).acceptAndExecute(frame, o1); } - protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2) { + protected final Object remove(String reason, Frame frame, Object o1, Object o2) { return removeSame(new RewriteEvent2(findParentNode(), reason, o1, o2)).acceptAndExecute(frame, o1, o2); } - protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2, Object o3) { + 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); } - protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + 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); } - protected final Object remove(String reason, VirtualFrame frame, Object... args) { + protected final Object remove(String reason, Frame frame, Object... args) { return removeSame(new RewriteEventN(findParentNode(), reason, args)).acceptAndExecute(frame, args); } - protected Object unsupported(VirtualFrame frame) { + protected Object unsupported(Frame frame) { throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren()); } - protected Object unsupported(VirtualFrame frame, Object o1) { + protected Object unsupported(Frame frame, Object o1) { throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1); } - protected Object unsupported(VirtualFrame frame, Object o1, Object o2) { + protected Object unsupported(Frame frame, Object o1, Object o2) { throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2); } - protected Object unsupported(VirtualFrame frame, Object o1, Object o2, Object o3) { + protected Object unsupported(Frame frame, Object o1, Object o2, Object o3) { throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3); } - protected Object unsupported(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) { + protected Object unsupported(Frame frame, Object o1, Object o2, Object o3, Object o4) { throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3, o4); } - protected Object unsupported(VirtualFrame frame, Object... args) { + protected Object unsupported(Frame frame, Object... args) { throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), args); } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java Mon Jan 05 01:31:08 2015 +0100 @@ -33,7 +33,9 @@ */ public class Log { - public static final boolean DEBUG = false; + public static boolean isDebug() { + return false; + } private final ProcessingEnvironment processingEnv; diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java Mon Jan 05 01:31:08 2015 +0100 @@ -29,6 +29,7 @@ import javax.lang.model.type.*; import javax.lang.model.util.*; +import com.oracle.truffle.api.frame.*; import com.oracle.truffle.dsl.processor.java.*; import com.oracle.truffle.dsl.processor.java.model.*; import com.oracle.truffle.dsl.processor.model.*; @@ -137,4 +138,8 @@ public static ProcessorContext getInstance() { return instance.get(); } + + public List getFrameTypes() { + return Arrays.asList(getType(VirtualFrame.class), getType(MaterializedFrame.class), getType(Frame.class)); + } } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java Mon Jan 05 01:31:08 2015 +0100 @@ -559,7 +559,7 @@ addInternalValueParameters(method, generic, true, false, false); CodeTreeBuilder builder = method.createBuilder(); - boolean needsFrame = node.isFrameUsedByAnyGuard(context); + boolean needsFrame = node.isFrameUsedByAnyGuard(); CodeTreeBuilder createSpecializationCall = builder.create(); createSpecializationCall.startCall(SPECIALIZE); addInternalValueParameterNames(createSpecializationCall, generic, generic, null, needsFrame, !needsFrame, null); @@ -607,7 +607,7 @@ addInternalValueParameters(method, generic, true, false, false); method.addParameter(new CodeVariableElement(context.getType(String.class), "reason")); - boolean needsFrame = node.isFrameUsedByAnyGuard(context); + boolean needsFrame = node.isFrameUsedByAnyGuard(); CodeTreeBuilder builder = method.createBuilder(); builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end(); @@ -669,7 +669,7 @@ CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), baseClassName(node)), SPECIALIZE); - final boolean needsFrame = node.isFrameUsedByAnyGuard(context); + final boolean needsFrame = node.isFrameUsedByAnyGuard(); if (!needsFrame) { method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getTruffleTypes().getTruffleBoundary())); diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Mon Jan 05 01:31:08 2015 +0100 @@ -169,7 +169,7 @@ } for (NodeExecutionData execution : node.getChildExecutions()) { - if (findSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).isEmpty()) { + if (resolveSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).isEmpty()) { continue; } clazz.add(createNodeField(PRIVATE, getType(Class.class), polymorphicTypeProfileFieldName(execution), CompilationFinal.class)); @@ -225,7 +225,7 @@ CodeTree nameTree = CodeTreeBuilder.singleString(name); CodeTreeBuilder callBuilder = builder.create(); callBuilder.string(name).string(" != null ? "); - callBuilder.tree(callTemplateMethod(builder, null, createCast, nameTree)); + callBuilder.tree(callTemplateMethod(null, createCast, nameTree)); callBuilder.string(" : null"); name += "_"; builder.declaration(child.getNodeType(), name, callBuilder.build()); @@ -251,7 +251,7 @@ CodeTree accessor = accessorBuilder.build(); if (createCast != null && execution.getChild().getCardinality().isOne()) { - accessor = callTemplateMethod(builder, null, createCast, accessor); + accessor = callTemplateMethod(null, createCast, accessor); } if (execution.isIndexed()) { @@ -282,7 +282,7 @@ clazz.add(createSingleSpecialization(single)); return single; } else { - CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization(clazz)); + CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization()); TypeMirror baseSpecializationType = baseSpecialization.asType(); Map generated = new LinkedHashMap<>(); @@ -308,7 +308,7 @@ // create specialization - private CodeTypeElement createBaseSpecialization(CodeTypeElement parentClass) { + private CodeTypeElement createBaseSpecialization() { CodeTypeElement clazz = createClass(node, null, modifiers(PRIVATE, ABSTRACT, STATIC), "BaseNode_", TypeSystemNodeFactory.nodeType(typeSystem)); clazz.addOptional(createSpecializationConstructor(clazz, null, null)); @@ -330,11 +330,7 @@ specializedTypes.add(genericType); for (TypeData specializedType : specializedTypes) { if (isExecuteChildShared(execution, specializedType)) { - if (specializedType.isGeneric()) { - parentClass.add(createExecuteChildMethod(execution, specializedType)); - } else { - clazz.add(createExecuteChildMethod(execution, specializedType)); - } + clazz.add(createExecuteChildMethod(execution, specializedType)); } } } @@ -495,7 +491,7 @@ private Element createFastPathWrapVoidMethod(TypeData wrap) { CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), TypeSystemNodeFactory.executeName(typeSystem.getVoidType())); - executable.addParameter(new CodeVariableElement(getType(VirtualFrame.class), FRAME_VALUE)); + executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE)); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); builder.startStatement(); @@ -509,7 +505,7 @@ private Element createFastPathWrapExecuteMethod(TypeData override, TypeData wrap) { CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override.getPrimitiveType(), TypeSystemNodeFactory.executeName(override)); - executable.addParameter(new CodeVariableElement(getType(VirtualFrame.class), FRAME_VALUE)); + executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE)); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); if (wrap != null) { @@ -605,7 +601,7 @@ } private CodeExecutableElement createFallbackGuardMethod() { - boolean frameUsed = node.isFrameUsedByAnyGuard(context); + boolean frameUsed = node.isFrameUsedByAnyGuard(); LocalContext locals = LocalContext.load(this); if (!frameUsed) { @@ -701,7 +697,7 @@ CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); - builder.tree(callTemplateMethod(builder, accessParent(null), fallback, locals)); + builder.tree(callTemplateMethod(accessParent(null), fallback, locals)); builder.end(); return method; @@ -860,9 +856,11 @@ return childField; } - private static List findSpecializedExecutables(NodeExecutionData execution, Collection types, TypeBoxingOptimization optimization) { + private static List resolveSpecializedExecutables(NodeExecutionData execution, Collection types, TypeBoxingOptimization optimization) { if (optimization == TypeBoxingOptimization.NONE) { return Collections.emptyList(); + } else if (types.isEmpty()) { + return Collections.emptyList(); } List executables = new ArrayList<>(); @@ -878,8 +876,8 @@ return executables; } - private static CodeTree callTemplateMethod(CodeTreeBuilder parent, CodeTree receiver, TemplateMethod method, CodeTree... boundValues) { - CodeTreeBuilder builder = parent.create(); + private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, CodeTree... boundValues) { + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); if (method.getMethod().getModifiers().contains(STATIC)) { builder.startStaticCall(method.getMethod().getEnclosingElement().asType(), method.getMethodName()); } else { @@ -901,25 +899,33 @@ return builder.build(); } - private static CodeTree callTemplateMethod(CodeTreeBuilder parent, CodeTree receiver, TemplateMethod method, LocalContext currentValues) { + private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) { CodeTree[] bindings = new CodeTree[method.getParameters().size()]; int signatureIndex = 0; for (int i = 0; i < bindings.length; i++) { Parameter parameter = method.getParameters().get(i); + LocalVariable var = currentValues.get(parameter, signatureIndex); + if (var == null) { + var = currentValues.get(parameter.getLocalName()); + } + if (var != null) { - CodeTree valueReference = bindings[i] = var.createReference(); + CodeTree valueReference = var.createReference(); if (parameter.getTypeSystemType() != null && var.getType() != null && var.getType().needsCastTo(parameter.getTypeSystemType())) { valueReference = TypeSystemCodeGenerator.cast(parameter.getTypeSystemType(), valueReference); + } else if (ElementUtils.needsCastTo(var.getTypeMirror(), parameter.getType())) { + valueReference = CodeTreeBuilder.createBuilder().cast(parameter.getType(), valueReference).build(); } bindings[i] = valueReference; } + if (parameter.getSpecification().isSignature()) { signatureIndex++; } } - return callTemplateMethod(parent, receiver, method, bindings); + return callTemplateMethod(receiver, method, bindings); } private SpecializationGroup createSpecializationGroups() { @@ -931,7 +937,7 @@ if (specialization.isFallback()) { return builder.returnNull().build(); } - if (node.isFrameUsedByAnyGuard(context)) { + if (node.isFrameUsedByAnyGuard()) { builder.tree(createTransferToInterpreterAndInvalidate()); } for (SpecializationData otherSpeciailzation : node.getSpecializations()) { @@ -1154,24 +1160,27 @@ return TypeSystemCodeGenerator.expect(executedType, forType, builder.build()); } - private static ExecutableTypeData findSpecializedExecutableType(NodeExecutionData execution, TypeData type) { - NodeChildData child = execution.getChild(); + private Set findSpecializedExecutableTypes(NodeExecutionData execution, TypeData type) { + ExecutableTypeData executableType = resolveExecutableType(execution.getChild(), type); + Set executedTypes = new HashSet<>(); + executedTypes.add(executableType); + if (type.hasImplicitSourceTypes()) { + executedTypes.addAll(resolveSpecializedExecutables(execution, type.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization())); + } + return executedTypes; + } + + private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) { int executeWithCount = child.getExecuteWith().size(); - return child.getNodeData().findExecutableType(type, executeWithCount); + ExecutableTypeData executableType = child.getNodeData().findExecutableType(type, executeWithCount); + if (executableType == null) { + executableType = child.getNodeData().findAnyGenericExecutableType(context, executeWithCount); + } + return executableType; } private boolean hasUnexpectedResult(NodeExecutionData execution, TypeData type) { - if (type.isGeneric() || type.isVoid()) { - return false; - } - List executableTypes = new ArrayList<>(); - executableTypes.add(findSpecializedExecutableType(execution, type)); - - if (!options.implicitCastOptimization().isNone()) { - executableTypes.addAll(findSpecializedExecutables(execution, type.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization())); - } - - for (ExecutableTypeData executableType : executableTypes) { + for (ExecutableTypeData executableType : findSpecializedExecutableTypes(execution, type)) { if (executableType != null && executableType.hasUnexpectedValue(context)) { return true; } @@ -1245,7 +1254,7 @@ if (execution.isShortCircuit()) { ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution)); - CodeTree access = callTemplateMethod(CodeTreeBuilder.createBuilder(), accessParent(null), shortCircuitData, currentLocals); + CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals); shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access); } return shortCircuit; @@ -1269,7 +1278,7 @@ int ifCount = 0; if (specialization.isFallback()) { builder.startIf().startCall("guardFallback"); - if (node.isFrameUsedByAnyGuard(context)) { + if (node.isFrameUsedByAnyGuard()) { builder.string(FRAME_VALUE); } currentValues.addReferencesTo(builder); @@ -1286,7 +1295,7 @@ currentValues.addReferencesTo(execute, FRAME_VALUE); execute.end(); } else { - execute.tree(callTemplateMethod(execute, accessParent(null), specialization, currentValues)); + execute.tree(callTemplateMethod(accessParent(null), specialization, currentValues)); } execute.end(); builder.tree(createFastPathTryCatchRewriteException(specialization, forType, currentValues, execute.build())); @@ -1454,7 +1463,7 @@ } CodeTreeBuilder builder = method.createBuilder(); - CodeTree executeChild = createExecuteChild(execution, targetType, locals.createValue(execution, targetType), locals, true); + CodeTree executeChild = createExecuteChild(execution, locals.createValue(execution, targetType), locals, true); if (executeChild.isSingleLine()) { builder.statement(executeChild); } else { @@ -1484,7 +1493,7 @@ if (isSingleSpecializable(getReachableSpecializations())) { return false; } - return findSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).size() >= 1; + return resolveSpecializedExecutables(execution, node.findSpecializedTypes(execution), options.polymorphicTypeBoxingElimination()).size() >= 1; } else { if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) { return false; @@ -1503,7 +1512,7 @@ } } if (uses > 1) { - return findSpecializedExecutables(execution, targetType.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()).size() > 1; + return resolveSpecializedExecutables(execution, targetType.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()).size() > 1; } else { return false; } @@ -1518,7 +1527,7 @@ if (isExecuteChildShared(execution, targetValue.getType())) { executeChild = createCallSharedExecuteChild(execution, targetValue, currentValues); } else { - executeChild = createExecuteChild(execution, targetValue.getType(), targetValue, currentValues, false); + executeChild = createExecuteChild(execution, targetValue, currentValues, false); } builder.tree(createTryExecuteChild(targetValue, executeChild, shortCircuit == null, hasUnexpected)); @@ -1605,11 +1614,7 @@ CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); builder.tree(targetValue.createReference()).string(" = "); - if (targetValue.getType().isGeneric()) { - builder.startCall("root", executeChildMethodName(execution, targetValue.getType())); - } else { - builder.startCall(executeChildMethodName(execution, targetValue.getType())); - } + builder.startCall(executeChildMethodName(execution, targetValue.getType())); builder.string(FRAME_VALUE); CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getType()); @@ -1623,171 +1628,149 @@ return builder.build(); } - private CodeTree createExecuteChild(NodeExecutionData execution, TypeData returnType, LocalVariable target, LocalContext currentValues, boolean shared) { + private CodeTree createExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) { final CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - final ExecutableTypeData executableType = findSpecializedExecutableType(execution, target.getType()); - CodeTree assignment = createAssignmentStart(target, shared, false); + CodeTree assignment = createAssignmentStart(target, shared); - if (executableType == null) { - if (target.getType().isGeneric()) { - throw new AssertionError("Should be caught by the parser."); - } - CodeTree genericExecute = createExecuteChild(execution, returnType, target.makeGeneric(), currentValues, shared); - builder.tree(genericExecute); - } else { + final Set executableTypes = findSpecializedExecutableTypes(execution, target.getType()); + if (executableTypes.isEmpty()) { + throw new AssertionError(); // cannot execute child + } else if (executableTypes.size() == 1) { + ExecutableTypeData executableType = executableTypes.iterator().next(); if (target.getType().isGeneric() && executableType.getEvaluatedCount() == 0) { return createPolymorphicExecuteChild(execution, target, currentValues, shared); - } else if (target.getType().hasImplicitSourceTypes()) { - if (options.implicitCastOptimization().isNone()) { - CodeTree execute = createCallSharedExecuteChild(execution, target.makeGeneric(), currentValues); - return TypeSystemCodeGenerator.implicitExpect(target.getType(), execute, null); - } else if (options.implicitCastOptimization().isDuplicateTail()) { - builder.tree(createExecuteChildDuplicateTail(builder, execution, assignment, target, currentValues)); - } else if (options.implicitCastOptimization().isMergeCasts()) { - // TODO - } else { - throw new AssertionError(); - } } else { builder.tree(assignment); - - CodeTree accessChild; - if (shared && target.getType().isGeneric()) { - accessChild = CodeTreeBuilder.singleString(nodeFieldName(execution)); - } else { - accessChild = accessParent(nodeFieldName(execution)); - } - - CodeTree execute = callTemplateMethod(builder, accessChild, executableType, currentValues); - CodeTree expect = TypeSystemCodeGenerator.expect(executableType.getType(), returnType, execute); - builder.tree(expect); + builder.tree(createSingleExecute(execution, target, currentValues, executableType)); + } + } else { + if (options.implicitCastOptimization().isNone()) { + throw new AssertionError("findSpecializedExecutableTypes is always 1 if implicit cast opt is disabled"); + } else if (options.implicitCastOptimization().isDuplicateTail()) { + builder.tree(createExecuteChildDuplicateTail(builder, execution, assignment, target, currentValues)); + } else if (options.implicitCastOptimization().isMergeCasts()) { + // TODO + throw new UnsupportedOperationException(); + } else { + throw new AssertionError(); } } return builder.build(); } + private static CodeTree createSingleExecute(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, ExecutableTypeData executableType) { + CodeTree accessChild = accessParent(nodeFieldName(execution)); + CodeTree execute = callTemplateMethod(accessChild, executableType, currentValues); + return TypeSystemCodeGenerator.expect(executableType.getType(), target.getType(), execute); + } + private CodeTree createPolymorphicExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) throws AssertionError { ExecutableTypeData genericExecutableType = execution.getChild().getNodeData().findAnyGenericExecutableType(context, execution.getChild().getExecuteWith().size()); if (genericExecutableType == null) { - throw new AssertionError("error should be caught by the parser"); + throw new AssertionError("At least one generic executable method must be available."); } - CodeTree assignment = createAssignmentStart(target, shared, true); - - CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); - CodeTreeBuilder polyChainBuilder = builder.create(); - boolean hasUnexpectedResult = false; - Set specializedTypes = new HashSet<>(); for (TypeData type : node.findSpecializedTypes(execution)) { specializedTypes.addAll(type.getImplicitSourceTypes()); } - List specializedExecutables = findSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination()); - + List specializedExecutables = resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination()); Collections.sort(specializedExecutables, new Comparator() { public int compare(ExecutableTypeData o1, ExecutableTypeData o2) { return o1.getType().compareTo(o2.getType()); } }); - if (isSingleSpecializable(getReachableSpecializations())) { - specializedExecutables = Collections.emptyList(); - } + CodeTree assignment = createAssignmentStart(target, shared); + CodeTree executeGeneric = createSingleExecute(execution, target, currentValues, genericExecutableType); - boolean hasSpecializedTypes = false; - for (ExecutableTypeData executableType : specializedExecutables) { - hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes); - polyChainBuilder.tree(createAccessPolymorphicField(execution, shared)); - polyChainBuilder.string(" == ").typeLiteral(executableType.getType().getPrimitiveType()); - polyChainBuilder.end(); - polyChainBuilder.startBlock(); - polyChainBuilder.startStatement(); - polyChainBuilder.tree(assignment); - polyChainBuilder.tree(callTemplateMethod(polyChainBuilder, CodeTreeBuilder.singleString(nodeFieldName(execution)), executableType, currentValues)).end(); - polyChainBuilder.end(); - hasUnexpectedResult |= executableType.hasUnexpectedValue(context); - } - - CodeTree executeGeneric = callTemplateMethod(polyChainBuilder, CodeTreeBuilder.singleString(nodeFieldName(execution)), genericExecutableType, currentValues); - - if (specializedExecutables.isEmpty()) { + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + if (specializedExecutables.isEmpty() || isSingleSpecializable(getReachableSpecializations())) { builder.tree(assignment); builder.tree(executeGeneric); } else { - CodeTree accessPolymorphicProfile = createAccessPolymorphicField(execution, shared); - polyChainBuilder.startElseIf().tree(accessPolymorphicProfile).string(" == null").end(); + final CodeTreeBuilder polyChainBuilder = builder.create(); + final String profileField = polymorphicTypeProfileFieldName(execution); + final String valueFieldName = "_value"; + + builder.declaration(getType(Class.class), profileField, accessParent(profileField)); + + boolean encounteredUnexpectedResult = false; + boolean hasSpecializedTypes = false; + for (ExecutableTypeData executableType : specializedExecutables) { + hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes); + polyChainBuilder.string(profileField); + polyChainBuilder.string(" == ").typeLiteral(executableType.getType().getPrimitiveType()); + polyChainBuilder.end(); + polyChainBuilder.startBlock(); + polyChainBuilder.startStatement(); + polyChainBuilder.tree(assignment); + polyChainBuilder.tree(createSingleExecute(execution, target, currentValues, executableType)).end(); + polyChainBuilder.end(); + encounteredUnexpectedResult |= executableType.hasUnexpectedValue(context); + } + + // else if null -> specialize + polyChainBuilder.startElseIf().string(profileField).string(" == null").end(); polyChainBuilder.startBlock(); polyChainBuilder.tree(createTransferToInterpreterAndInvalidate()); - polyChainBuilder.declaration(genericExecutableType.getType().getPrimitiveType(), "value_", executeGeneric); + polyChainBuilder.declaration(genericExecutableType.getType().getPrimitiveType(), valueFieldName, executeGeneric); hasSpecializedTypes = false; for (ExecutableTypeData executableType : specializedExecutables) { hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes); - polyChainBuilder.tree(TypeSystemCodeGenerator.check(executableType.getType(), CodeTreeBuilder.singleString("value_"))); + polyChainBuilder.tree(TypeSystemCodeGenerator.check(executableType.getType(), CodeTreeBuilder.singleString(valueFieldName))); polyChainBuilder.end(); polyChainBuilder.startBlock(); - polyChainBuilder.startStatement().tree(accessPolymorphicProfile).string(" = ").typeLiteral(executableType.getType().getPrimitiveType()).end(); + polyChainBuilder.startStatement().string(profileField).string(" = ").typeLiteral(executableType.getType().getPrimitiveType()).end(); polyChainBuilder.end(); } polyChainBuilder.startElseBlock(); - polyChainBuilder.startStatement().tree(accessPolymorphicProfile).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); + polyChainBuilder.startStatement().string(profileField).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); + polyChainBuilder.end(); + polyChainBuilder.startReturn().string(valueFieldName).end(); polyChainBuilder.end(); - polyChainBuilder.startReturn().string("value_").end(); - - polyChainBuilder.end(); + // else -> execute generic polyChainBuilder.startElseBlock(); polyChainBuilder.startStatement().tree(assignment).tree(executeGeneric).end(); polyChainBuilder.end(); - if (hasUnexpectedResult) { + CodeTree executePolymorphic = polyChainBuilder.build(); + if (encounteredUnexpectedResult) { builder.startTryBlock(); - } - - builder.tree(polyChainBuilder.build()); - - if (hasUnexpectedResult) { + builder.tree(executePolymorphic); builder.end(); builder.startCatchBlock(getType(UnexpectedResultException.class), "ex"); - builder.startStatement().tree(accessPolymorphicProfile).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); + builder.startStatement().string(profileField).string(" = ").typeLiteral(genericType.getPrimitiveType()).end(); builder.startReturn().string("ex.getResult()").end(); builder.end(); + } else { + builder.tree(executePolymorphic); } } return builder.build(); } - private static CodeTree createAssignmentStart(LocalVariable target, boolean shared, boolean accessParent) { + private static CodeTree createAssignmentStart(LocalVariable target, boolean shared) { CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); if (shared) { builder.string("return "); } else { builder.string(target.getName()).string(" = "); - if (accessParent) { - builder.tree(accessParent(null)).string("."); - } } return builder.build(); } - private static CodeTree createAccessPolymorphicField(NodeExecutionData execution, boolean shared) { - String name = polymorphicTypeProfileFieldName(execution); - if (shared) { - return CodeTreeBuilder.singleString(name); - } else { - return accessParent(name); - } - } - private CodeTree createExecuteChildDuplicateTail(CodeTreeBuilder parent, NodeExecutionData execution, CodeTree assignment, LocalVariable target, LocalContext currentValues) { CodeTreeBuilder builder = parent.create(); List sourceTypes = target.getType().getImplicitSourceTypes(); String implicitClassFieldName = implicitClassFieldName(execution); String nodeFieldName = nodeFieldName(execution); - List executableTypes = findSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization()); + List executableTypes = resolveSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization()); boolean elseIf = false; for (ExecutableTypeData executableType : executableTypes) { @@ -1797,10 +1780,10 @@ builder.startBlock(); builder.startStatement().tree(assignment); - CodeTree execute = callTemplateMethod(builder, accessParent(nodeFieldName), executableType, currentValues); + CodeTree execute = callTemplateMethod(accessParent(nodeFieldName), executableType, currentValues); ImplicitCastData cast = typeSystem.lookupCast(executableType.getType(), target.getType()); if (cast != null) { - execute = callTemplateMethod(builder, null, cast, execute); + execute = callTemplateMethod(null, cast, execute); } builder.tree(execute); builder.end(); @@ -1857,7 +1840,7 @@ if (guard.isNegated()) { builder.string("!"); } - builder.tree(callTemplateMethod(builder, accessParent(null), guard.getResolvedGuard(), currentValues)); + builder.tree(callTemplateMethod(accessParent(null), guard.getResolvedGuard(), currentValues)); and = " && "; } return builder.build(); @@ -2039,7 +2022,7 @@ } private void loadValues(int evaluatedArguments) { - values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(VirtualFrame.class), FRAME_VALUE, null)); + values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null)); for (NodeFieldData field : factory.node.getFields()) { String fieldName = fieldValueName(field); diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java Mon Jan 05 01:31:08 2015 +0100 @@ -118,6 +118,14 @@ 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; diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java Mon Jan 05 01:31:08 2015 +0100 @@ -98,7 +98,7 @@ TypeData voidType = typeSystem.getVoidType(); String methodName = voidBoxingExecuteName(type); CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), voidType.getPrimitiveType(), methodName); - method.addParameter(new CodeVariableElement(context.getType(VirtualFrame.class), "frame")); + method.addParameter(new CodeVariableElement(context.getType(Frame.class), "frame")); CodeTreeBuilder builder = method.createBuilder(); builder.startTryBlock(); @@ -114,7 +114,7 @@ TypeData genericType = typeSystem.getGenericTypeData(); String methodName = executeName(type); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), methodName); - method.addParameter(new CodeVariableElement(context.getType(VirtualFrame.class), "frame")); + method.addParameter(new CodeVariableElement(context.getType(Frame.class), "frame")); if (type.isGeneric()) { method.getModifiers().add(ABSTRACT); diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Mon Jan 05 01:31:08 2015 +0100 @@ -954,6 +954,14 @@ } } + public static List getUniqueIdentifiers(List typeMirror) { + List ids = new ArrayList<>(); + for (TypeMirror type : typeMirror) { + ids.add(getUniqueIdentifier(type)); + } + return ids; + } + public static String getUniqueIdentifier(TypeMirror typeMirror) { if (typeMirror.getKind() == TypeKind.ARRAY) { return getUniqueIdentifier(((ArrayType) typeMirror).getComponentType()) + "[]"; diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Mon Jan 05 01:31:08 2015 +0100 @@ -54,23 +54,24 @@ private final NodeExecutionData thisExecution; private final boolean generateFactory; - public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, List children, List executions, - List fields, List assumptions, boolean generateFactory) { + private TypeMirror frameType; + + public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, boolean generateFactory) { super(context, type, null); - this.nodeId = type.getSimpleName().toString(); + this.nodeId = ElementUtils.getSimpleName(type); this.shortName = shortName; this.typeSystem = typeSystem; - this.fields = fields; - this.children = children; - this.childExecutions = executions; - this.assumptions = assumptions; + 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; } public NodeData(ProcessorContext context, TypeElement type) { - this(context, type, null, null, null, null, null, null, false); + this(context, type, null, null, false); } public boolean isGenerateFactory() { @@ -89,6 +90,14 @@ return false; } + public void setFrameType(TypeMirror frameType) { + this.frameType = frameType; + } + + public TypeMirror getFrameType() { + return frameType; + } + public void addEnclosedNode(NodeData node) { this.enclosingNodes.add(node); node.declaringNode = this; @@ -134,12 +143,12 @@ return 0; } - public boolean isFrameUsedByAnyGuard(ProcessorContext context) { + public boolean isFrameUsedByAnyGuard() { for (SpecializationData specialization : specializations) { if (!specialization.isReachable()) { continue; } - if (specialization.isFrameUsedByGuard(context)) { + if (specialization.isFrameUsedByGuard()) { return true; } } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Mon Jan 05 01:31:08 2015 +0100 @@ -49,6 +49,16 @@ this.allowedTypesIdentifier = typeIdentifiers; } + public ParameterSpec(String name, List allowedTypes) { + this.name = name; + this.allowedTypes = allowedTypes; + Set typeIdentifiers = new HashSet<>(); + for (TypeMirror type : allowedTypes) { + typeIdentifiers.add(ElementUtils.getUniqueIdentifier(type)); + } + this.allowedTypesIdentifier = typeIdentifiers; + } + public ParameterSpec(String name, TypeMirror type) { this(name, Arrays.asList(type), new HashSet<>(Arrays.asList(ElementUtils.getUniqueIdentifier(type)))); } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Mon Jan 05 01:31:08 2015 +0100 @@ -284,14 +284,14 @@ return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); } - public boolean isFrameUsedByGuard(ProcessorContext context) { + public boolean isFrameUsedByGuard() { for (GuardExpression guard : getGuards()) { if (guard.getResolvedGuard() == null) { continue; } for (Parameter param : guard.getResolvedGuard().getParameters()) { - if (ElementUtils.typeEquals(param.getType(), context.getTruffleTypes().getFrame())) { + if (ElementUtils.typeEquals(param.getType(), getNode().getFrameType())) { return true; } } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java Mon Jan 05 01:31:08 2015 +0100 @@ -35,8 +35,11 @@ public class ExecutableTypeMethodParser extends NodeMethodParser { - public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) { + private final List frameTypes; + + public ExecutableTypeMethodParser(ProcessorContext context, NodeData node, List frameTypes) { super(context, node); + this.frameTypes = frameTypes; setParseNullOnError(false); getParser().setEmitErrors(false); getParser().setUseVarArgs(true); @@ -48,8 +51,9 @@ List requiredSpecs = new ArrayList<>(spec.getRequired()); spec.getRequired().clear(); - List allowedTypes = getNode().getTypeSystem().getPrimitiveTypeMirrors(); - Set allowedIdentifiers = getNode().getTypeSystem().getTypeIdentifiers(); + TypeSystemData typeSystem = getNode().getTypeSystem(); + List allowedTypes = typeSystem.getPrimitiveTypeMirrors(); + Set allowedIdentifiers = typeSystem.getTypeIdentifiers(); for (ParameterSpec originalSpec : requiredSpecs) { spec.addRequired(new ParameterSpec(originalSpec, allowedTypes, allowedIdentifiers)); } @@ -64,6 +68,11 @@ } @Override + protected void addDefaultFrame(MethodSpec methodSpec) { + methodSpec.addOptional(new ParameterSpec("frame", frameTypes)); + } + + @Override protected List nodeTypeMirrors(NodeData nodeData) { return getNode().getTypeSystem().getPrimitiveTypeMirrors(); } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java Mon Jan 05 01:31:08 2015 +0100 @@ -100,9 +100,9 @@ } } - private void addDefaultFrame(MethodSpec methodSpec) { + protected void addDefaultFrame(MethodSpec methodSpec) { if (getNode().supportsFrame()) { - methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + methodSpec.addOptional(new ParameterSpec("frame", getNode().getFrameType())); } } diff -r a069a87b9a02 -r c0fb70634640 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Mon Jan 05 01:31:08 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Mon Jan 05 01:31:08 2015 +0100 @@ -45,25 +45,13 @@ public static final List> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class, NodeChildren.class); - private Map parsedNodes; - @Override protected NodeData parse(Element element, AnnotationMirror mirror) { - NodeData node = null; - try { - parsedNodes = new HashMap<>(); - node = resolveNode((TypeElement) element); - if (Log.DEBUG) { - NodeData parsed = parsedNodes.get(ElementUtils.getQualifiedName((TypeElement) element)); - if (node != null) { - String dump = parsed.dump(); - log.message(Kind.ERROR, null, null, null, dump); - } - } - } finally { - parsedNodes = null; + NodeData node = parseRootType((TypeElement) element); + if (Log.isDebug() && node != null) { + String dump = node.dump(); + log.message(Kind.ERROR, null, null, null, dump); } - return node; } @@ -96,20 +84,14 @@ return ANNOTATIONS; } - private NodeData resolveNode(TypeElement rootType) { - String typeName = ElementUtils.getQualifiedName(rootType); - if (parsedNodes.containsKey(typeName)) { - return parsedNodes.get(typeName); - } - + private NodeData parseRootType(TypeElement rootType) { List enclosedNodes = new ArrayList<>(); for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) { - NodeData enclosedChild = resolveNode(enclosedType); + NodeData enclosedChild = parseRootType(enclosedType); if (enclosedChild != null) { enclosedNodes.add(enclosedChild); } } - NodeData node = parseNode(rootType); if (node == null && !enclosedNodes.isEmpty()) { node = new NodeData(context, rootType); @@ -120,8 +102,6 @@ node.addEnclosedNode(enclosedNode); } } - - parsedNodes.put(typeName, node); return node; } @@ -134,24 +114,64 @@ return null; } - List lookupTypes = collectSuperClasses(new ArrayList(), templateType); if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { return null; } - List elements = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + + List lookupTypes = collectSuperClasses(new ArrayList(), templateType); + List members = loadMembers(templateType); + // ensure the processed element has at least one @Specialization annotation. + if (!containsSpecializations(members)) { + return null; + } - NodeData node = parseNodeData(templateType, elements, lookupTypes); + NodeData node = parseNodeData(templateType, lookupTypes); - parseImportGuards(node, lookupTypes, elements); + 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))); + + initializeExecutableTypes(node); + initializeImportGuards(node, lookupTypes, members); if (node.hasErrors()) { return node; // error sync point } - initializeExecutableTypes(elements, node); initializeChildren(node); - // ensure the processed element has at least one @Specialization annotation. + if (node.hasErrors()) { + return node; // error sync point + } + + node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(members)); + node.getSpecializations().addAll(new GenericParser(context, node).parse(members)); + node.getCasts().addAll(new CreateCastParser(context, node).parse(members)); + node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(members)); + + if (node.hasErrors()) { + return node; // error sync point + } + + verifySpecializationSameLength(node); + initializeSpecializations(members, node); + initializeShortCircuits(node); // requires specializations and polymorphic specializations + + verifyVisibilities(node); + verifyMissingAbstractMethods(node, members); + verifyConstructors(node); + verifyNamingConvention(node.getShortCircuits(), "needs"); + verifySpecializationThrows(node); + return node; + } + + private ArrayList loadMembers(TypeElement templateType) { + return new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType)); + } + + private boolean containsSpecializations(List elements) { boolean foundSpecialization = false; for (ExecutableElement method : ElementFilter.methodsIn(elements)) { if (ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class) != null) { @@ -159,36 +179,10 @@ break; } } - if (!foundSpecialization) { - return node; - } - - if (node.hasErrors()) { - return node; // error sync point - } - - node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(elements)); - node.getSpecializations().addAll(new GenericParser(context, node).parse(elements)); - node.getCasts().addAll(new CreateCastParser(context, node).parse(elements)); - node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(elements)); - - if (node.hasErrors()) { - return node; // error sync point - } - - verifySpecializationSameLength(node); - initializeSpecializations(elements, node); - initializeShortCircuits(node); // requires specializations and polymorphic specializations - - verifyVisibilities(node); - verifyMissingAbstractMethods(node, elements); - verifyConstructors(node); - verifyNamingConvention(node.getShortCircuits(), "needs"); - verifySpecializationThrows(node); - return node; + return foundSpecialization; } - private void parseImportGuards(NodeData node, List lookupTypes, List elements) { + private void initializeImportGuards(NodeData node, List lookupTypes, List elements) { for (TypeElement lookupType : lookupTypes) { AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportGuards.class); if (importAnnotation == null) { @@ -228,7 +222,7 @@ } } - private NodeData parseNodeData(TypeElement templateType, List elements, List typeHierarchy) { + private NodeData parseNodeData(TypeElement templateType, List typeHierarchy) { AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); if (typeSystemMirror == null) { NodeData nodeData = new NodeData(context, templateType); @@ -244,6 +238,17 @@ return nodeData; } + AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); + String shortName = null; + if (nodeInfoMirror != null) { + shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); + } + boolean useNodeFactory = findFirstAnnotation(typeHierarchy, GenerateNodeFactory.class) != null; + return new NodeData(context, templateType, shortName, typeSystem, useNodeFactory); + + } + + private List parseAssumptions(List typeHierarchy) { List assumptionsList = new ArrayList<>(); for (int i = typeHierarchy.size() - 1; i >= 0; i--) { TypeElement type = typeHierarchy.get(i); @@ -258,22 +263,7 @@ } } } - AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class); - String shortName = null; - if (nodeInfoMirror != null) { - shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"); - } - - List fields = parseFields(typeHierarchy, elements); - List children = parseChildren(typeHierarchy, elements); - List executions = parseExecutions(children, elements); - boolean useNodeFactory = findFirstAnnotation(typeHierarchy, GenerateNodeFactory.class) != null; - - NodeData nodeData = new NodeData(context, templateType, shortName, typeSystem, children, executions, fields, assumptionsList, useNodeFactory); - - parsedNodes.put(ElementUtils.getQualifiedName(templateType), nodeData); - - return nodeData; + return assumptionsList; } private List parseFields(List typeHierarchy, List elements) { @@ -469,31 +459,33 @@ } } - // pre-parse specializations + List frameTypes = context.getFrameTypes(); + // pre-parse specializations to find signature size for (ExecutableElement method : methods) { AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class); if (mirror == null) { continue; } - int currentArgumentCount = 0; + int currentArgumentIndex = 0; boolean skipShortCircuit = false; - for (VariableElement var : method.getParameters()) { + outer: for (VariableElement var : method.getParameters()) { TypeMirror type = var.asType(); - if (currentArgumentCount == 0) { + if (currentArgumentIndex == 0) { // skip optionals - if (ElementUtils.typeEquals(type, context.getTruffleTypes().getFrame())) { - continue; + for (TypeMirror frameType : frameTypes) { + if (ElementUtils.typeEquals(type, frameType)) { + continue outer; + } } - // TODO skip optional fields? } - int childIndex = currentArgumentCount < children.size() ? currentArgumentCount : children.size() - 1; + 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, currentArgumentCount - childIndex))) { + if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentIndex - childIndex))) { skipShortCircuit = true; continue; } @@ -501,9 +493,9 @@ skipShortCircuit = false; } - currentArgumentCount++; + currentArgumentIndex++; } - maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount); + maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex); } List executions = new ArrayList<>(); @@ -526,25 +518,63 @@ return executions; } - private void initializeExecutableTypes(List elements, NodeData node) { - node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node).parse(elements))); - List genericExecutes = node.getThisExecution().getChild().findGenericExecutableTypes(context); + private void initializeExecutableTypes(NodeData node) { + List genericExecutes = node.findGenericExecutableTypes(context, 0); + List allExecutes = node.getExecutableTypes(); + + Set inconsistentFrameTypes = new HashSet<>(); + TypeMirror frameType = null; + Set evaluatedCounts = new HashSet<>(); + for (ExecutableTypeData execute : allExecutes) { + evaluatedCounts.add(execute.getEvaluatedCount()); + + Parameter frame = execute.getFrame(); + TypeMirror resolvedFrameType; + if (frame == null) { + resolvedFrameType = node.getTypeSystem().getVoidType().getPrimitiveType(); + } else { + resolvedFrameType = frame.getType(); + } - List overridableGenericExecutes = new ArrayList<>(); + 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)); + } + } + } + if (!inconsistentFrameTypes.isEmpty()) { + // ensure they are sorted somehow + List inconsistentFrameTypesList = new ArrayList<>(inconsistentFrameTypes); + 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); + } + node.setFrameType(frameType); + + int nonFinalCount = 0; + int voidCount = 0; for (ExecutableTypeData executableTypeData : genericExecutes) { if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) { - overridableGenericExecutes.add(executableTypeData); + nonFinalCount++; + } + if (ElementUtils.isVoid(executableTypeData.getReturnType().getType())) { + voidCount++; } } - if (overridableGenericExecutes.isEmpty()) { + // no generic executes + if (nonFinalCount == 0 && voidCount == 0) { node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " - + "signature 'public abstract {Type} executeGeneric(VirtualFrame)' and must not throw any checked exceptions."); + + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions."); } - if (overridableGenericExecutes.size() > 1) { + // multiple generic execute + if (voidCount > 1 || (nonFinalCount - voidCount) > 1) { List methodSignatures = new ArrayList<>(); - for (ExecutableTypeData type : overridableGenericExecutes) { + for (ExecutableTypeData type : genericExecutes) { methodSignatures.add(type.createReferenceName()); } node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures); @@ -571,30 +601,61 @@ } private void initializeChildren(NodeData node) { - for (NodeChildData nodeChild : node.getChildren()) { - NodeData fieldNodeData = resolveNode(ElementUtils.fromTypeMirror(nodeChild.getNodeType())); - nodeChild.setNode(fieldNodeData); - if (fieldNodeData == null) { - nodeChild.addError("Node type '%s' is invalid or not a valid Node.", ElementUtils.getQualifiedName(nodeChild.getNodeType())); + for (NodeChildData child : node.getChildren()) { + TypeMirror nodeType = child.getNodeType(); + NodeData fieldNodeData = parseChildNodeData(node, ElementUtils.fromTypeMirror(nodeType)); + + child.setNode(fieldNodeData); + if (fieldNodeData == null || fieldNodeData.hasErrors()) { + child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType)); } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) { - nodeChild.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), + child.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(), NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()), ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType())); - } else if (nodeChild.findAnyGenericExecutableType(context) == null) { - nodeChild.addError("No generic execute method found for child type %s. Generic execute methods usually have the signature 'Object executeGeneric(VirtualFrame)'.", - ElementUtils.getQualifiedName(nodeChild.getNodeType())); - } - if (fieldNodeData != null) { - List types = nodeChild.findGenericExecutableTypes(context); + } else { + List types = child.findGenericExecutableTypes(context); if (types.isEmpty()) { - AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(nodeChild.getMessageAnnotation(), "executeWith"); - nodeChild.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", nodeChild.getExecuteWith().size(), - ElementUtils.getSimpleName(nodeChild.getNodeType())); + AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith"); + child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(), + ElementUtils.getSimpleName(nodeType), ElementUtils.getUniqueIdentifiers(createAllowedChildFrameTypes(node))); } } } } + private NodeData parseChildNodeData(NodeData parentNode, TypeElement originalTemplateType) { + TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); + + if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { + // generated nodes should not get called again. + return null; + } + + if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) { + return null; + } + + List lookupTypes = collectSuperClasses(new ArrayList(), templateType); + + // Declaration order is not required for child nodes. + List members = processingEnv.getElementUtils().getAllMembers(templateType); + NodeData node = parseNodeData(templateType, lookupTypes); + + node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, createAllowedChildFrameTypes(parentNode)).parse(members))); + node.setFrameType(parentNode.getFrameType()); + return node; + } + + private List createAllowedChildFrameTypes(NodeData parentNode) { + List allowedFrameTypes = new ArrayList<>(); + for (TypeMirror frameType : context.getFrameTypes()) { + if (ElementUtils.isAssignable(parentNode.getFrameType(), frameType)) { + allowedFrameTypes.add(frameType); + } + } + return allowedFrameTypes; + } + private void initializeSpecializations(List elements, final NodeData node) { if (node.getSpecializations().isEmpty()) { return;