# HG changeset patch # User Thomas Wuerthinger # Date 1363219783 -3600 # Node ID ff91c7101ed0af8ee2b99a4982835d3f3ee556ae # Parent 53683dc2815ec57d555285538df64800644918f0# Parent 1d40b7e8823b62c3cc33b8b62a24c47d92d43593 Merge. diff -r 53683dc2815e -r ff91c7101ed0 GRAAL_AUTHORS --- a/GRAAL_AUTHORS Thu Mar 14 01:09:32 2013 +0100 +++ b/GRAAL_AUTHORS Thu Mar 14 01:09:43 2013 +0100 @@ -1,9 +1,12 @@ Gilles Duboscq (gdub) Peter Hofer +Christian Haeubl (chaeubl) +Christian Humer (chumer) +Roland Schatz +Doug Simon (dnsimon) +Lukas Stadler (lstadler) Alexander Stipsits Katrin Strassl -Christian Humer (chumer) Christian Wimmer (cwimmer) -Doug Simon (dnsimon) -Lukas Stadler (lstadler) +Andreas Woess (aw) Thomas Wuerthinger (thomaswue) diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Mar 14 01:09:43 2013 +0100 @@ -221,7 +221,7 @@ return method.invoke(receiver, args); } - static class Result { + protected static class Result { final Object returnValue; final Throwable exception; @@ -263,7 +263,10 @@ before(); Object[] executeArgs = argsWithReceiver(receiver, args); - InstalledCode compiledMethod = getCode(runtime.lookupJavaMethod(method), parse(method)); + ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); + checkArgs(javaMethod, executeArgs); + + InstalledCode compiledMethod = getCode(javaMethod, parse(method)); try { return new Result(compiledMethod.executeVarargs(executeArgs), null); } catch (Throwable e) { @@ -273,6 +276,25 @@ } } + protected void checkArgs(ResolvedJavaMethod method, Object[] args) { + JavaType[] sig = MetaUtil.signatureToTypes(method); + Assert.assertEquals(sig.length, args.length); + for (int i = 0; i < args.length; i++) { + JavaType javaType = sig[i]; + Kind kind = javaType.getKind(); + Object arg = args[i]; + if (kind == Kind.Object) { + if (arg != null && javaType instanceof ResolvedJavaType) { + ResolvedJavaType resolvedJavaType = (ResolvedJavaType) javaType; + Assert.assertTrue(resolvedJavaType + " from " + runtime.lookupJavaType(arg.getClass()), resolvedJavaType.isAssignableFrom(runtime.lookupJavaType(arg.getClass()))); + } + } else { + Assert.assertNotNull(arg); + Assert.assertEquals(kind.toBoxedJavaClass(), arg.getClass()); + } + } + } + /** * Prepends a non-null receiver argument to a given list or args. * @@ -296,16 +318,28 @@ Method method = getMethod(name); Object receiver = Modifier.isStatic(method.getModifiers()) ? null : this; + test(method, receiver, args); + } + + protected void test(Method method, Object receiver, Object... args) { Result expect = executeExpected(method, receiver, args); if (runtime == null) { return; } + test(method, expect, receiver, args); + } + + protected void test(Method method, Result expect, Object receiver, Object... args) { Result actual = executeActual(method, receiver, args); if (expect.exception != null) { Assert.assertTrue("expected " + expect.exception, actual.exception != null); Assert.assertEquals(expect.exception.getClass(), actual.exception.getClass()); } else { + if (actual.exception != null) { + actual.exception.printStackTrace(); + Assert.fail("expected " + expect.returnValue + " but got an exception"); + } assertEquals(expect.returnValue, actual.returnValue); } } @@ -360,8 +394,7 @@ GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); editPhasePlan(method, graph, phasePlan); - CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, - new SpeculationLog()); + CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog()); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Thu Mar 14 01:09:43 2013 +0100 @@ -282,7 +282,6 @@ * @return the created interval */ Interval createInterval(Value operand) { - assert isProcessed(operand); assert isLegal(operand); int operandNumber = operandNumber(operand); Interval interval = new Interval(operand, operandNumber); @@ -1951,12 +1950,6 @@ throw new GraalInternalError(""); } - if (!isProcessed(i1.location())) { - TTY.println("Can not have an Interval for an ignored register " + i1.location()); - TTY.println(i1.logString(this)); - throw new GraalInternalError(""); - } - if (i1.first() == Range.EndMarker) { TTY.println("Interval %d has no Range", i1.operandNumber); TTY.println(i1.logString(this)); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Thu Mar 14 01:09:43 2013 +0100 @@ -33,15 +33,12 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.phases.*; // @formatter:off public class AMD64HotSpotRegisterConfig implements RegisterConfig { - private final Register[] allocatable = { - rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15, */ - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; + private final Register[] allocatable = initAllocatable(); private final EnumMap categorized = Register.categorize(allocatable); @@ -68,6 +65,34 @@ private final CalleeSaveLayout csl; + private static Register findRegister(String name, Register[] all) { + for (Register reg : all) { + if (reg.name.equals(name)) { + return reg; + } + } + throw new IllegalArgumentException("register " + name + " is not allocatable"); + } + + private static Register[] initAllocatable() { + Register[] allocatable = { + rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15, */ + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + + if (GraalOptions.RegisterPressure != null) { + String[] names = GraalOptions.RegisterPressure.split(","); + Register[] regs = new Register[names.length]; + for (int i = 0; i < names.length; i++) { + regs[i] = findRegister(names[i], allocatable); + } + return regs; + } + + return allocatable; + } + public AMD64HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { if (config.windowsOs) { javaGeneralParameterRegisters = new Register[] {rdx, r8, r9, rdi, rsi, rcx}; diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Thu Mar 14 01:09:43 2013 +0100 @@ -41,11 +41,6 @@ public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class); - /** - * Vtable stubs expect the metaspace Method in RBX. - */ - public static final Register METHOD = AMD64.rbx; - @Use({REG}) protected AllocatableValue exception; @Temp private RegisterValue framePointer; diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Mar 14 01:09:43 2013 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.java; +import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import static java.lang.reflect.Modifier.*; @@ -52,7 +54,7 @@ /** * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. */ -public final class GraphBuilderPhase extends Phase { +public class GraphBuilderPhase extends Phase { public static final class RuntimeCalls { @@ -72,7 +74,7 @@ */ public static final int TRACELEVEL_STATE = 2; - private StructuredGraph currentGraph; + protected StructuredGraph currentGraph; private final MetaAccessProvider runtime; private ConstantPool constantPool; @@ -82,7 +84,7 @@ private BytecodeStream stream; // the bytecode stream - private FrameStateBuilder frameState; // the current execution state + protected FrameStateBuilder frameState; // the current execution state private Block currentBlock; private ValueNode methodSynchronizedObject; @@ -279,7 +281,7 @@ * @param type the unresolved type of the constant */ protected void handleUnresolvedLoadConstant(JavaType type) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); } @@ -288,7 +290,7 @@ * @param object the object value whose type is being checked against {@code type} */ protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile))); + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile))); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -298,7 +300,7 @@ */ protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); + DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); append(ifNode); lastInstr = successor; @@ -309,7 +311,7 @@ * @param type the type being instantiated */ protected void handleUnresolvedNewInstance(JavaType type) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -318,7 +320,7 @@ * @param length the length of the array */ protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -327,7 +329,7 @@ * @param dims the dimensions for the multi-array */ protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -337,7 +339,7 @@ */ protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { Kind kind = field.getKind(); - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); } @@ -347,7 +349,7 @@ * @param receiver the object containing the field or {@code null} if {@code field} is static */ protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); } /** @@ -355,12 +357,12 @@ * @param type */ protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); } protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { boolean withReceiver = invokeKind != InvokeKind.Static; - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + append(currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved))); frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver)); Kind kind = javaMethod.getSignature().getReturnKind(); if (kind != Kind.Void) { @@ -733,8 +735,7 @@ private void genThrow() { ValueNode exception = frameState.apop(); - FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, - true)); + FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); append(node); append(handleException(exception, bci())); } @@ -826,7 +827,7 @@ /** * Gets the kind of array elements for the array type code that appears in a * {@link Bytecodes#NEWARRAY} bytecode. - * + * * @param code the array type code * @return the kind from the array type code */ @@ -1109,7 +1110,7 @@ private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) { Kind resultType = targetMethod.getSignature().getReturnKind(); if (GraalOptions.DeoptALot) { - DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint)); + DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); append(deoptimize); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); return; @@ -1190,8 +1191,7 @@ ValueNode local = frameState.loadLocal(localIndex); JsrScope scope = currentBlock.jsrScope; int retAddress = scope.nextReturnAddress(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), DeoptimizationReason.JavaSubroutineMismatch, - DeoptimizationAction.InvalidateReprofile))); + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile))); if (!successor.jsrScope.equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); } @@ -1224,7 +1224,7 @@ /** * Helper function that sums up the probabilities of all keys that lead to a specific successor. - * + * * @return an array of size successorCount with the accumulated probability for each successor. */ private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) { @@ -1391,7 +1391,7 @@ private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { assert probability >= 0 && probability <= 1.01 : probability; if (isNeverExecutedCode(probability)) { - return currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode)); + return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); } else { assert block != null; return createTarget(block, stateAfter); @@ -1553,7 +1553,10 @@ private void createUnwind() { assert frameState.stackSize() == 1 : frameState; synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI); - UnwindNode unwindNode = currentGraph.add(new UnwindNode(frameState.apop())); + ValueNode exception = frameState.apop(); + FixedGuardNode guard = currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); + append(guard); + UnwindNode unwindNode = currentGraph.add(new UnwindNode(exception)); append(unwindNode); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Thu Mar 14 01:09:43 2013 +0100 @@ -48,6 +48,10 @@ */ Object[] argsToBind; + public JTTTest() { + Assert.assertNotNull(runtime); + } + @Override protected StructuredGraph parse(Method m) { StructuredGraph graph = super.parse(m); @@ -89,10 +93,14 @@ } protected void runTest(String name, Object... args) { - // System.out.println(getClass().getSimpleName() + "." + name); - super.test(name, args); + Method method = getMethod(name); + Object receiver = Modifier.isStatic(method.getModifiers()) ? null : this; + + Result expect = executeExpected(method, receiver, args); + + test(method, expect, receiver, args); this.argsToBind = args; - super.test(name, args); + test(method, expect, receiver, args); this.argsToBind = null; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized05.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized05.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Except_Synchronized05.java Thu Mar 14 01:09:43 2013 +0100 @@ -29,29 +29,11 @@ public class Except_Synchronized05 extends JTTTest { - Object field; - - public static int test(int arg) { - Except_Synchronized05 obj = new Except_Synchronized05(); - int a = obj.bar(arg) != null ? 1 : 0; - int b = obj.baz(arg) != null ? 1 : 0; - return a + b; - } + static class Foo { - public synchronized Object bar(int arg) { - try { - String f = foo1(arg); - if (f == null) { - field = new Object(); - } - } catch (NullPointerException e) { - // do nothing - } - return field; - } + Object field; - public Object baz(int arg) { - synchronized (this) { + public synchronized Object bar(int arg) { try { String f = foo1(arg); if (f == null) { @@ -62,14 +44,36 @@ } return field; } + + public Object baz(int arg) { + synchronized (this) { + try { + String f = foo1(arg); + if (f == null) { + field = new Object(); + } + } catch (NullPointerException e) { + // do nothing + } + return field; + } + } + + @SuppressWarnings("static-method") + private String foo1(int arg) { + if (arg == 0) { + throw null; + } + return null; + } + } - @SuppressWarnings("static-method") - private String foo1(int arg) { - if (arg == 0) { - throw null; - } - return null; + public static int test(int arg) { + Foo obj = new Foo(); + int a = obj.bar(arg) != null ? 1 : 0; + int b = obj.baz(arg) != null ? 1 : 0; + return a + b; } @Test diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Thu Mar 14 01:09:43 2013 +0100 @@ -59,12 +59,19 @@ BeginNode trueSuccessor; BeginNode falseSuccessor; DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason())); + BeginNode deoptBranch = BeginNode.begin(deopt); + Loop loop = block.getLoop(); + while (loop != null) { + LoopExitNode exit = graph.add(new LoopExitNode(loop.loopBegin())); + graph.addBeforeFixed(deopt, exit); + loop = loop.parent; + } if (guard.negated()) { - trueSuccessor = BeginNode.begin(deopt); + trueSuccessor = deoptBranch; falseSuccessor = fastPath; } else { trueSuccessor = fastPath; - falseSuccessor = BeginNode.begin(deopt); + falseSuccessor = deoptBranch; } IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0)); guard.replaceAndDelete(fastPath); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Thu Mar 14 01:09:43 2013 +0100 @@ -1000,6 +1000,17 @@ return count; } + static MonitorExitNode findPrecedingMonitorExit(UnwindNode unwind) { + Node pred = unwind.predecessor(); + while (pred != null) { + if (pred instanceof MonitorExitNode) { + return (MonitorExitNode) pred; + } + pred = pred.predecessor(); + } + return null; + } + /** * Performs an actual inlining, thereby replacing the given invoke with the given inlineGraph. * @@ -1070,13 +1081,13 @@ } else { if (unwindNode != null) { UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); + MonitorExitNode monitorExit = findPrecedingMonitorExit(unwindDuplicate); DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode)); // move the deopt upwards if there is a monitor exit that tries to use the // "after exception" frame state // (because there is no "after exception" frame state!) - if (deoptimizeNode.predecessor() instanceof MonitorExitNode) { - MonitorExitNode monitorExit = (MonitorExitNode) deoptimizeNode.predecessor(); + if (monitorExit != null) { if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_EXCEPTION_BCI) { FrameState monitorFrameState = monitorExit.stateAfter(); graph.removeFixed(monitorExit); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Mar 14 01:09:43 2013 +0100 @@ -148,6 +148,9 @@ public static boolean ExitVMOnBailout = ____; public static boolean ExitVMOnException = true; + // Register allocator debugging + public static String RegisterPressure = null; + // Code generator settings public static boolean ConditionalElimination = true; public static boolean CullFrameStates = ____; diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Thu Mar 14 01:09:43 2013 +0100 @@ -82,16 +82,22 @@ if (sdf == null) { sdf = new SimpleDateFormat("YYYY-MM-dd-HHmm"); } - String fileName = "Graphs-" + Thread.currentThread().getName() + "-" + sdf.format(new Date()) + ext; + String prefix = "Graphs-" + Thread.currentThread().getName() + "-" + sdf.format(new Date()); + String num = ""; + File file; + int i = 0; + while ((file = new File(prefix + num + ext)).exists()) { + num = "-" + Integer.toString(++i); + } try { if (GraalOptions.PrintBinaryGraphs) { - printer = new BinaryGraphPrinter(FileChannel.open(new File(fileName).toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)); + printer = new BinaryGraphPrinter(FileChannel.open(file.toPath(), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)); } else { - printer = new IdealGraphPrinter(new FileOutputStream(fileName)); + printer = new IdealGraphPrinter(new FileOutputStream(file)); } - TTY.println("Dumping IGV graphs to %s", fileName); + TTY.println("Dumping IGV graphs to %s", file.getName()); } catch (IOException e) { - TTY.println("Failed to open %s to dump IGV graphs : %s", fileName, e); + TTY.println("Failed to open %s to dump IGV graphs : %s", file.getName(), e); failuresCount++; printer = null; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryOperationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryOperationTest.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,76 @@ +/* + * 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.api.codegen.test; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; + +public class BinaryOperationTest { + + static int convertInt(Object value) { + if (value instanceof Number) { + return ((Number) value).intValue(); + } else if (value instanceof String) { + return Integer.parseInt((String) value); + } + throw new RuntimeException("Invalid datatype"); + } + + @NodeClass(BinaryNode.class) + abstract static class BinaryNode extends ValueNode { + + @Child protected ValueNode leftNode; + @Child protected ValueNode rightNode; + + public BinaryNode(ValueNode left, ValueNode right) { + this.leftNode = left; + this.rightNode = right; + } + + public BinaryNode(BinaryNode prev) { + this(prev.leftNode, prev.rightNode); + } + + @Specialization + int add(int left, int right) { + return left + right; + } + + @Generic + int add(Object left, Object right) { + return convertInt(left) + convertInt(right); + } + + @Specialization + int sub(int left, int right) { + return left + right; + } + + @Generic + int sub(Object left, Object right) { + return convertInt(left) + convertInt(right); + } + + } + +} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/RuntimeStringTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/RuntimeStringTest.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,159 @@ +/* + * 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.api.codegen.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; +import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; + +public class RuntimeStringTest { + + @Test + public void testSubstr() { + assertExecute(new RuntimeString("es"), "substr", new RuntimeString("test"), 1, 3); + } + + @Test + public void testConcat() { + assertExecute(new RuntimeString("concatconcat"), "concat", new RuntimeString("concat"), new RuntimeString("concat")); + } + + @Test(expected = ArrayIndexOutOfBoundsException.class) + public void testConcatFail() { + assertExecute(new RuntimeString("concatconcat"), "concat", new RuntimeString("concat")); + } + + @Test + public void testFindMethodByMethodName() { + // TODO + } + + private static void assertExecute(Object expectedResult, String name, Object... argumentsArray) { + ArgNode[] args = new ArgNode[argumentsArray.length]; + for (int i = 0; i < args.length; i++) { + args[i] = new ArgNode(argumentsArray, i); + } + + BuiltinNode node = null; + for (NodeFactory nodeFactory : RuntimeStringTestFactory.getFactories()) { + GeneratedBy generated = nodeFactory.getClass().getAnnotation(GeneratedBy.class); + Assert.assertNotNull(generated); + Assert.assertNotSame("", generated.methodName()); + if (generated.methodName().equals(name)) { + node = nodeFactory.createNode((Object) args); + break; + } + } + Assert.assertNotNull("Node not found", node); + CallTarget target = Truffle.getRuntime().createCallTarget(new TestRootNode(node)); + Assert.assertEquals(expectedResult, target.call()); + } + + static class ArgNode extends ValueNode { + + final Object[] arguments; + final int index; + + ArgNode(Object[] args, int index) { + this.arguments = args; + this.index = index; + } + + @Override + Object execute() { + return arguments[index]; + } + + } + + abstract static class BuiltinNode extends ValueNode { + + @Children ArgNode[] parameters; + + BuiltinNode(ArgNode[] parameters) { + this.parameters = adoptChildren(parameters); + } + + BuiltinNode(BuiltinNode prev) { + this(prev.parameters); + } + + } + + @NodeClass(BuiltinNode.class) + static class RuntimeString { + + private final String internal; + + public RuntimeString(String internal) { + this.internal = internal; + } + + @Specialization + static RuntimeString concat(RuntimeString s1, RuntimeString s2) { + return new RuntimeString(s1.internal + s2.internal); + } + + @Specialization + RuntimeString substr(int beginIndex, int endIndex) { + return new RuntimeString(internal.substring(beginIndex, endIndex)); + } + + @Generic + RuntimeString substr(Object beginIndex, Object endIndex) { + return substr(convertInt(beginIndex), convertInt(endIndex)); + } + + static int convertInt(Object value) { + if (value instanceof Number) { + return ((Number) value).intValue(); + } else if (value instanceof String) { + return Integer.parseInt((String) value); + } + throw new RuntimeException("Invalid datatype"); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof RuntimeString) { + return internal.equals(((RuntimeString) obj).internal); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return internal.hashCode(); + } + + @Override + public String toString() { + return internal; + } + + } + +} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,71 @@ +/* + * 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.api.codegen.test; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.RuntimeStringTest.RuntimeString; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class TypeSystemTest { + + @TypeSystem({int.class, RuntimeString.class}) + static class SimpleTypes { + } + + @TypeSystemReference(SimpleTypes.class) + abstract static class ValueNode extends Node { + + int executeInt() throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectInteger(execute()); + } + + RuntimeString executeString() { + return new RuntimeString(execute().toString()); + } + + @SuppressWarnings("static-method") + final long executeSpecial() { + return 42L; + } + + abstract Object execute(); + + } + + @TypeSystemReference(SimpleTypes.class) + static class TestRootNode extends RootNode { + + @Child private ValueNode node; + + public TestRootNode(ValueNode node) { + this.node = adoptChild(node); + } + + @Override + public Object execute(VirtualFrame frame) { + return node.execute(); + } + } + +} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,50 @@ +/* + * 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. + */ +/** + *

This package contains basic tests of the Truffle-Source-Code-Generation (short Codegen) API and serves at the same + * time as an introduction to the Codegen API for language implementors. Every test gives an example on how to use the construct explained in the class description.

+ * + *

+ * This API relies heavily on the concepts described in com.oracle.truffle.api.test. We assume that the + * reader is already familiarized with those concepts. + *

+ * + *

+ * TODO general description + *

+ * + *

+ * This introduction to Codegen contains items in the following recommended order: + * + * Prerequisites: + * + * + *

    + *
  • What do I need to get started? {@link com.oracle.truffle.api.codegen.test.TypeSystemTest}
  • + *
  • How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.codegen.test.RuntimeStringTest}
  • + *
+ *

+ * + */ +package com.oracle.truffle.api.codegen.test; + diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java Thu Mar 14 01:09:43 2013 +0100 @@ -25,12 +25,14 @@ import java.lang.annotation.*; /** - * Marks a type to be generated by another class. + * Marks a type to be generated by another class or a method. */ -@Retention(RetentionPolicy.CLASS) +@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface GeneratedBy { Class value(); + String methodName() default ""; + } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java Thu Mar 14 01:09:32 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +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.api.codegen; - -import java.lang.annotation.*; - -/** - * - * - * @see SpecializationGuard - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface GuardCheck { - -} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,35 @@ +/* + * 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.api.codegen; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.nodes.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface NodeClass { + + Class value(); + +} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeFactory.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeFactory.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeFactory.java Thu Mar 14 01:09:43 2013 +0100 @@ -24,6 +24,8 @@ import java.util.*; +import com.oracle.truffle.api.nodes.*; + /** * Enables the dynamic creation of generated nodes. It provides an convenient way to instantiate * generated node classes without using reflection. @@ -63,4 +65,10 @@ */ List>> getNodeSignatures(); + /** + * Returns a list of children that will be executed by the created node. This is useful for base + * nodes that can execute a variable amount of nodes. + */ + List> getExecutionSignature(); + } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeId.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeId.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,33 @@ +/* + * 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.api.codegen; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface NodeId { + + String value(); + +} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java Thu Mar 14 01:09:43 2013 +0100 @@ -32,8 +32,8 @@ int order() default DEFAULT_ORDER; - SpecializationThrows[] exceptions() default {}; + Class[] rewriteOn() default {}; - SpecializationGuard[] guards() default {}; + String[] guards() default {}; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java Thu Mar 14 01:09:32 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +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.api.codegen; - -import java.lang.annotation.*; - -/** - * Specifies the use of a guard for a specialization. - */ -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface SpecializationGuard { - - /** - * Specifies the name of the guard method annotated by {@link GuardCheck} specified as method in - * the {@link TypeSystem} class. - */ - String methodName(); - - /** - * Determines if a guard check is invoked on specialization. Defaults to true. - */ - boolean onSpecialization() default true; - - /** - * Determines if a guard check is invoked on execution. Defaults to true. - */ - boolean onExecution() default true; - -} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java Thu Mar 14 01:09:32 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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.api.codegen; - -import java.lang.annotation.*; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD}) -public @interface SpecializationThrows { - - Class javaClass(); - - String transitionTo(); -} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java Thu Mar 14 01:09:43 2013 +0100 @@ -28,8 +28,8 @@ *

* Annotates a type system class that represents type information for a node. Generates code for * converting and managing types. Methods contained in the type system may be annotated with - * {@link TypeCast}, {@link TypeCheck} or {@link GuardCheck}. These methods alter the default - * behavior of the type system. + * {@link TypeCast} or {@link TypeCheck}. These methods alter the default behavior of the type + * system. *

* * @@ -62,7 +62,6 @@ * * @see TypeCast * @see TypeCheck - * @see GuardCheck */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.TYPE}) diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Thu Mar 14 01:09:43 2013 +0100 @@ -38,7 +38,7 @@ * should be speculated on. When the speculation fails and the child node cannot return the * appropriate type of value, it can use an {@link UnexpectedResultException} to still pass the * result to the caller. In such a case, the caller must rewrite itself to a more general version in - * oder to avoid future failures of this kind. + * order to avoid future failures of this kind. *

*/ public class ReturnTypeSpecializationTest { diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -58,12 +58,22 @@ if (!context.getTruffleTypes().verify(context, element, mirror)) { return null; } - return parse(element, mirror); + M model = parse(element, mirror); + if (model == null) { + return null; + } + + model.emitMessages((TypeElement) element, log); + return filterErrorElements(model); } finally { this.roundEnv = null; } } + protected M filterErrorElements(M model) { + return model.hasErrors() ? null : model; + } + protected abstract M parse(Element element, AnnotationMirror mirror); public abstract Class getAnnotationType(); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Thu Mar 14 01:09:43 2013 +0100 @@ -41,30 +41,6 @@ this.processingEnv = env; } - public void warning(Element element, String format, Object... args) { - message(Kind.WARNING, element, null, null, format, args); - } - - public void warning(Element element, AnnotationMirror mirror, String format, Object... args) { - message(Kind.WARNING, element, mirror, null, format, args); - } - - public void error(Element element, String format, Object... args) { - message(Kind.ERROR, element, null, null, format, args); - } - - public void error(String format, Object... args) { - message(Kind.ERROR, null, null, null, format, args); - } - - public void error(Element element, AnnotationMirror mirror, String format, Object... args) { - message(Kind.ERROR, element, mirror, null, format, args); - } - - public void error(Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { - message(Kind.ERROR, element, mirror, value, format, args); - } - public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { AnnotationMirror usedMirror = mirror; Element usedElement = element; diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java Thu Mar 14 01:09:43 2013 +0100 @@ -28,6 +28,7 @@ import javax.annotation.processing.*; import javax.lang.model.*; import javax.lang.model.element.*; +import javax.tools.Diagnostic.*; import com.oracle.truffle.codegen.processor.ProcessorContext.ProcessCallback; import com.oracle.truffle.codegen.processor.node.*; @@ -95,7 +96,7 @@ private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) { String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e; - generator.getContext().getLog().error(e, message + ": " + Utils.printException(t)); + generator.getContext().getLog().message(Kind.ERROR, e, null, null, message + ": " + Utils.printException(t)); } @SuppressWarnings("unchecked") diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Thu Mar 14 01:09:43 2013 +0100 @@ -26,6 +26,7 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; +import javax.tools.Diagnostic.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.intrinsics.*; @@ -66,7 +67,7 @@ } for (String error : errors) { - context.getLog().error(element, mirror, error); + context.getLog().message(Kind.ERROR, element, mirror, null, error); } return false; diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Thu Mar 14 01:09:43 2013 +0100 @@ -55,9 +55,17 @@ return boxedType; } + public static List asTypeMirrors(List elements) { + List types = new ArrayList<>(elements.size()); + for (Element element : elements) { + types.add(element.asType()); + } + return types; + } + public static List collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, Class annotationClass) { - List result = Utils.getAnnotationValueList(markerAnnotation, elementName); + List result = Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName); AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); if (explicit != null) { result.add(explicit); @@ -167,6 +175,46 @@ return new LinkedHashSet<>(Arrays.asList(modifier)); } + public static String getTypeId(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "Boolean"; + case BYTE: + return "Byte"; + case CHAR: + return "Char"; + case DOUBLE: + return "Double"; + case FLOAT: + return "Float"; + case SHORT: + return "Short"; + case INT: + return "Int"; + case LONG: + return "Long"; + case DECLARED: + return ((DeclaredType) mirror).asElement().getSimpleName().toString(); + case ARRAY: + return getTypeId(((ArrayType) mirror).getComponentType()) + "Array"; + case VOID: + return "Void"; + case WILDCARD: + StringBuilder b = new StringBuilder(); + WildcardType type = (WildcardType) mirror; + if (type.getExtendsBound() != null) { + b.append("Extends").append(getTypeId(type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("Super").append(getTypeId(type.getExtendsBound())); + } + return b.toString(); + case TYPEVAR: + return "Any"; + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + public static String getSimpleName(TypeElement element) { return getSimpleName(element.asType()); } @@ -428,29 +476,32 @@ } @SuppressWarnings("unchecked") - public static List getAnnotationValueList(AnnotationMirror mirror, String name) { + public static List getAnnotationValueList(Class expectedListType, AnnotationMirror mirror, String name) { + List values = getAnnotationValue(List.class, mirror, name); List result = new ArrayList<>(); - List values = (List) getAnnotationValue(mirror, name).getValue(); + for (AnnotationValue value : values) { - result.add((T) value.getValue()); + result.add(resolveAnnotationValue(expectedListType, value)); } return result; } - public static TypeMirror getAnnotationValueType(AnnotationMirror mirror, String name) { - return (TypeMirror) getAnnotationValue(mirror, name).getValue(); + public static T getAnnotationValue(Class expectedType, AnnotationMirror mirror, String name) { + return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name)); } - public static TypeMirror getAnnotationValueTypeMirror(AnnotationMirror mirror, String name) { - return (TypeMirror) getAnnotationValue(mirror, name).getValue(); - } - - public static String getAnnotationValueString(AnnotationMirror mirror, String name) { - return (String) getAnnotationValue(mirror, name).getValue(); - } - - public static int getAnnotationValueInt(AnnotationMirror mirror, String name) { - return (int) getAnnotationValue(mirror, name).getValue(); + @SuppressWarnings({"unchecked"}) + private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { + Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); + if (unboxedValue != null) { + if (expectedType == TypeMirror.class && unboxedValue instanceof String) { + return null; + } + if (!expectedType.isAssignableFrom(unboxedValue.getClass())) { + throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName()); + } + } + return (T) unboxedValue; } public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { @@ -470,9 +521,79 @@ if (value == null) { value = valueMethod.getDefaultValue(); } + return value; } + private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7 { + + @Override + public Object visitBoolean(boolean b, Void p) { + return Boolean.valueOf(b); + } + + @Override + public Object visitByte(byte b, Void p) { + return Byte.valueOf(b); + } + + @Override + public Object visitChar(char c, Void p) { + return c; + } + + @Override + public Object visitDouble(double d, Void p) { + return d; + } + + @Override + public Object visitFloat(float f, Void p) { + return f; + } + + @Override + public Object visitInt(int i, Void p) { + return i; + } + + @Override + public Object visitLong(long i, Void p) { + return i; + } + + @Override + public Object visitShort(short s, Void p) { + return s; + } + + @Override + public Object visitString(String s, Void p) { + return s; + } + + @Override + public Object visitType(TypeMirror t, Void p) { + return t; + } + + @Override + public Object visitEnumConstant(VariableElement c, Void p) { + return c.getConstantValue(); + } + + @Override + public Object visitAnnotation(AnnotationMirror a, Void p) { + return a; + } + + @Override + public Object visitArray(List vals, Void p) { + return vals; + } + + } + public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) { return (Boolean) getAnnotationValue(mirror, name).getValue(); } @@ -591,6 +712,14 @@ } String qualified1 = getQualifiedName(type1); String qualified2 = getQualifiedName(type2); + + if (type1.getKind() == TypeKind.ARRAY || type2.getKind() == TypeKind.ARRAY) { + if (type1.getKind() == TypeKind.ARRAY && type2.getKind() == TypeKind.ARRAY) { + return typeEquals(((ArrayType) type1).getComponentType(), ((ArrayType) type2).getComponentType()); + } else { + return false; + } + } return qualified1.equals(qualified2); } @@ -619,7 +748,7 @@ return true; } - // search for any supertypes + // search for any super types TypeElement exceptionTypeElement = fromTypeMirror(exceptionType); List superTypes = getSuperTypes(exceptionTypeElement); for (TypeElement typeElement : superTypes) { @@ -648,7 +777,7 @@ Set typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); String typeName = getQualifiedName(type); if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) { - throw new IllegalArgumentException("Given does not extend Throwable."); + throw new IllegalArgumentException("Given type does not extend Throwable."); } return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName()); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Thu Mar 14 01:09:43 2013 +0100 @@ -204,7 +204,7 @@ return v.visitExecutable(this, p); } - public static CodeExecutableElement clone(ProcessingEnvironment env, ExecutableElement method) { + public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) { CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString()); for (TypeMirror thrownType : method.getThrownTypes()) { copy.addThrownType(thrownType); @@ -220,7 +220,6 @@ for (Element element : method.getEnclosedElements()) { copy.add(element); } - copy.setBody(Utils.getMethodBody(env, method)); copy.getModifiers().addAll(method.getModifiers()); return copy; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Thu Mar 14 01:09:43 2013 +0100 @@ -495,7 +495,7 @@ } public CodeTreeBuilder create() { - return new CodeTreeBuilder(null); + return new CodeTreeBuilder(this); } public CodeTreeBuilder type(TypeMirror type) { diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Thu Mar 14 01:09:43 2013 +0100 @@ -123,6 +123,14 @@ writeClassImpl(e); } + private String useImport(TypeMirror type) { + if (imports != null) { + return imports.useImport(type); + } else { + return Utils.getSimpleName(type); + } + } + private void writeClassImpl(CodeTypeElement e) { for (AnnotationMirror annotation : e.getAnnotationMirrors()) { visitAnnotation(annotation); @@ -137,12 +145,12 @@ } write(e.getSimpleName()); if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { - write(" extends ").write(typeSimpleName(e.getSuperclass())); + write(" extends ").write(useImport(e.getSuperclass())); } if (e.getImplements().size() > 0) { write(" implements "); for (int i = 0; i < e.getImplements().size(); i++) { - write(typeSimpleName(e.getImplements().get(i))); + write(useImport(e.getImplements().get(i))); if (i < e.getImplements().size() - 1) { write(", "); } @@ -267,7 +275,7 @@ } } else { writeModifiers(f.getModifiers()); - write(typeSimpleName(f.asType())); + write(useImport(f.asType())); if (f.getEnclosingElement().getKind() == ElementKind.METHOD) { ExecutableElement method = (ExecutableElement) f.getEnclosingElement(); @@ -287,7 +295,7 @@ } public void visitAnnotation(AnnotationMirror e) { - write("@").write(typeSimpleName(e.getAnnotationType())); + write("@").write(useImport(e.getAnnotationType())); if (!e.getElementValues().isEmpty()) { write("("); @@ -395,14 +403,14 @@ @Override public Void visitType(TypeMirror t, Void p) { - write(typeSimpleName(t)); + write(useImport(t)); write(".class"); return null; } @Override public Void visitEnumConstant(VariableElement c, Void p) { - write(typeSimpleName(c.asType())); + write(useImport(c.asType())); write("."); write(c.getSimpleName().toString()); return null; @@ -458,7 +466,7 @@ writeModifiers(e.getModifiers()); if (e.getReturnType() != null) { - write(typeSimpleName(e.getReturnType())); + write(useImport(e.getReturnType())); write(" "); } write(e.getSimpleName()); @@ -477,7 +485,7 @@ if (throwables.size() > 0) { write(" throws "); for (int i = 0; i < throwables.size(); i++) { - write(typeSimpleName(throwables.get(i))); + write(useImport(throwables.get(i))); if (i < throwables.size() - 1) { write(", "); } @@ -554,7 +562,7 @@ } break; case TYPE: - write(imports.useImport(e.getType())); + write(useImport(e.getType())); break; default: assert false; @@ -562,10 +570,6 @@ } } - private static String typeSimpleName(TypeMirror type) { - return Utils.getSimpleName(type); - } - protected void writeHeader() { // default implementation does nothing } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Thu Mar 14 01:09:43 2013 +0100 @@ -359,6 +359,100 @@ public void visitAnnotation(AnnotationMirror e) { addImport(e.getAnnotationType()); + if (!e.getElementValues().isEmpty()) { + Map values = e.getElementValues(); + Set methodsSet = values.keySet(); + List methodsList = new ArrayList<>(); + for (ExecutableElement method : methodsSet) { + if (values.get(method) == null) { + continue; + } + methodsList.add(method); + } + + for (int i = 0; i < methodsList.size(); i++) { + AnnotationValue value = values.get(methodsList.get(i)); + visitAnnotationValue(value); + } + } + } + + public void visitAnnotationValue(AnnotationValue e) { + e.accept(new AnnotationValueReferenceVisitor(), null); + } + + private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { + + @Override + public Void visitBoolean(boolean b, Void p) { + return null; + } + + @Override + public Void visitByte(byte b, Void p) { + return null; + } + + @Override + public Void visitChar(char c, Void p) { + return null; + } + + @Override + public Void visitDouble(double d, Void p) { + return null; + } + + @Override + public Void visitFloat(float f, Void p) { + return null; + } + + @Override + public Void visitInt(int i, Void p) { + return null; + } + + @Override + public Void visitLong(long i, Void p) { + return null; + } + + @Override + public Void visitShort(short s, Void p) { + return null; + } + + @Override + public Void visitString(String s, Void p) { + return null; + } + + @Override + public Void visitType(TypeMirror t, Void p) { + addImport(t); + return null; + } + + @Override + public Void visitEnumConstant(VariableElement c, Void p) { + addImport(c.asType()); + return null; + } + + @Override + public Void visitAnnotation(AnnotationMirror a, Void p) { + ReferenceCollector.this.visitAnnotation(a); + return null; + } + + @Override + public Void visitArray(List vals, Void p) { + for (int i = 0; i < vals.size(); i++) { + ReferenceCollector.this.visitAnnotationValue(vals.get(i)); + } + return null; + } } @Override diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java Thu Mar 14 01:09:43 2013 +0100 @@ -39,6 +39,9 @@ } protected static Object field(Object o, String fieldName) throws Exception { + if (o == null) { + return null; + } Field field = o.getClass().getField(fieldName); field.setAccessible(true); return field.get(o); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -31,6 +31,7 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.api.*; import com.oracle.truffle.codegen.processor.api.element.*; +import com.oracle.truffle.codegen.processor.template.*; public class ExtensionParser { @@ -45,25 +46,25 @@ this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory); } - public List parseAll(TypeElement typeElement, List elements) { + public List parseAll(Template template, List elements) { List generatedMethods = new ArrayList<>(); - parseElement(generatedMethods, typeElement); + parseElement(template, generatedMethods, template.getTemplateType()); List methods = ElementFilter.methodsIn(elements); for (ExecutableElement method : methods) { for (VariableElement var : method.getParameters()) { - parseElement(generatedMethods, var); + parseElement(template, generatedMethods, var); } - parseElement(generatedMethods, method); + parseElement(template, generatedMethods, method); } return generatedMethods; } - private void parseElement(List elements, Element element) { + private void parseElement(Template template, List elements, Element element) { List mirrors = element.getAnnotationMirrors(); for (AnnotationMirror mirror : mirrors) { - ExtensionProcessor processor = findProcessor(element, mirror); + ExtensionProcessor processor = findProcessor(template, mirror); if (processor != null) { try { factory.generatorAnnotationMirror = mirror; @@ -71,7 +72,7 @@ processor.process(extensionContext, mirror, element); elements.addAll(extensionContext.returnElements()); } catch (Throwable e) { - context.getLog().error(element, mirror, "Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e)); + template.addError("Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e)); } finally { factory.generatorAnnotationMirror = null; factory.generatorElement = null; @@ -80,7 +81,7 @@ } } - private ExtensionProcessor findProcessor(Element element, AnnotationMirror mirror) { + private ExtensionProcessor findProcessor(Template template, AnnotationMirror mirror) { String processorName = Utils.getQualifiedName(mirror.getAnnotationType()); ExtensionProcessor processor = null; if (extensions.containsKey(processorName)) { @@ -88,24 +89,24 @@ } else { AnnotationMirror foundExtension = Utils.findAnnotationMirror(context.getEnvironment(), mirror.getAnnotationType().asElement(), ExtensionAnnotation.class); if (foundExtension != null) { - String className = Utils.getAnnotationValueString(foundExtension, "processorClassName"); + String className = Utils.getAnnotationValue(String.class, foundExtension, "processorClassName"); Class processorClass; try { processorClass = Class.forName(className); } catch (ClassNotFoundException e) { - context.getLog().error(element, mirror, "Could not find processor class '%s' configured in '@%s'.", className, processorName); + template.addError("Could not find processor class '%s' configured in '@%s'.", className, processorName); return null; } try { processor = (ExtensionProcessor) processorClass.newInstance(); } catch (InstantiationException e) { - context.getLog().error(element, mirror, "Could not instantiate processor class '%s' configured in '@%s'.", className, processorName); + template.addError("Could not instantiate processor class '%s' configured in '@%s'.", className, processorName); return null; } catch (IllegalAccessException e) { - context.getLog().error(element, mirror, "Could not access processor class '%s' configured in '@%s'.", className, processorName); + template.addError("Could not access processor class '%s' configured in '@%s'.", className, processorName); return null; } catch (ClassCastException e) { - context.getLog().error(element, mirror, "Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName()); + template.addError("Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName()); return null; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -44,14 +44,14 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { List types = new ArrayList<>(); - types.addAll(Arrays.asList(getNode().getTypeSystem().getPrimitiveTypeMirrors())); + types.addAll(getNode().getTypeSystem().getPrimitiveTypeMirrors()); types.add(getContext().getType(void.class)); - ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types.toArray(new TypeMirror[types.size()]), false, Cardinality.ONE); + ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types, false, Cardinality.ONE); List parameters = new ArrayList<>(); parameters.add(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true)); - return new MethodSpec(returnTypeSpec, parameters); + return new MethodSpec(new ArrayList(), returnTypeSpec, parameters); } @Override diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -41,7 +41,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(null); + return createDefaultMethodSpec(method, mirror, null); } @Override @@ -51,8 +51,7 @@ for (ExecutableTypeData type : execTypes) { types.add(type.getType().getPrimitiveType()); } - TypeMirror[] array = types.toArray(new TypeMirror[types.size()]); - return new ParameterSpec(valueName, array, false, Cardinality.ONE); + return new ParameterSpec(valueName, types, false, Cardinality.ONE); } @Override diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -25,9 +25,10 @@ import java.util.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; +import com.oracle.truffle.codegen.processor.node.NodeFieldData.*; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; @@ -54,10 +55,21 @@ return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; } - protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) { + @SuppressWarnings("unused") + protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) { List defaultParameters = new ArrayList<>(); - ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true); - defaultParameters.add(frameSpec); + + if (getNode().supportsFrame()) { + defaultParameters.add(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true)); + } + + TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); + + List prefixTypes = new ArrayList<>(); + + if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(declaredType, template.getNodeType())) { + prefixTypes.add(getNode().getTemplateType().asType()); + } for (NodeFieldData field : getNode().getFields()) { if (field.getExecutionKind() == ExecutionKind.IGNORE) { @@ -65,7 +77,12 @@ } if (field.getExecutionKind() == ExecutionKind.DEFAULT) { - defaultParameters.add(createValueParameterSpec(field.getName(), field.getNodeData(), false)); + ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData(), false); + if (field.getKind() == FieldKind.CHILDREN) { + spec.setCardinality(Cardinality.MULTIPLE); + spec.setIndexed(true); + } + defaultParameters.add(spec); } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { String valueName = field.getName(); if (shortCircuitName != null && valueName.equals(shortCircuitName)) { @@ -79,7 +96,7 @@ } } - return new MethodSpec(createReturnParameterSpec(), defaultParameters); + return new MethodSpec(prefixTypes, createReturnParameterSpec(), defaultParameters); } private static String shortCircuitValueName(String valueName) { diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Thu Mar 14 01:09:43 2013 +0100 @@ -35,6 +35,7 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.ast.*; import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; +import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -51,73 +52,49 @@ } private static String factoryClassName(NodeData node) { - return nodeClassName(node) + "Factory"; - } - - private static String nodeClassName(NodeData node) { - return Utils.getSimpleName(node.getTemplateType().asType()); + return node.getNodeId() + "Factory"; } - private static String nodeClassName(SpecializationData specialization) { - String name = specializationId(specialization); - name += nodeClassName(specialization.getNode()); - if (name.equals(Utils.getSimpleName(specialization.getNode().getNodeType())) || name.equals(Utils.getSimpleName(specialization.getNode().getTemplateType()))) { - name = name + "Impl"; + private static String nodeSpecializationClassName(SpecializationData specialization) { + String nodeid = specialization.getNode().getNodeId(); + if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { + nodeid = nodeid.substring(0, nodeid.length() - 4); } + String name = Utils.firstLetterUpperCase(nodeid); + name += Utils.firstLetterUpperCase(specialization.getId()); + name += "Node"; return name; } - private static String specializationId(SpecializationData specialization) { - String name = ""; - NodeData node = specialization.getNode(); - if (node.getSpecializations().length > 1) { - name = specialization.getMethodName(); - if (name.startsWith("do")) { - name = name.substring(2); - } - } - return name; - } - - private static String valueName(NodeFieldData field) { - return field.getName() + "Value"; - } - private static String valueName(ActualParameter param) { - NodeData node = (NodeData) param.getMethod().getTemplate(); - NodeFieldData field = node.findField(param.getSpecification().getName()); - if (field != null) { - return valueName(field); - } else { - return param.getSpecification().getName(); - } + return param.getName(); } private static String castValueName(ActualParameter parameter) { return valueName(parameter) + "Cast"; } - private static String castValueName(NodeFieldData field) { - return valueName(field) + "Cast"; - } - - private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { - if (forceFrame) { - method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame")); + private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean includeHidden) { + if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { + method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue")); } for (ActualParameter parameter : specialization.getParameters()) { ParameterSpec spec = parameter.getSpecification(); if (forceFrame && spec.getName().equals("frame")) { continue; } + if (!includeHidden && parameter.isHidden()) { + continue; + } + method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); } } - private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame) { - if (forceFrame) { - builder.string("frame"); + private static void addValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeHidden) { + if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { + builder.string("frameValue"); } for (ActualParameter parameter : specialization.getParameters()) { ParameterSpec spec = parameter.getSpecification(); @@ -125,7 +102,11 @@ continue; } - if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) { + if (!includeHidden && parameter.isHidden()) { + continue; + } + + if (unexpectedValueName != null && parameter.getName().equals(unexpectedValueName)) { builder.string("ex.getResult()"); } else { builder.string(valueName(parameter)); @@ -133,14 +114,18 @@ } } - private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization) { + private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization, boolean includeHidden) { NodeData node = targetSpecialization.getNode(); TypeSystemData typeSystem = node.getTypeSystem(); for (ActualParameter targetParameter : targetSpecialization.getParameters()) { - ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getSpecification().getName()); + ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getName()); TypeData targetType = targetParameter.getActualTypeData(typeSystem); + if (!includeHidden && (targetParameter.isHidden() || valueParameter.isHidden())) { + continue; + } + TypeData valueType = null; if (valueParameter != null) { valueType = valueParameter.getActualTypeData(typeSystem); @@ -158,31 +143,63 @@ return getSimpleName(operation.getTemplateType()) + "Gen"; } - private static void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod method) { + private void startCallOperationMethod(CodeTreeBuilder body, TemplateMethod templateMethod, boolean castedValues) { body.startGroup(); - if (body.findMethod().getModifiers().contains(STATIC)) { - body.string(THIS_NODE_LOCAL_VAR_NAME); + ExecutableElement method = templateMethod.getMethod(); + if (method == null) { + throw new IllegalStateException("Cannot call synthtetic operation methods."); + } + TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); + NodeData node = (NodeData) templateMethod.getTemplate(); + + boolean accessible = templateMethod.canBeAccessedByInstanceOf(node.getNodeType()); + if (accessible) { + if (body.findMethod().getModifiers().contains(STATIC)) { + body.string(THIS_NODE_LOCAL_VAR_NAME); + } else { + body.string("super"); + } } else { - body.string("super"); + if (method.getModifiers().contains(STATIC)) { + body.type(targetClass.asType()); + } else { + ActualParameter parameter = templateMethod.getParameters().get(0); + if (castedValues) { + NodeFieldData field = node.findField(parameter.getSpecification().getName()); + NodeData fieldNode = field.getNodeData(); + ExecutableTypeData execType = fieldNode.findExecutableType(parameter.getActualTypeData(node.getTypeSystem())); + if (execType.hasUnexpectedValue(getContext())) { + body.string(castValueName(parameter)); + } else { + body.string(valueName(parameter)); + } + } else { + body.string(valueName(parameter)); + } + } } body.string("."); - body.startCall(method.getMethodName()); + body.startCall(method.getSimpleName().toString()); } - private static String generatedGenericMethodName(SpecializationData specialization) { + private String generatedGenericMethodName(SpecializationData specialization) { final String prefix = "generic"; if (specialization == null) { return prefix; } + if (!specialization.getNode().getGenericSpecialization().isUseSpecializationsForGeneric() || !specialization.getNode().needsRewrites(context)) { + return prefix; + } + SpecializationData prev = null; for (SpecializationData current : specialization.getNode().getSpecializations()) { if (specialization == current) { if (prev == null || prev.isUninitialized()) { return prefix; } else { - return prefix + specializationId(current); + return prefix + current.getId(); } } prev = current; @@ -237,34 +254,32 @@ } if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { - builder.startIf().string(conditionPrefix).end().startBlock(); + builder.startIf(); + builder.string(conditionPrefix); + builder.end().startBlock(); ifCount++; } builder.tree(guardedStatements); builder.end(ifCount); - if (ifCount > 0 && elseStatements != null) { - builder.startElseBlock(); + if (elseStatements != null && ifCount > 0) { builder.tree(elseStatements); - builder.end(); } - return builder.getRoot(); } - private static CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, - boolean onSpecialization) { + private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; - if (guardedSpecialization.getGuards().length > 0) { + if (guardedSpecialization.getGuards().size() > 0) { // Explicitly specified guards for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { builder.string(andOperator); - startCallOperationMethod(builder, guard.getGuardDeclaration()); - addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization); + startCallOperationMethod(builder, guard.getGuardDeclaration(), true); + addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization, false); builder.end().end(); // call andOperator = " && "; @@ -276,13 +291,14 @@ } private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { - NodeData node = guardedSpecialization.getNode(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); // Implict guards based on method signature - for (NodeFieldData field : node.getFields()) { - ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); - ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); + for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { + NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); + if (field == null) { + continue; + } + ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getName()); CodeTree cast = createCast(parent, field, valueParam, guardedParam); if (cast == null) { @@ -295,14 +311,15 @@ } private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { - NodeData node = guardedSpecialization.getNode(); - CodeTreeBuilder builder = new CodeTreeBuilder(parent); // Implict guards based on method signature String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; - for (NodeFieldData field : node.getFields()) { - ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); - ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); + for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { + NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); + if (field == null) { + continue; + } + ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getName()); CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); if (implicitGuard == null) { @@ -339,7 +356,7 @@ } startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem()))); - builder.string(valueName(field)); + builder.string(valueName(source)); builder.end().end(); // call if (field.isShortCircuit()) { @@ -371,7 +388,7 @@ CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target)); - return createLazyAssignment(parent, castValueName(field), target.getActualType(), condition, value); + return createLazyAssignment(parent, castValueName(target), target.getActualType(), condition, value); } /** @@ -408,6 +425,10 @@ return builder.getRoot(); } + private void emitEncounteredSynthetic(CodeTreeBuilder builder) { + builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); + } + @Override protected void createChildren(NodeData node) { Map> childTypes = new LinkedHashMap<>(); @@ -492,13 +513,15 @@ if (node.needsFactory()) { createFactoryMethods(node, clazz, createVisibility); - if (node.getSpecializations().length > 1) { + if (node.getSpecializations().size() > 1) { clazz.add(createCreateSpecializedMethod(node, createVisibility)); } - if (node.needsRewrites(getContext())) { + if (node.needsRewrites(context)) { clazz.add(createSpecializeMethod(node)); + } + if (node.getGenericSpecialization() != null) { List genericMethods = createGeneratedGenericMethod(node); for (CodeExecutableElement method : genericMethods) { clazz.add(method); @@ -515,6 +538,7 @@ clazz.add(createCreateNodeSpecializedMethod(node)); clazz.add(createGetNodeClassMethod(node)); clazz.add(createGetNodeSignaturesMethod(node)); + clazz.add(createGetChildrenSignatureMethod(node)); clazz.add(createGetInstanceMethod(node, createVisibility)); clazz.add(createInstanceConstant(node, clazz.asType())); } @@ -565,21 +589,62 @@ builder.startStaticCall(getContext().getType(Arrays.class), "asList"); List constructors = findUserConstructors(node); for (ExecutableElement constructor : constructors) { - builder.startGroup(); - builder.type(getContext().getType(Arrays.class)); - builder.string(".<").type(getContext().getType(Class.class)).string(">"); - builder.startCall("asList"); - for (VariableElement param : constructor.getParameters()) { - builder.typeLiteral(param.asType()); - } - builder.end(); - builder.end(); + builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); } builder.end(); builder.end(); return method; } + private CodeExecutableElement createGetChildrenSignatureMethod(NodeData node) { + Types types = getContext().getEnvironment().getTypeUtils(); + TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); + TypeMirror classType = getContext().getType(Class.class); + TypeMirror nodeType = getContext().getTruffleTypes().getNode(); + TypeMirror wildcardNodeType = types.getWildcardType(nodeType, null); + classType = types.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); + TypeMirror returnType = types.getDeclaredType(listType, classType); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); + CodeTreeBuilder builder = method.createBuilder(); + + List signatureTypes = new ArrayList<>(); + assert !node.getSpecializations().isEmpty(); + SpecializationData data = node.getSpecializations().get(0); + for (ActualParameter parameter : data.getParameters()) { + ParameterSpec spec = parameter.getSpecification(); + NodeFieldData field = node.findField(spec.getName()); + if (field == null) { + continue; + } + + TypeMirror type; + if (field.getKind() == FieldKind.CHILDREN && field.getType().getKind() == TypeKind.ARRAY) { + type = ((ArrayType) field.getType()).getComponentType(); + } else { + type = field.getType(); + } + + signatureTypes.add(type); + } + + builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end(); + return method; + } + + private CodeTree createAsList(CodeTreeBuilder parent, List types, TypeMirror elementClass) { + CodeTreeBuilder builder = parent.create(); + builder.startGroup(); + builder.type(getContext().getType(Arrays.class)); + builder.string(".<").type(elementClass).string(">"); + builder.startCall("asList"); + for (TypeMirror typeMirror : types) { + builder.typeLiteral(typeMirror); + } + builder.end().end(); + return builder.getRoot(); + } + private CodeExecutableElement createCreateNodeMethod(NodeData node) { CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); @@ -717,15 +782,21 @@ } List nodeTypesList = new ArrayList<>(); + TypeMirror prev = null; + boolean allSame = true; for (NodeData child : children) { - nodeTypesList.add(child.getTemplateType().asType()); + nodeTypesList.add(child.getNodeType()); + if (prev != null && !Utils.typeEquals(child.getNodeType(), prev)) { + allSame = false; + } + prev = child.getNodeType(); } TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); Types types = getContext().getEnvironment().getTypeUtils(); TypeMirror factoryType = getContext().getType(NodeFactory.class); TypeMirror baseType; - if (children.size() == 1) { + if (allSame) { baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); } else { baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); @@ -793,10 +864,10 @@ CodeTreeBuilder body = method.createBuilder(); body.startReturn(); - if (node.getSpecializations().length == 0) { + if (node.getSpecializations().isEmpty()) { body.null_(); } else { - body.startNew(nodeClassName(node.getSpecializations()[0])); + body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0))); for (VariableElement var : method.getParameters()) { body.string(var.getSimpleName().toString()); } @@ -828,14 +899,14 @@ body.startElseIf(); } body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); - body.startReturn().startNew(nodeClassName(specialization)); + body.startReturn().startNew(nodeSpecializationClassName(specialization)); body.string(THIS_NODE_LOCAL_VAR_NAME); body.end().end(); // new, return body.end(); // if } } - body.startReturn().startNew(nodeClassName(node.getGenericSpecialization())); + body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization())); body.string(THIS_NODE_LOCAL_VAR_NAME); body.end().end(); return method; @@ -845,17 +916,17 @@ CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize"); method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); - addValueParameters(method, node.getGenericSpecialization(), false); + addValueParameters(method, node.getGenericSpecialization(), false, true); CodeTreeBuilder body = method.createBuilder(); - body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(node.getSpecializations()[0])).string(".class)").end(); + body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); - for (int i = 1; i < node.getSpecializations().length; i++) { - SpecializationData specialization = node.getSpecializations()[i]; - body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end(); + for (int i = 1; i < node.getSpecializations().size(); i++) { + SpecializationData specialization = node.getSpecializations().get(i); + body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(specialization)).string(".class)").end(); CodeTreeBuilder guarded = new CodeTreeBuilder(body); - guarded.startReturn().startNew(nodeClassName(specialization)); + guarded.startReturn().startNew(nodeSpecializationClassName(specialization)); guarded.string(THIS_NODE_LOCAL_VAR_NAME); guarded.end().end(); @@ -868,14 +939,14 @@ private List createGeneratedGenericMethod(NodeData node) { TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getActualType(); - if (node.getGenericSpecialization().isUseSpecializationsForGeneric()) { + if (node.getGenericSpecialization().isUseSpecializationsForGeneric() && node.needsRewrites(context)) { List methods = new ArrayList<>(); - SpecializationData[] specializations = node.getSpecializations(); + List specializations = node.getSpecializations(); SpecializationData prev = null; - for (int i = 0; i < specializations.length; i++) { - SpecializationData current = specializations[i]; - SpecializationData next = i + 1 < specializations.length ? specializations[i + 1] : null; + for (int i = 0; i < specializations.size(); i++) { + SpecializationData current = specializations.get(i); + SpecializationData next = i + 1 < specializations.size() ? specializations.get(i + 1) : null; if (prev == null || current.isUninitialized()) { prev = current; continue; @@ -883,7 +954,7 @@ String methodName = generatedGenericMethodName(current); CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName); method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); - addValueParameters(method, node.getGenericSpecialization(), true); + addValueParameters(method, node.getGenericSpecialization(), true, true); emitGeneratedGenericSpecialization(method.createBuilder(), current, next); @@ -896,7 +967,7 @@ } else { CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null)); method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME)); - addValueParameters(method, node.getGenericSpecialization(), true); + addValueParameters(method, node.getGenericSpecialization(), true, true); emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0); return Arrays.asList(method); } @@ -908,44 +979,51 @@ CodeTree invokeMethod = invokeMethodBuilder.getRoot(); if (next != null) { - invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, null); + CodeTreeBuilder nextBuilder = builder.create(); + + nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); + nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); + addValueParameterNames(nextBuilder, next, null, true, true); + nextBuilder.end().end(); + + invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, nextBuilder.getRoot()); } builder.tree(invokeMethod); if (next != null) { builder.end(); - - builder.startReturn().startCall(generatedGenericMethodName(next)); - builder.string(THIS_NODE_LOCAL_VAR_NAME); - addValueParameterNames(builder, next, null, true); - builder.end().end(); } } private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization, int level) { - if (specialization.getExceptions().length > 0) { + if (!specialization.getExceptions().isEmpty()) { builder.startTryBlock(); } - builder.startReturn(); - startCallOperationMethod(builder, specialization); - addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization); - builder.end().end(); // start call operation - builder.end(); // return + if (specialization.getMethod() == null) { + emitEncounteredSynthetic(builder); + } else { + builder.startReturn(); + startCallOperationMethod(builder, specialization, true); + addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization, false); + builder.end().end(); // start call operation + builder.end(); // return + } - if (specialization.getExceptions().length > 0) { + if (!specialization.getExceptions().isEmpty()) { for (SpecializationThrowsData exception : specialization.getExceptions()) { builder.end().startCatchBlock(exception.getJavaClass(), "ex" + level); builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); builder.string(THIS_NODE_LOCAL_VAR_NAME); - addValueParameterNames(builder, exception.getTransitionTo(), null, true); + addValueParameterNames(builder, exception.getTransitionTo(), null, true, true); builder.end().end(); } builder.end(); } } + } private class SpecializedNodeFactory extends ClassElementFactory { @@ -957,7 +1035,7 @@ @Override public CodeTypeElement create(SpecializationData specialization) { NodeData node = specialization.getNode(); - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), node.getNodeType(), false); + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), node.getNodeType(), false); return clazz; } @@ -981,7 +1059,7 @@ CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); if (method.getParameters().size() == 1) { CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0)); - var.setName("frame"); + var.setName("frameValue"); method.getParameters().set(0, var); } method.getModifiers().remove(Modifier.ABSTRACT); @@ -996,7 +1074,7 @@ } if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) { - buildSpecializeStateMethod(clazz, specialization); + buildSpecializeAndExecute(clazz, specialization); } } @@ -1014,7 +1092,7 @@ CodeTree primaryExecuteCall = null; CodeTreeBuilder executeBuilder = CodeTreeBuilder.createBuilder(); - buildExecute(executeBuilder, null, execType); + buildExecute(executeBuilder, null, null, execType); primaryExecuteCall = executeBuilder.getRoot(); if (needsTry) { @@ -1122,7 +1200,7 @@ builder.startCall(factoryClassName(node), "specialize"); builder.string("this"); builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); - addValueParameterNames(builder, specialization, null, false); + addValueParameterNames(builder, specialization, null, false, true); builder.end(); // call replace, call specialize } else { builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); @@ -1134,29 +1212,28 @@ private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (specialization.getExceptions().length > 0) { + if (!specialization.getExceptions().isEmpty()) { builder.startTryBlock(); } - if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) { + if (specialization.getMethod() == null && !node.needsRewrites(context)) { + emitEncounteredSynthetic(builder); + } else if (specialization.isUninitialized() || specialization.isGeneric()) { builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); builder.string("this"); - addValueParameterNames(builder, specialization, null, true); + addValueParameterNames(builder, specialization, null, true, true); builder.end().end(); } else { builder.startReturn(); - if (specialization.isUninitialized()) { - startCallOperationMethod(builder, specialization.getNode().getGenericSpecialization()); - } else { - startCallOperationMethod(builder, specialization); - } - addValueParameterNames(builder, specialization, null, false); + startCallOperationMethod(builder, specialization, false); + addValueParameterNames(builder, specialization, null, false, false); + builder.end().end(); // operation call builder.end(); // return } - if (specialization.getExceptions().length > 0) { + if (!specialization.getExceptions().isEmpty()) { for (SpecializationThrowsData exception : specialization.getExceptions()) { builder.end().startCatchBlock(exception.getJavaClass(), "ex"); builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null)); @@ -1168,18 +1245,14 @@ private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); - for (NodeFieldData field : specialization.getNode().getFields()) { - if (field.getExecutionKind() == ExecutionKind.IGNORE) { + + for (ActualParameter parameter : specialization.getParameters()) { + NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName()); + if (field == null) { continue; } - ActualParameter parameterType = specialization.findParameter(field.getName()); - - if (parameterType.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) { - buildGenericValueExecute(builder, specialization, field, null); - } else { - buildSpecializedValueExecute(builder, specialization, field); - } + buildFieldExecute(builder, specialization, parameter, field, null); } return builder.getRoot(); } @@ -1187,37 +1260,58 @@ private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { for (TemplateMethod listener : node.getSpecializationListeners()) { builder.startStatement(); - startCallOperationMethod(builder, listener); - addValueParameterNames(builder, listener, null, false); + startCallOperationMethod(builder, listener, false); + addValueParameterNames(builder, listener, null, false, false); builder.end().end(); builder.end(); // statement } } - private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field, NodeFieldData exceptionSpec) { - ActualParameter specParameter = specialization.findParameter(field.getName()); - NodeData node = specialization.getNode(); - boolean shortCircuit = startShortCircuit(builder, specialization, field, exceptionSpec); + private void buildFieldExecute(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter param, NodeFieldData field, ActualParameter exceptionParam) { + boolean shortCircuit = startShortCircuit(builder, specialization, param, exceptionParam); + ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); + boolean unexpected = execType.hasUnexpectedValue(getContext()); - builder.startStatement(); - if (!shortCircuit) { - builder.type(specialization.getNode().getTypeSystem().getGenericType()); - builder.string(" "); + if (!shortCircuit && unexpected) { + builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); + } + + if (unexpected) { + builder.startTryBlock(); } - builder.string(valueName(specParameter)); - builder.string(" = "); - ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), specParameter.getActualTypeData(node.getTypeSystem())); - if (genericExecutableType == null) { - throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes())); + if (!shortCircuit && !unexpected) { + builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).string(" = "); + } else { + builder.startStatement().string(valueName(param)).string(" = "); } - buildExecute(builder, field, genericExecutableType); + buildExecute(builder, param, field, execType); builder.end(); + if (unexpected) { + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + SpecializationData generic = specialization.getNode().getGenericSpecialization(); + boolean execute = false; + for (ActualParameter exParam : generic.getParameters()) { + NodeFieldData exField = generic.getNode().findField(exParam.getSpecification().getName()); + if (exField == null) { + continue; + } + if (execute) { + buildFieldExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param); + } else if (exParam.getName().equals(param.getName())) { + execute = true; + } + } + builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param)); + builder.end(); // catch block + } + endShortCircuit(builder, shortCircuit); + builder.newLine(); } - private void buildExecute(CodeTreeBuilder builder, NodeFieldData field, ExecutableTypeData execType) { + private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) { if (field != null) { Element accessElement = field.getAccessElement(); if (accessElement.getKind() == ElementKind.METHOD) { @@ -1227,60 +1321,28 @@ } else { throw new AssertionError(); } + if (parameter.getSpecification().isIndexed()) { + builder.string("[" + parameter.getIndex() + "]"); + } builder.string("."); } builder.startCall(execType.getMethodName()); - if (execType.getParameters().length == 1) { - builder.string("frame"); + if (execType.getParameters().size() == 1) { + builder.string("frameValue"); } builder.end(); } - private void buildSpecializedValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field) { - ActualParameter param = specialization.findParameter(field.getName()); - boolean shortCircuit = startShortCircuit(builder, specialization, field, null); - - if (!shortCircuit) { - builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); - } - - ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); - - if (execType.hasUnexpectedValue(getContext())) { - builder.startTryBlock(); + private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { + NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); + if (forField == null) { + return false; } - builder.startStatement().string(valueName(field)).string(" = "); - buildExecute(builder, field, execType); - builder.end(); - - if (execType.hasUnexpectedValue(getContext())) { - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); - boolean execute = false; - for (NodeFieldData exField : specialization.getNode().getFields()) { - if (exField.getExecutionKind() == ExecutionKind.IGNORE) { - continue; - } - if (execute) { - buildGenericValueExecute(builder, specialization.getNode().getGenericSpecialization(), exField, field); - } else if (exField == field) { - execute = true; - } - } - builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification())); - builder.end(); // catch block - } - - endShortCircuit(builder, shortCircuit); - builder.newLine(); - } - - private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData forField, NodeFieldData exceptionField) { if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) { return false; } - ActualParameter parameter = specialization.findParameter(forField.getName()); ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); int shortCircuitIndex = 0; @@ -1294,16 +1356,16 @@ } builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); - ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; + ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - startCallOperationMethod(builder, shortCircuitData); - addValueParameterNames(builder, shortCircuitData, exceptionField != null ? exceptionField.getName() : null, false); + startCallOperationMethod(builder, shortCircuitData, false); + addValueParameterNames(builder, shortCircuitData, exceptionParam != null ? exceptionParam.getName() : null, false, false); builder.end().end(); // call operation builder.end(); // statement builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); - builder.startIf().string(shortCircuitParam.getSpecification().getName()).end(); + builder.startIf().string(shortCircuitParam.getName()).end(); builder.startBlock(); return true; @@ -1315,11 +1377,11 @@ } } - private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) { + private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) { CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); specializeCall.startCall("specializeAndExecute"); - specializeCall.string(nodeClassName(nextSpecialization) + ".class"); - addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true); + specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); + addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getName() : null, true, true); specializeCall.end().end(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -1329,7 +1391,7 @@ return builder.getRoot(); } - private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) { + private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) { NodeData node = specialization.getNode(); TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); ExecutableTypeData returnExecutableType = node.findExecutableType(returnType); @@ -1340,7 +1402,7 @@ if (canThrowUnexpected) { method.addThrownType(getUnexpectedValueException()); } - addValueParameters(method, specialization.getNode().getGenericSpecialization(), true); + addValueParameters(method, specialization.getNode().getGenericSpecialization(), true, true); clazz.add(method); CodeTreeBuilder builder = method.createBuilder(); @@ -1351,7 +1413,7 @@ builder.startStatement(); builder.startCall("replace"); builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); - addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false); + addValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false, true); builder.end(); builder.end(); // call replace builder.end(); // statement @@ -1362,7 +1424,7 @@ CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); genericExecute.string("this"); - addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true); + addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true, true); genericExecute.end(); // call generated generic CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Thu Mar 14 01:09:43 2013 +0100 @@ -35,22 +35,85 @@ public class NodeData extends Template { - private NodeData parent; - private List declaredChildren; + private final String nodeId; + private NodeData declaringNode; + private List declaredChildren = new ArrayList<>(); + + private TypeSystemData typeSystem; + private List fields; + private TypeMirror nodeType; + private ParameterSpec instanceParameterSpec; + + private List specializations; + private List specializationListeners; + private List guards; + private List executableTypes; + private List shortCircuits; - private final TypeSystemData typeSystem; + public NodeData(TypeElement type, String id) { + super(type, null, null); + this.nodeId = id; + } + + public NodeData(NodeData splitSource, String templateMethodName, String nodeId) { + super(splitSource.getTemplateType(), templateMethodName, null); + this.nodeId = nodeId; + this.declaringNode = splitSource.declaringNode; + this.declaredChildren = splitSource.declaredChildren; + this.typeSystem = splitSource.typeSystem; + this.nodeType = splitSource.nodeType; + this.specializations = splitSource.specializations; + this.specializationListeners = splitSource.specializationListeners; + this.guards = splitSource.guards; + this.executableTypes = splitSource.executableTypes; + this.shortCircuits = splitSource.shortCircuits; + this.fields = splitSource.fields; + } + + void setTypeSystem(TypeSystemData typeSystem) { + this.typeSystem = typeSystem; + } - private NodeFieldData[] fields; - private SpecializationData[] specializations; - private TemplateMethod[] specializationListeners; - private GuardData[] guards; - private ExecutableTypeData[] executableTypes; + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (declaredChildren != null) { + sinks.addAll(declaredChildren); + } + if (typeSystem != null) { + sinks.add(typeSystem); + } + if (specializations != null) { + sinks.addAll(specializations); + } + if (specializationListeners != null) { + sinks.addAll(specializationListeners); + } + if (guards != null) { + sinks.addAll(guards); + } + if (executableTypes != null) { + sinks.addAll(executableTypes); + } + if (shortCircuits != null) { + sinks.addAll(shortCircuits); + } + if (fields != null) { + sinks.addAll(fields); + } + return sinks; + } - private TypeMirror nodeType; + public ParameterSpec getInstanceParameterSpec() { + return instanceParameterSpec; + } - public NodeData(TypeElement type, TypeSystemData typeSystem) { - super(type, null); - this.typeSystem = typeSystem; + public void setInstanceParameterSpec(ParameterSpec instanceParameter) { + this.instanceParameterSpec = instanceParameter; + } + + public String getNodeId() { + return nodeId; } public TypeMirror getNodeType() { @@ -71,6 +134,15 @@ return !noSpecialization; } + public boolean supportsFrame() { + for (ExecutableTypeData execType : executableTypes) { + if (execType.findParameter("frameValue") == null) { + return false; + } + } + return true; + } + public List getNodeChildren() { List children = new ArrayList<>(); for (NodeData child : getDeclaredChildren()) { @@ -86,12 +158,12 @@ this.declaredChildren = declaredChildren; for (NodeData child : declaredChildren) { - child.parent = this; + child.declaringNode = this; } } public NodeData getParent() { - return parent; + return declaringNode; } public List getDeclaredChildren() { @@ -107,22 +179,16 @@ for (SpecializationData specialization : getSpecializations()) { methods.add(specialization); - if (specialization.getShortCircuits() != null) { - methods.addAll(Arrays.asList(specialization.getShortCircuits())); - } } - methods.addAll(Arrays.asList(getSpecializationListeners())); - methods.addAll(Arrays.asList(getExecutableTypes())); - methods.addAll(Arrays.asList(getGuards())); + methods.addAll(getSpecializationListeners()); + methods.addAll(getExecutableTypes()); + methods.addAll(getGuards()); + methods.addAll(getShortCircuits()); return methods; } - public TemplateMethod[] getSpecializationListeners() { - return specializationListeners; - } - public List findGuards(String name) { List foundGuards = new ArrayList<>(); for (GuardData guardData : getGuards()) { @@ -133,10 +199,6 @@ return foundGuards; } - public ExecutableTypeData[] getExecutableTypes() { - return executableTypes; - } - public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type) { List types = findGenericExecutableTypes(context); for (ExecutableTypeData availableType : types) { @@ -147,6 +209,14 @@ return null; } + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) { + List types = findGenericExecutableTypes(context); + if (!types.isEmpty()) { + return types.get(0); + } + return null; + } + public List findGenericExecutableTypes(ProcessorContext context) { List types = new ArrayList<>(); for (ExecutableTypeData type : executableTypes) { @@ -180,47 +250,20 @@ return result; } - public TypeMirror[] getExecutablePrimitiveTypeMirrors() { - TypeMirror[] typeMirrors = new TypeMirror[executableTypes.length]; - for (int i = 0; i < executableTypes.length; i++) { - typeMirrors[i] = executableTypes[i].getType().getPrimitiveType(); + public List getExecutablePrimitiveTypeMirrors() { + List typeMirrors = new ArrayList<>(); + for (ExecutableTypeData executableType : executableTypes) { + typeMirrors.add(executableType.getType().getPrimitiveType()); } return typeMirrors; } - void setExecutableTypes(ExecutableTypeData[] declaredExecuableTypes) { - this.executableTypes = declaredExecuableTypes; - } - - void setFields(NodeFieldData[] fields) { - this.fields = fields; - } - - void setSpecializations(SpecializationData[] specializations) { - this.specializations = specializations; - } - - void setSpecializationListeners(TemplateMethod[] specializationListeners) { - this.specializationListeners = specializationListeners; - } - - void setGuards(GuardData[] guards) { - this.guards = guards; - } - - public GuardData[] getGuards() { - return guards; - } - public NodeFieldData[] filterFields(FieldKind fieldKind, ExecutionKind usage) { List filteredFields = new ArrayList<>(); - NodeFieldData[] resolvedFields = getFields(); - if (fields != null) { - for (NodeFieldData field : resolvedFields) { - if (usage == null || field.getExecutionKind() == usage) { - if (fieldKind == null || field.getKind() == fieldKind) { - filteredFields.add(field); - } + for (NodeFieldData field : getFields()) { + if (usage == null || field.getExecutionKind() == usage) { + if (fieldKind == null || field.getKind() == fieldKind) { + filteredFields.add(field); } } } @@ -238,18 +281,13 @@ public boolean needsRewrites(ProcessorContext context) { boolean needsRewrites = false; - for (NodeFieldData field : getFields()) { - if (field.getExecutionKind() == ExecutionKind.DEFAULT || field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { - if (!field.getNodeData().hasUnexpectedExecutableTypes(context)) { - continue; - } + for (SpecializationData specialization : getSpecializations()) { + if (specialization.hasRewrite(context)) { needsRewrites = true; break; } } - - needsRewrites &= specializations.length >= 2; return needsRewrites; } @@ -263,37 +301,65 @@ } public TypeSystemData getTypeSystem() { - if (typeSystem != null) { - return typeSystem; + return typeSystem; + } + + public String dump() { + return dump(0); + } + + private String dump(int level) { + String indent = ""; + for (int i = 0; i < level; i++) { + indent += " "; + } + StringBuilder builder = new StringBuilder(); + + builder.append(String.format("%s%s {", indent, toString())); + + dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType())); + dumpProperty(builder, indent, "typeSystem", getTypeSystem()); + dumpProperty(builder, indent, "fields", getFields()); + dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); + dumpProperty(builder, indent, "specializations", getSpecializations()); + dumpProperty(builder, indent, "guards", getGuards()); + dumpProperty(builder, indent, "messages", collectMessages()); + if (getDeclaredChildren().size() > 0) { + builder.append(String.format("\n%s children = [", indent)); + for (NodeData node : getDeclaredChildren()) { + builder.append("\n"); + builder.append(node.dump(level + 1)); + } + builder.append(String.format("\n%s ]", indent)); + } + builder.append(String.format("%s}", indent)); + return builder.toString(); + } + + private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) { + if (value instanceof List) { + List list = (List) value; + if (!list.isEmpty()) { + b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList((List) value))); + } } else { - return null; + if (value != null) { + b.append(String.format("\n%s %s = %s", indent, propertyName, value)); + } } } - public NodeFieldData[] getFields() { - return fields; - } - - public NodeFieldData[] getDeclaredFields() { - return fields; - } - - public SpecializationData[] getSpecializations() { - return specializations; - } - - public String dump() { - StringBuilder b = new StringBuilder(); - b.append(String.format("[name = %s\n" + " typeSystem = %s\n" + " fields = %s\n" + " types = %s\n" + " specializations = %s\n" + " guards = %s\n" + "]", - Utils.getQualifiedName(getTemplateType()), getTypeSystem(), dumpList(fields), dumpList(getExecutableTypes()), dumpList(getSpecializations()), dumpList(guards))); - return b.toString(); - } - - private static String dumpList(Object[] array) { + private static String dumpList(List array) { if (array == null) { return "null"; } + if (array.isEmpty()) { + return "[]"; + } else if (array.size() == 1) { + return "[" + array.get(0).toString() + "]"; + } + StringBuilder b = new StringBuilder(); b.append("["); for (Object object : array) { @@ -315,4 +381,76 @@ return null; } + public List getFields() { + return fields; + } + + void setFields(List fields) { + this.fields = fields; + } + + public List getSpecializations() { + return getSpecializations(false); + } + + public List getSpecializations(boolean userDefinedOnly) { + if (userDefinedOnly) { + List specs = new ArrayList<>(); + for (SpecializationData spec : specializations) { + if (spec.getMethod() != null) { + specs.add(spec); + } + } + return specs; + } else { + return specializations; + } + } + + public List getSpecializationListeners() { + return specializationListeners; + } + + public List getGuards() { + return guards; + } + + public List getExecutableTypes() { + return executableTypes; + } + + public List getShortCircuits() { + return shortCircuits; + } + + void setSpecializations(List specializations) { + this.specializations = specializations; + if (this.specializations != null) { + for (SpecializationData specialization : specializations) { + specialization.setNode(this); + } + } + } + + void setSpecializationListeners(List specializationListeners) { + this.specializationListeners = specializationListeners; + } + + void setGuards(List guards) { + this.guards = guards; + } + + void setExecutableTypes(List executableTypes) { + this.executableTypes = executableTypes; + } + + void setShortCircuits(List shortCircuits) { + this.shortCircuits = shortCircuits; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getNodeId() + "]"; + } + } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Thu Mar 14 01:09:43 2013 +0100 @@ -25,10 +25,12 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; -public class NodeFieldData { +import com.oracle.truffle.codegen.processor.template.*; + +public class NodeFieldData extends MessageContainer { public enum FieldKind { - FIELD, CHILD, CHILDREN + CHILD, CHILDREN } public enum ExecutionKind { @@ -41,21 +43,39 @@ private final FieldKind fieldKind; private final ExecutionKind executionKind; - private final NodeData nodeData; + private NodeData nodeData; - public NodeFieldData(NodeData typeNodeData, VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) { + public NodeFieldData(VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) { this.fieldElement = fieldElement; this.accessElement = accessElement; this.childAnnotationMirror = childAnnotationMirror; - this.nodeData = typeNodeData; this.fieldKind = fieldKind; this.executionKind = executionKind; } + NodeFieldData(NodeFieldData field) { + this.fieldElement = field.fieldElement; + this.accessElement = field.accessElement; + this.childAnnotationMirror = field.childAnnotationMirror; + this.fieldKind = field.fieldKind; + this.executionKind = field.executionKind; + this.nodeData = field.nodeData; + } + + @Override + public Element getMessageElement() { + return fieldElement; + } + public boolean isShortCircuit() { return executionKind == ExecutionKind.SHORT_CIRCUIT; } + void setNode(NodeData nodeData) { + this.nodeData = nodeData; + getMessages().addAll(nodeData.collectMessages()); + } + public VariableElement getFieldElement() { return fieldElement; } @@ -90,7 +110,7 @@ @Override public String toString() { - return "NodeFieldData[name=" + getName() + ", kind=" + fieldKind + ", execution=" + executionKind + "]"; + return "NodeFieldData[name=" + getName() + ", kind=" + fieldKind + ", execution=" + executionKind + ", node=" + getNodeData().toString() + "]"; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -28,6 +28,7 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; import javax.lang.model.util.*; +import javax.tools.Diagnostic.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.nodes.Node.Child; @@ -41,11 +42,9 @@ public class NodeParser extends TemplateParser { - public static final List> ANNOTATIONS = Arrays.asList(Generic.class, GuardCheck.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, - SpecializationGuard.class, SpecializationListener.class, SpecializationThrows.class); + public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class); private Map parsedNodes; - private TypeElement originalType; public NodeParser(ProcessorContext c) { super(c); @@ -54,23 +53,37 @@ @Override protected NodeData parse(Element element, AnnotationMirror mirror) { assert element instanceof TypeElement; + NodeData node = null; try { parsedNodes = new HashMap<>(); - originalType = (TypeElement) element; - - return parseInnerClassHierarchy((TypeElement) element); - } finally { + node = resolveNode((TypeElement) element); if (Log.DEBUG) { - NodeData parsed = parsedNodes.get(Utils.getQualifiedName(originalType)); - if (parsed != null) { + NodeData parsed = parsedNodes.get(Utils.getQualifiedName((TypeElement) element)); + if (node != null) { String dump = parsed.dump(); - log.error("Node parsed: %s", dump); - System.out.println("Parsed: " + dump); + log.message(Kind.ERROR, null, null, null, dump); + System.out.println(dump); } } + } finally { parsedNodes = null; - originalType = null; } + + return node; + } + + @Override + protected NodeData filterErrorElements(NodeData model) { + for (Iterator iterator = model.getDeclaredChildren().iterator(); iterator.hasNext();) { + NodeData node = filterErrorElements(iterator.next()); + if (node == null) { + iterator.remove(); + } + } + if (model.hasErrors()) { + return null; + } + return model; } @Override @@ -78,182 +91,426 @@ return true; } - private NodeData parseInnerClassHierarchy(TypeElement rootType) { + private NodeData resolveNode(TypeElement rootType) { + String typeName = Utils.getQualifiedName(rootType); + if (parsedNodes.containsKey(typeName)) { + return parsedNodes.get(typeName); + } + List types = ElementFilter.typesIn(rootType.getEnclosedElements()); + List children = new ArrayList<>(); for (TypeElement childElement : types) { - NodeData childNode = parseInnerClassHierarchy(childElement); + NodeData childNode = resolveNode(childElement); if (childNode != null) { children.add(childNode); } } - NodeData rootNode = resolveNode(rootType); - if (rootNode == null && children.size() > 0) { - rootNode = new NodeData(rootType, null); + + NodeData rootNode = parseNode(rootType); + boolean hasErrors = rootNode != null ? rootNode.hasErrors() : false; + if ((rootNode == null || hasErrors) && children.size() > 0) { + rootNode = new NodeData(rootType, rootType.getSimpleName().toString()); } + + parsedNodes.put(typeName, rootNode); + if (rootNode != null) { + children.addAll(rootNode.getDeclaredChildren()); rootNode.setDeclaredChildren(children); } return rootNode; } - private NodeData resolveNode(TypeElement currentType) { - String typeName = Utils.getQualifiedName(currentType); - if (!parsedNodes.containsKey(typeName)) { - NodeData node = parseNode(currentType); - if (node != null) { - parsedNodes.put(typeName, node); - } - return node; - } - return parsedNodes.get(typeName); - } - private NodeData parseNode(TypeElement type) { if (Utils.findAnnotationMirror(processingEnv, type, GeneratedBy.class) != null) { - // generated nodes get called again. + // generated nodes should not get called again. return null; } - if (!Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) { + + AnnotationMirror methodNodes = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class); + + if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) { return null; // not a node } if (type.getModifiers().contains(Modifier.PRIVATE)) { - return null; // not visible + // TODO error message here!? + return null; // not visible, not a node + } + + TypeElement nodeType; + boolean needsSplit; + if (methodNodes != null) { + needsSplit = methodNodes != null; + nodeType = Utils.fromTypeMirror(Utils.getAnnotationValue(TypeMirror.class, methodNodes, "value")); + } else { + needsSplit = false; + nodeType = type; + } + + NodeData nodeData = parseNodeData(type, nodeType); + if (nodeData.hasErrors()) { + return nodeData; // error sync point } List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); - List typeHierarchy = findSuperClasses(new ArrayList(), type); - Collections.reverse(typeHierarchy); - - AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); - if (typeSystemMirror == null) { - log.error(type, "No @%s annotation found in type hierarchy.", TypeSystemReference.class.getSimpleName()); - return null; - } - - TypeMirror typeSytemType = Utils.getAnnotationValueType(typeSystemMirror, "value"); - final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); - if (typeSystem == null) { - log.error(type, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); - return null; - } - - NodeData nodeData = new NodeData(type, typeSystem); - - nodeData.setExtensionElements(getExtensionParser().parseAll(type, elements)); + nodeData.setExtensionElements(getExtensionParser().parseAll(nodeData, elements)); if (nodeData.getExtensionElements() != null) { elements.addAll(nodeData.getExtensionElements()); } + parseMethods(nodeData, elements); - List executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); - - nodeData.setExecutableTypes(executableTypes.toArray(new ExecutableTypeData[executableTypes.size()])); + if (nodeData.hasErrors()) { + return nodeData; + } - parsedNodes.put(Utils.getQualifiedName(type), nodeData); + List nodes; + if (needsSplit) { + nodes = splitNodeData(nodeData); + } else { + nodes = new ArrayList<>(); + nodes.add(nodeData); + } - NodeFieldData[] fields = parseFields(nodeData, elements, typeHierarchy); - if (fields == null) { - return null; + for (NodeData splittedNode : nodes) { + finalizeSpecializations(splittedNode); + verifyNode(splittedNode); + } + + if (needsSplit) { + nodeData.setDeclaredChildren(nodes); + nodeData.setSpecializationListeners(new ArrayList()); + nodeData.setSpecializations(new ArrayList()); + return nodeData; + } else { + return nodeData; } - nodeData.setFields(fields); + } + + private static List splitNodeData(NodeData node) { + SortedMap> groupedSpecializations = groupByNodeId(node.getSpecializations()); + SortedMap> groupedListeners = groupByNodeId(node.getSpecializationListeners()); + + Set ids = new TreeSet<>(); + ids.addAll(groupedSpecializations.keySet()); + ids.addAll(groupedListeners.keySet()); + + List splitted = new ArrayList<>(); + for (String id : ids) { + List specializations = groupedSpecializations.get(id); + List listeners = groupedListeners.get(id); + + if (specializations == null) { + specializations = new ArrayList<>(); + } - List genericSpecializations = new GenericParser(context, nodeData).parse(elements); - List guards = new GuardParser(context, nodeData, nodeData.getTypeSystem()).parse(elements); - nodeData.setGuards(guards.toArray(new GuardData[guards.size()])); + if (listeners == null) { + listeners = new ArrayList<>(); + } + + String nodeId = node.getNodeId(); + if (nodeId.endsWith("Node") && !nodeId.equals("Node")) { + nodeId = nodeId.substring(0, nodeId.length() - 4); + } + String newNodeId = nodeId + Utils.firstLetterUpperCase(id); + NodeData copy = new NodeData(node, id, newNodeId); + + copy.setSpecializations(specializations); + copy.setSpecializationListeners(listeners); + + splitted.add(copy); + } + + node.setSpecializations(new ArrayList()); + node.setSpecializationListeners(new ArrayList()); + + return splitted; + } - SpecializationMethodParser specializationParser = new SpecializationMethodParser(context, nodeData); - List specializations = specializationParser.parse(elements); - List shortCircuits = new ShortCircuitParser(context, nodeData).parse(elements); - List listeners = new SpecializationListenerParser(context, nodeData).parse(elements); + private static SortedMap> groupByNodeId(List methods) { + SortedMap> grouped = new TreeMap<>(); + for (M m : methods) { + List list = grouped.get(m.getId()); + if (list == null) { + list = new ArrayList<>(); + grouped.put(m.getId(), list); + } + list.add(m); + } + return grouped; + } + + private void parseMethods(final NodeData node, List elements) { + node.setGuards(new GuardParser(context, node, node.getTypeSystem()).parse(elements)); + node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements)); + node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements)); + List generics = new GenericParser(context, node).parse(elements); + List specializations = new SpecializationMethodParser(context, node).parse(elements); - if (specializations == null || genericSpecializations == null || shortCircuits == null || listeners == null || guards == null) { - return null; + List allSpecializations = new ArrayList<>(); + allSpecializations.addAll(generics); + allSpecializations.addAll(specializations); + + node.setSpecializations(allSpecializations); + } + + private void finalizeSpecializations(final NodeData node) { + List specializations = new ArrayList<>(node.getSpecializations()); + + if (specializations.isEmpty()) { + return; + } + + List generics = new ArrayList<>(); + for (SpecializationData spec : specializations) { + if (spec.isGeneric()) { + generics.add(spec); + } + } + + if (generics.size() == 1 && specializations.size() == 1) { + for (SpecializationData generic : generics) { + generic.addError("@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName()); + } } SpecializationData genericSpecialization = null; - if (genericSpecializations.size() > 1) { - for (SpecializationData generic : genericSpecializations) { - log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName()); + if (generics.size() > 1) { + for (SpecializationData generic : generics) { + generic.addError("Only @%s is allowed per operation.", Generic.class.getSimpleName()); } - return null; - } else if (genericSpecializations.size() == 1) { - genericSpecialization = genericSpecializations.get(0); + return; + } else if (generics.size() == 1) { + genericSpecialization = generics.get(0); + } else if (node.needsRewrites(context)) { + SpecializationData specialization = specializations.get(0); + GenericParser parser = new GenericParser(context, node); + MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, null); + + ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context); + assert anyGenericReturnType != null; + + ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType().getPrimitiveType(), 0, false); + List parameters = new ArrayList<>(); + for (ActualParameter specializationParameter : specialization.getParameters()) { + ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName()); + NodeFieldData field = node.findField(parameterSpec.getName()); + TypeMirror actualType; + if (field == null) { + actualType = specializationParameter.getActualType(); + } else { + ExecutableTypeData paramType = field.getNodeData().findAnyGenericExecutableType(context); + assert paramType != null; + actualType = paramType.getType().getPrimitiveType(); + } + parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isHidden())); + } + TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); + genericSpecialization = new SpecializationData(genericMethod, true, false); + + specializations.add(genericSpecialization); } - if (specializations.size() > 1 && genericSpecialization == null) { - log.error(type, "Need a @%s method.", Generic.class.getSimpleName()); - return null; + if (genericSpecialization != null) { + CodeExecutableElement uninitializedMethod = new CodeExecutableElement(Utils.modifiers(Modifier.PUBLIC), context.getType(void.class), "doUninitialized"); + TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), uninitializedMethod, genericSpecialization.getMarkerAnnotation(), + genericSpecialization.getReturnType(), genericSpecialization.getParameters()); + specializations.add(new SpecializationData(uninializedMethod, false, true)); } Collections.sort(specializations, new Comparator() { @Override public int compare(SpecializationData o1, SpecializationData o2) { - return compareSpecialization(typeSystem, o1, o2); + return compareSpecialization(node.getTypeSystem(), o1, o2); } }); - List allSpecializations = new ArrayList<>(specializations); - if (genericSpecialization != null) { - allSpecializations.add(genericSpecialization); - CodeExecutableElement uninitializedMethod = new CodeExecutableElement(Utils.modifiers(Modifier.PUBLIC), context.getType(void.class), "doUninitialized"); - TemplateMethod uninializedMethod = new TemplateMethod(nodeData, genericSpecialization.getSpecification(), uninitializedMethod, genericSpecialization.getMarkerAnnotation(), - genericSpecialization.getReturnType(), genericSpecialization.getParameters()); - allSpecializations.add(0, new SpecializationData(uninializedMethod, false, true)); + node.setSpecializations(specializations); + + for (SpecializationData specialization : specializations) { + specialization.setId(findUniqueSpecializationId(specialization)); } + } - for (SpecializationData specialization : allSpecializations) { - specialization.setNode(nodeData); + private static String findUniqueSpecializationId(SpecializationData specialization) { + + String name; + if (specialization.isGeneric()) { + name = "Generic"; + } else if (specialization.isUninitialized()) { + name = "Uninitialized"; + } else { + List specializations = new ArrayList<>(specialization.getNode().getSpecializations()); + for (ListIterator iterator = specializations.listIterator(); iterator.hasNext();) { + SpecializationData data = iterator.next(); + if (data.isGeneric() || data.isUninitialized()) { + iterator.remove(); + } + } + + Map> usedIds = new HashMap<>(); + for (SpecializationData other : specializations) { + for (ActualParameter param : other.getReturnTypeAndParameters()) { + if (other.getNode().findField(param.getSpecification().getName()) == null) { + continue; + } + + Set types = usedIds.get(param.getSpecification()); + if (types == null) { + types = new HashSet<>(); + usedIds.put(param.getSpecification(), types); + } + types.add(Utils.getTypeId(param.getActualType())); + } + } + + List ambiguousSpecs = new ArrayList<>(); + for (ActualParameter param : specialization.getReturnTypeAndParameters()) { + Set ids = usedIds.get(param.getSpecification()); + if (ids != null && ids.size() > 1) { + ambiguousSpecs.add(param.getSpecification()); + } + } + + String specializationId = findSpecializationId(specialization, ambiguousSpecs); + int specializationIndex = 0; + int totalIndex = 0; + + for (SpecializationData other : specializations) { + String id = findSpecializationId(other, ambiguousSpecs); + if (id.equals(specializationId)) { + totalIndex++; + if (specialization == other) { + specializationIndex = totalIndex; + } + } + } + + if (specializationIndex != totalIndex) { + name = specializationId + specializationIndex; + } else { + name = specializationId; + } } + return name; + } - // verify order is not ambiguous - if (!verifySpecializationOrder(typeSystem, specializations)) { - return null; + private static String findSpecializationId(SpecializationData specialization, List specs) { + boolean allSame = true; + ActualParameter prevParam = specialization.getReturnType(); + for (ParameterSpec spec : specs) { + ActualParameter param = specialization.findParameter(spec); + if (!Utils.typeEquals(prevParam.getActualType(), param.getActualType())) { + allSame = false; + break; + } + prevParam = param; } - nodeData.setSpecializations(allSpecializations.toArray(new SpecializationData[allSpecializations.size()])); - nodeData.setSpecializationListeners(listeners.toArray(new TemplateMethod[listeners.size()])); + if (allSame) { + return Utils.getTypeId(prevParam.getActualType()); + } else { + StringBuilder nameBuilder = new StringBuilder(); + nameBuilder.append(Utils.getTypeId(prevParam.getActualType())); + for (ParameterSpec spec : specs) { + ActualParameter param = specialization.findParameter(spec); + nameBuilder.append(Utils.getTypeId(param.getActualType())); + } + return nameBuilder.toString(); + } + } - if (!verifyMissingAbstractMethods(nodeData, elements)) { - return null; - } + private void verifyNode(NodeData nodeData) { + // verify specialization parameter length + verifySpecializationParameters(nodeData); + + // verify order is not ambiguous + verifySpecializationOrder(nodeData); + + verifyMissingAbstractMethods(nodeData); + + assignShortCircuitsToSpecializations(nodeData); - if (!assignShortCircuitsToSpecializations(nodeData, allSpecializations, shortCircuits)) { - return null; - } + verifyConstructors(nodeData); + +// if (!verifyNamingConvention(specializations, "do")) { +// return null; +// } +// +// if (!verifyNamesUnique(specializations)) { +// return null; +// } + + verifyNamingConvention(nodeData.getShortCircuits(), "needs"); - if (!verifyConstructors(nodeData)) { - return null; + verifySpecializationThrows(nodeData); + } + + private NodeData parseNodeData(TypeElement templateType, TypeElement nodeType) { + List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeType)); + List typeHierarchy = findSuperClasses(new ArrayList(), nodeType); + Collections.reverse(typeHierarchy); + NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); + + AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); + if (typeSystemMirror == null) { + nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), nodeType.getQualifiedName().toString()); + return nodeData; } - if (!verifyNamingConvention(specializations, "do")) { - return null; - } - - if (!verifyNamesUnique(specializations)) { - return null; + TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value"); + final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); + if (typeSystem == null) { + nodeData.addError("The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); + return nodeData; } - if (!verifyNamingConvention(shortCircuits, "needs")) { - return null; - } + nodeData.setNodeType(nodeType.asType()); + nodeData.setTypeSystem(typeSystem); - if (!verifySpecializationThrows(typeSystem, specializations)) { - return null; - } + List executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); + nodeData.setExecutableTypes(executableTypes); + parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); + nodeData.setFields(parseFields(nodeData, elements, typeHierarchy)); return nodeData; } - private boolean verifyMissingAbstractMethods(NodeData nodeData, List elements) { - if (nodeData.needsFactory()) { + private static void verifySpecializationParameters(NodeData nodeData) { + boolean valid = true; + int args = -1; + for (SpecializationData specializationData : nodeData.getSpecializations()) { + int specializationArgs = 0; + for (ActualParameter param : specializationData.getParameters()) { + if (!param.getSpecification().isOptional()) { + specializationArgs++; + } + } + if (args != -1 && args != specializationArgs) { + valid = false; + break; + } + args = specializationArgs; + } + if (!valid) { + for (SpecializationData specialization : nodeData.getSpecializations()) { + specialization.addError("All specializations must have the same number of arguments."); + } + } + } + + private void verifyMissingAbstractMethods(NodeData nodeData) { + if (!nodeData.needsFactory()) { // missing abstract methods only needs to be implemented // if we need go generate factory for it. - return true; + return; } + List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeData.getTemplateType())); + Set unusedElements = new HashSet<>(elements); for (TemplateMethod method : nodeData.getAllTemplateMethods()) { unusedElements.remove(method.getMethod()); @@ -262,24 +519,20 @@ unusedElements.removeAll(nodeData.getExtensionElements()); } - boolean valid = true; for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { - context.getLog().error(nodeData.getTemplateType(), "The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), - Utils.getReadableSignature(unusedMethod)); - valid = false; + nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod)); } } + } + + private void verifyConstructors(NodeData nodeData) { + if (!nodeData.needsRewrites(context)) { + // no specialization constructor is needed if the node never rewrites. + return; + } - return valid; - } - - private boolean verifyConstructors(NodeData nodeData) { TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType()); - if (!nodeData.needsRewrites(context)) { - // no specialization constructor is needed if the node never rewrites. - return true; - } List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); for (ExecutableElement e : constructors) { @@ -287,20 +540,17 @@ TypeMirror firstArg = e.getParameters().get(0).asType(); if (Utils.typeEquals(firstArg, nodeData.getNodeType())) { if (e.getModifiers().contains(Modifier.PRIVATE)) { - context.getLog().error(e, "The specialization constructor must not be private."); - return false; + nodeData.addError("The specialization constructor must not be private."); } else if (constructors.size() <= 1) { - context.getLog().error(e, "The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); - return false; + nodeData.addError("The specialization constructor must not be the only constructor. The definition of an alternative constructor is required."); } - return true; + return; } } } // not found - context.getLog().error(type, "Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); - return false; + nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); } private static List filterExecutableTypes(List executableTypes) { @@ -347,13 +597,13 @@ return null; } - private NodeFieldData[] parseFields(NodeData nodeData, List elements, final List typeHierarchy) { + private List parseFields(NodeData nodeData, List elements, final List typeHierarchy) { AnnotationMirror executionOrderMirror = findFirstAnnotation(typeHierarchy, ExecuteChildren.class); List executionDefinition = null; if (executionOrderMirror != null) { executionDefinition = new ArrayList<>(); - for (Object object : Utils.getAnnotationValueList(executionOrderMirror, "value")) { - executionDefinition.add((String) object); + for (String object : Utils.getAnnotationValueList(String.class, executionOrderMirror, "value")) { + executionDefinition.add(object); } } @@ -361,12 +611,10 @@ for (ExecutableElement method : ElementFilter.methodsIn(elements)) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); if (mirror != null) { - shortCircuits.add(Utils.getAnnotationValueString(mirror, "value")); + shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); } } - boolean valid = true; - List fields = new ArrayList<>(); for (VariableElement var : ElementFilter.fieldsIn(elements)) { if (var.getModifiers().contains(Modifier.STATIC)) { @@ -380,23 +628,12 @@ } NodeFieldData field = parseField(nodeData, var, shortCircuits); - if (field != null) { - if (field.getExecutionKind() != ExecutionKind.IGNORE) { - fields.add(field); - } - } else { - valid = false; + if (field.getExecutionKind() != ExecutionKind.IGNORE) { + fields.add(field); } } - - // TODO parse getters - if (!valid) { - return null; - } - - NodeFieldData[] fieldArray = fields.toArray(new NodeFieldData[fields.size()]); - sortByExecutionOrder(fieldArray, executionDefinition == null ? Collections. emptyList() : executionDefinition, typeHierarchy); - return fieldArray; + sortByExecutionOrder(fields, executionDefinition == null ? Collections. emptyList() : executionDefinition, typeHierarchy); + return fields; } private NodeFieldData parseField(NodeData parentNodeData, VariableElement var, Set foundShortCircuits) { @@ -424,34 +661,29 @@ nodeType = getComponentType(var.asType()); kind = FieldKind.CHILDREN; } else { - mirror = null; + execution = ExecutionKind.IGNORE; nodeType = null; - kind = FieldKind.FIELD; - execution = ExecutionKind.IGNORE; + mirror = null; + kind = null; } - NodeData fieldNodeData = null; + NodeFieldData fieldData = new NodeFieldData(var, findAccessElement(var), mirror, kind, execution); if (nodeType != null) { - fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeType)); - Element errorElement = Utils.typeEquals(parentNodeData.getTemplateType().asType(), var.getEnclosingElement().asType()) ? var : parentNodeData.getTemplateType(); + NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(nodeType)); + fieldData.setNode(fieldNodeData); if (fieldNodeData == null) { - // TODO redirect errors from resolve. - context.getLog().error(errorElement, "Node type '%s' is invalid.", Utils.getQualifiedName(nodeType)); - return null; + fieldData.addError("Node type '%s' is invalid.", Utils.getQualifiedName(nodeType)); } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { - // TODO better error handling for (no or multiple?) - context.getLog().error(errorElement, "No executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType)); - return null; + fieldData.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType)); + } + + // TODO correct handling of access elements + if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) { + execution = ExecutionKind.IGNORE; } } - - // TODO correct handling of access elements - if (var.getModifiers().contains(Modifier.PRIVATE) && Utils.typeEquals(var.getEnclosingElement().asType(), parentNodeData.getTemplateType().asType())) { - execution = ExecutionKind.IGNORE; - } - - return new NodeFieldData(fieldNodeData, var, findAccessElement(var), mirror, kind, execution); + return fieldData; } private Element findAccessElement(VariableElement variableElement) { @@ -482,8 +714,8 @@ } } - private static void sortByExecutionOrder(NodeFieldData[] fields, final List executionOrder, final List typeHierarchy) { - Arrays.sort(fields, new Comparator() { + private static void sortByExecutionOrder(List fields, final List executionOrder, final List typeHierarchy) { + Collections.sort(fields, new Comparator() { @Override public int compare(NodeFieldData o1, NodeFieldData o2) { @@ -505,18 +737,16 @@ }); } - private boolean assignShortCircuitsToSpecializations(NodeData nodeData, List specializations, List shortCircuits) { - - Map> groupedShortCircuits = groupShortCircuits(shortCircuits); + private void assignShortCircuitsToSpecializations(NodeData node) { + Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); boolean valid = true; - - for (NodeFieldData field : nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) { + for (NodeFieldData field : node.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) { String valueName = field.getName(); List availableCircuits = groupedShortCircuits.get(valueName); if (availableCircuits == null || availableCircuits.isEmpty()) { - log.error(nodeData.getTemplateType(), "@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); + node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName); valid = false; continue; } @@ -531,7 +761,7 @@ if (!sameMethodName) { for (ShortCircuitData circuit : availableCircuits) { - log.error(circuit.getMethod(), circuit.getMarkerAnnotation(), "All short circuits for short cut value '%s' must have the same method name.", valueName); + circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName); } valid = false; continue; @@ -539,14 +769,14 @@ ShortCircuitData genericCircuit = null; for (ShortCircuitData circuit : availableCircuits) { - if (isGenericShortCutMethod(nodeData, circuit)) { + if (isGenericShortCutMethod(node, circuit)) { genericCircuit = circuit; break; } } if (genericCircuit == null) { - log.error(nodeData.getTemplateType(), "No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); + node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); valid = false; continue; } @@ -559,67 +789,48 @@ } if (!valid) { - return valid; + return; } - NodeFieldData[] fields = nodeData.filterFields(null, ExecutionKind.SHORT_CIRCUIT); - for (SpecializationData specialization : specializations) { - ShortCircuitData[] assignedShortCuts = new ShortCircuitData[fields.length]; + NodeFieldData[] fields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT); + for (SpecializationData specialization : node.getSpecializations()) { + List assignedShortCuts = new ArrayList<>(fields.length); for (int i = 0; i < fields.length; i++) { List availableShortCuts = groupedShortCircuits.get(fields[i].getName()); ShortCircuitData genericShortCircuit = null; + ShortCircuitData compatibleShortCircuit = null; for (ShortCircuitData circuit : availableShortCuts) { if (circuit.isGeneric()) { genericShortCircuit = circuit; } else if (circuit.isCompatibleTo(specialization)) { - assignedShortCuts[i] = circuit; + compatibleShortCircuit = circuit; } } - if (assignedShortCuts[i] == null) { - assignedShortCuts[i] = genericShortCircuit; + if (compatibleShortCircuit == null) { + compatibleShortCircuit = genericShortCircuit; } + assignedShortCuts.add(compatibleShortCircuit); } specialization.setShortCircuits(assignedShortCuts); } - return true; } - private boolean verifyNamingConvention(List methods, String prefix) { - boolean valid = true; + private static void verifyNamingConvention(List methods, String prefix) { for (int i = 0; i < methods.size(); i++) { TemplateMethod m1 = methods.get(i); if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Naming convention: method name must start with '%s'.", prefix); - valid = false; + m1.addError("Naming convention: method name must start with '%s'.", prefix); } } - return valid; - } - - private boolean verifyNamesUnique(List methods) { - boolean valid = true; - for (int i = 0; i < methods.size(); i++) { - TemplateMethod m1 = methods.get(i); - for (int j = i + 1; j < methods.size(); j++) { - TemplateMethod m2 = methods.get(j); - - if (m1.getMethodName().equalsIgnoreCase(m2.getMethodName())) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName()); - log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName()); - return false; - } - } - } - return valid; } private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { - for (NodeFieldData field : node.getFields()) { - ActualParameter parameter = method.findParameter(field.getName()); - if (parameter == null) { + for (ActualParameter parameter : method.getParameters()) { + NodeFieldData field = node.findField(parameter.getSpecification().getName()); + if (field == null) { continue; } ExecutableTypeData found = null; @@ -668,7 +879,10 @@ return collection; } - private boolean verifySpecializationOrder(TypeSystemData typeSystem, List specializations) { + private static void verifySpecializationOrder(NodeData node) { + TypeSystemData typeSystem = node.getTypeSystem(); + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size(); i++) { SpecializationData m1 = specializations.get(i); for (int j = i + 1; j < specializations.size(); j++) { @@ -678,56 +892,39 @@ if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { int specOrder = m1.getOrder() - m2.getOrder(); if (specOrder == 0) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder()); - log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder()); - return false; + m1.addError("Order value %d used multiple times", m1.getOrder()); + m2.addError("Order value %d used multiple times", m1.getOrder()); + return; } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) { - log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); - return false; + m1.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + m2.addError("Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + return; } } else if (inferredOrder == 0) { SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2); - log.error(m.getMethod(), m.getMarkerAnnotation(), "Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); - return false; + m.addError("Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); + return; } } } - return true; } - private boolean verifySpecializationThrows(TypeSystemData typeSystem, List specializations) { + private static void verifySpecializationThrows(NodeData node) { Map specializationMap = new HashMap<>(); - for (SpecializationData spec : specializations) { + for (SpecializationData spec : node.getSpecializations()) { specializationMap.put(spec.getMethodName(), spec); } - boolean valid = true; - for (SpecializationData sourceSpecialization : specializations) { + for (SpecializationData sourceSpecialization : node.getSpecializations()) { if (sourceSpecialization.getExceptions() != null) { for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) { - SpecializationData targetSpecialization = specializationMap.get(throwsData.getTransitionToName()); - AnnotationValue value = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "transitionTo"); - - if (targetSpecialization == null) { - log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value, "Specialization with name '%s' not found.", throwsData.getTransitionToName()); - valid = false; - } else if (compareSpecialization(typeSystem, sourceSpecialization, targetSpecialization) >= 0) { - log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value, - "The order of the target specializalization must be higher than the source specialization.", throwsData.getTransitionToName()); - valid = false; - } - for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) { if (otherThrowsData != throwsData && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) { - AnnotationValue javaClassValue = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "javaClass"); - log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), javaClassValue, "Duplicate exception type.", throwsData.getTransitionToName()); - valid = false; + throwsData.addError("Duplicate exception type."); } } } } } - return valid; } private static int compareSpecialization(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) { @@ -744,8 +941,22 @@ } private static int compareSpecializationWithoutOrder(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) { - if (m1.getSpecification() != m2.getSpecification()) { - throw new UnsupportedOperationException("Cannot compare two specializations with different specifications."); + if (m1 == m2) { + return 0; + } + + if (m1.isUninitialized() && !m2.isUninitialized()) { + return -1; + } else if (!m1.isUninitialized() && m2.isUninitialized()) { + return 1; + } else if (m1.isGeneric() && !m2.isGeneric()) { + return 1; + } else if (!m1.isGeneric() && m2.isGeneric()) { + return -1; + } + + if (m1.getTemplate() != m2.getTemplate()) { + throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); } int result = compareActualParameter(typeSystem, m1.getReturnType(), m2.getReturnType()); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Thu Mar 14 01:09:43 2013 +0100 @@ -61,8 +61,7 @@ } for (ActualParameter param : getParameters()) { - ParameterSpec paramSpec = param.getSpecification(); - ActualParameter specializationParam = specialization.findParameter(paramSpec.getName()); + ActualParameter specializationParam = specialization.findParameter(param.getName()); if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) { return false; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -48,14 +48,8 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - String shortCircuitValue = Utils.getAnnotationValueString(mirror, "value"); - - if (!shortCircuitValues.contains(shortCircuitValue)) { - getContext().getLog().error(method, mirror, "Invalid short circuit value %s.", shortCircuitValue); - return null; - } - - return createDefaultMethodSpec(shortCircuitValue); + String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); + return createDefaultMethodSpec(method, mirror, shortCircuitValue); } @Override @@ -65,9 +59,12 @@ @Override public ShortCircuitData create(TemplateMethod method) { - String shortCircuitValue = Utils.getAnnotationValueString(method.getMarkerAnnotation(), "value"); - assert shortCircuitValue != null; - assert shortCircuitValues.contains(shortCircuitValue); + String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value"); + + if (!shortCircuitValues.contains(shortCircuitValue)) { + method.addError("Invalid short circuit value %s.", shortCircuitValue); + } + return new ShortCircuitData(method, shortCircuitValue); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Thu Mar 14 01:09:43 2013 +0100 @@ -22,7 +22,10 @@ */ package com.oracle.truffle.codegen.processor.node; +import java.util.*; + import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.*; public class SpecializationData extends TemplateMethod { @@ -30,13 +33,13 @@ private final int order; private final boolean generic; private final boolean uninitialized; - private final SpecializationThrowsData[] exceptions; - private SpecializationGuardData[] guards; - private ShortCircuitData[] shortCircuits; + private final List exceptions; + private List guards; + private List shortCircuits; private boolean useSpecializationsForGeneric = true; private NodeData node; - public SpecializationData(TemplateMethod template, int order, SpecializationThrowsData[] exceptions) { + public SpecializationData(TemplateMethod template, int order, List exceptions) { super(template); this.order = order; this.generic = false; @@ -53,8 +56,40 @@ this.order = Specialization.DEFAULT_ORDER; this.generic = generic; this.uninitialized = uninitialized; - this.exceptions = new SpecializationThrowsData[0]; - this.guards = new SpecializationGuardData[0]; + this.exceptions = Collections.emptyList(); + this.guards = new ArrayList<>(); + } + + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (exceptions != null) { + sinks.addAll(exceptions); + } + if (guards != null) { + sinks.addAll(guards); + } + return sinks; + } + + public boolean hasRewrite(ProcessorContext context) { + if (!getExceptions().isEmpty()) { + return true; + } + if (!getGuards().isEmpty()) { + return true; + } + for (ActualParameter parameter : getParameters()) { + NodeFieldData field = getNode().findField(parameter.getSpecification().getName()); + if (field == null) { + continue; + } + ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getActualTypeData(field.getNodeData().getTypeSystem())); + if (type.hasUnexpectedValue(context)) { + return true; + } + } + return false; } public NodeData getNode() { @@ -65,7 +100,7 @@ this.node = node; } - public void setGuards(SpecializationGuardData[] guards) { + public void setGuards(List guards) { this.guards = guards; } @@ -81,19 +116,19 @@ return uninitialized; } - public SpecializationThrowsData[] getExceptions() { + public List getExceptions() { return exceptions; } - public SpecializationGuardData[] getGuards() { + public List getGuards() { return guards; } - public void setShortCircuits(ShortCircuitData[] shortCircuits) { + public void setShortCircuits(List shortCircuits) { this.shortCircuits = shortCircuits; } - public ShortCircuitData[] getShortCircuits() { + public List getShortCircuits() { return shortCircuits; } @@ -106,10 +141,10 @@ } public SpecializationData findNextSpecialization() { - SpecializationData[] specializations = node.getSpecializations(); - for (int i = 0; i < specializations.length - 1; i++) { - if (specializations[i] == this) { - return specializations[i + 1]; + List specializations = node.getSpecializations(); + for (int i = 0; i < specializations.size() - 1; i++) { + if (specializations.get(i) == this) { + return specializations.get(i + 1); } } return null; diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationGuardData.java Thu Mar 14 01:09:43 2013 +0100 @@ -22,20 +22,42 @@ */ package com.oracle.truffle.codegen.processor.node; +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; -public class SpecializationGuardData { +public class SpecializationGuardData extends MessageContainer { + private final SpecializationData specialization; + private final AnnotationValue value; private final String guardMethod; private final boolean onSpecialization; private final boolean onExecution; private GuardData guardDeclaration; - public SpecializationGuardData(String guardMethod, boolean onSpecialization, boolean onExecution) { + public SpecializationGuardData(SpecializationData specialization, AnnotationValue value, String guardMethod, boolean onSpecialization, boolean onExecution) { + this.specialization = specialization; this.guardMethod = guardMethod; this.onSpecialization = onSpecialization; this.onExecution = onExecution; + this.value = value; + } + + @Override + public Element getMessageElement() { + return specialization.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return specialization.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return value; } public String getGuardMethod() { diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerData.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,33 @@ +/* + * 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.codegen.processor.node; + +import com.oracle.truffle.codegen.processor.template.*; + +public class SpecializationListenerData extends TemplateMethod { + + public SpecializationListenerData(TemplateMethod method) { + super(method); + } + +} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -30,18 +30,15 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.*; -public class SpecializationListenerParser extends MethodParser { - - private final MethodSpec specification; +public class SpecializationListenerParser extends MethodParser { public SpecializationListenerParser(ProcessorContext context, NodeData node) { super(context, node); - this.specification = createDefaultMethodSpec(null); } @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return specification; + return createDefaultMethodSpec(method, mirror, null); } @Override @@ -50,8 +47,8 @@ } @Override - public TemplateMethod create(TemplateMethod method) { - return method; + public SpecializationListenerData create(TemplateMethod method) { + return new SpecializationListenerData(method); } @Override diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -35,16 +35,13 @@ public class SpecializationMethodParser extends MethodParser { - private final MethodSpec specification; - public SpecializationMethodParser(ProcessorContext context, NodeData operation) { super(context, operation); - this.specification = createDefaultMethodSpec(null); } @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return specification; + return createDefaultMethodSpec(method, mirror, null); } @Override @@ -58,27 +55,24 @@ } private SpecializationData parseSpecialization(TemplateMethod method) { - int order = Utils.getAnnotationValueInt(method.getMarkerAnnotation(), "order"); + int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order"); if (order < 0 && order != Specialization.DEFAULT_ORDER) { - getContext().getLog().error(method.getMethod(), method.getMarkerAnnotation(), "Invalid order attribute %d. The value must be >= 0 or the default value."); + method.addError("Invalid order attribute %d. The value must be >= 0 or the default value."); return null; } - List exceptionDefs = Utils.collectAnnotations(getContext(), method.getMarkerAnnotation(), "exceptions", method.getMethod(), SpecializationThrows.class); - SpecializationThrowsData[] exceptionData = new SpecializationThrowsData[exceptionDefs.size()]; - for (int i = 0; i < exceptionData.length; i++) { - AnnotationMirror mirror = exceptionDefs.get(i); - TypeMirror javaClass = Utils.getAnnotationValueType(mirror, "javaClass"); - String transitionTo = Utils.getAnnotationValueString(mirror, "transitionTo"); - exceptionData[i] = new SpecializationThrowsData(mirror, javaClass, transitionTo); - - if (!Utils.canThrowType(method.getMethod().getThrownTypes(), javaClass)) { - getContext().getLog().error(method.getMethod(), "Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(javaClass)); - return null; + AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); + List exceptionTypes = Utils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn"); + List exceptionData = new ArrayList<>(); + for (TypeMirror exceptionType : exceptionTypes) { + SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType); + if (!Utils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) { + throwsData.addError("Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(exceptionType)); } + exceptionData.add(throwsData); } - Arrays.sort(exceptionData, new Comparator() { + Collections.sort(exceptionData, new Comparator() { @Override public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) { @@ -87,26 +81,19 @@ }); SpecializationData specialization = new SpecializationData(method, order, exceptionData); boolean valid = true; - List guardDefs = Utils.collectAnnotations(getContext(), method.getMarkerAnnotation(), "guards", method.getMethod(), SpecializationGuard.class); - SpecializationGuardData[] guardData = new SpecializationGuardData[guardDefs.size()]; - for (int i = 0; i < guardData.length; i++) { - AnnotationMirror guardMirror = guardDefs.get(i); - String guardMethod = Utils.getAnnotationValueString(guardMirror, "methodName"); - boolean onSpecialization = Utils.getAnnotationValueBoolean(guardMirror, "onSpecialization"); - boolean onExecution = Utils.getAnnotationValueBoolean(guardMirror, "onExecution"); + AnnotationValue guardsValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "guards"); + List guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards"); + List guardData = new ArrayList<>(guardDefs.size()); + for (int i = 0; i < guardDefs.size(); i++) { + String guardMethod = guardDefs.get(i); - if (!onSpecialization && !onExecution) { - String message = "Either onSpecialization, onExecution or both must be enabled."; - getContext().getLog().error(method.getMethod(), guardMirror, message); - valid = false; - continue; - } + SpecializationGuardData assignedGuard = new SpecializationGuardData(specialization, guardsValue, guardMethod, true, true); + + guardData.add(assignedGuard); - guardData[i] = new SpecializationGuardData(guardMethod, onSpecialization, onExecution); - - GuardData compatibleGuard = matchSpecializationGuard(guardMirror, specialization, guardData[i]); + GuardData compatibleGuard = matchSpecializationGuard(specialization, assignedGuard); if (compatibleGuard != null) { - guardData[i].setGuardDeclaration(compatibleGuard); + assignedGuard.setGuardDeclaration(compatibleGuard); } else { valid = false; } @@ -121,7 +108,7 @@ return specialization; } - private GuardData matchSpecializationGuard(AnnotationMirror mirror, SpecializationData specialization, SpecializationGuardData specializationGuard) { + private GuardData matchSpecializationGuard(SpecializationData specialization, SpecializationGuardData specializationGuard) { List foundGuards = getNode().findGuards(specializationGuard.getGuardMethod()); GuardData compatibleGuard = null; @@ -142,16 +129,14 @@ } List typeDefs = createTypeDefinitions(returnTypeSpec, expectedParameterSpecs); String expectedSignature = TemplateMethodParser.createExpectedSignature(specializationGuard.getGuardMethod(), returnTypeSpec, expectedParameterSpecs, typeDefs); - AnnotationValue value = Utils.getAnnotationValue(mirror, "methodName"); - getContext().getLog().error(specialization.getMethod(), mirror, value, "No guard with signature '%s' found in type system.", expectedSignature); - return null; + specializationGuard.addError("No guard with signature '%s' found in type system.", expectedSignature); } return compatibleGuard; } private static boolean isGuardCompatible(SpecializationData specialization, GuardData guard) { - Iterator guardParameters = Arrays.asList(guard.getParameters()).iterator(); + Iterator guardParameters = guard.getParameters().iterator(); for (ActualParameter param : specialization.getParameters()) { if (param.getSpecification().isOptional()) { continue; diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationThrowsData.java Thu Mar 14 01:09:43 2013 +0100 @@ -25,23 +25,40 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; -public class SpecializationThrowsData { +import com.oracle.truffle.codegen.processor.template.*; +public class SpecializationThrowsData extends MessageContainer { + + private final AnnotationValue annotationValue; private final AnnotationMirror annotationMirror; private final TypeMirror javaClass; - private final String transitionTo; private SpecializationData specialization; - public SpecializationThrowsData(AnnotationMirror annotationMirror, TypeMirror javaClass, String transitionTo) { + public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) { this.annotationMirror = annotationMirror; + this.annotationValue = value; this.javaClass = javaClass; - this.transitionTo = transitionTo; } void setSpecialization(SpecializationData specialization) { this.specialization = specialization; } + @Override + public Element getMessageElement() { + return specialization.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return annotationMirror; + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + public TypeMirror getJavaClass() { return javaClass; } @@ -54,16 +71,7 @@ return annotationMirror; } - public String getTransitionToName() { - return transitionTo; - } - public SpecializationData getTransitionTo() { - for (SpecializationData s : specialization.getNode().getSpecializations()) { - if (s.getMethodName().equals(transitionTo)) { - return s; - } - } - return null; + return specialization.findNextSpecialization(); } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Thu Mar 14 01:09:43 2013 +0100 @@ -31,10 +31,33 @@ private final ParameterSpec specification; private final TypeMirror actualType; private TemplateMethod method; + private final String name; + private final int index; + private final boolean implicit; - public ActualParameter(ParameterSpec specification, TypeMirror actualType) { + public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index, boolean implicit) { this.specification = specification; this.actualType = actualType; + + this.index = index; + this.implicit = implicit; + String valueName = specification.getName() + "Value"; + if (specification.isIndexed()) { + valueName = valueName + index; + } + this.name = valueName; + } + + public boolean isHidden() { + return implicit; + } + + public int getIndex() { + return index; + } + + public String getName() { + return name; } void setMethod(TemplateMethod method) { diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Thu Mar 14 01:09:43 2013 +0100 @@ -128,6 +128,10 @@ CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class)); generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType())); + if (model.getTemplateMethodName() != null) { + generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName())); + } + clazz.addAnnotationMirror(generatedByAnnotation); context.registerType(model.getTemplateType(), clazz.asType()); diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java Thu Mar 14 01:09:43 2013 +0100 @@ -0,0 +1,180 @@ +/* + * 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.codegen.processor.template; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.codegen.processor.*; + +public abstract class MessageContainer { + + private final List messages = new ArrayList<>(); + + public final void addWarning(String text, Object... params) { + getMessages().add(new Message(this, String.format(text, params), Kind.WARNING)); + } + + public final void addError(String text, Object... params) { + getMessages().add(new Message(this, String.format(text, params), Kind.ERROR)); + } + + protected List findChildContainers() { + return Collections.emptyList(); + } + + public abstract Element getMessageElement(); + + public final void emitMessages(TypeElement baseElement, Log log) { + emitMessagesImpl(baseElement, log, new HashSet()); + } + + private void emitMessagesImpl(TypeElement baseElement, Log log, Set visitedSinks) { + for (Message message : getMessages()) { + emitDefault(baseElement, log, message); + } + + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + return; + } + + visitedSinks.add(sink); + sink.emitMessagesImpl(baseElement, log, visitedSinks); + } + } + + private void emitDefault(TypeElement baseType, Log log, Message message) { + if (Utils.typeEquals(baseType.asType(), Utils.findRootEnclosingType(getMessageElement()).asType()) && this == message.getOriginalContainer()) { + log.message(message.getKind(), getMessageElement(), getMessageAnnotation(), getMessageAnnotationValue(), message.getText()); + } else { + MessageContainer original = message.getOriginalContainer(); + log.message(message.getKind(), baseType, null, null, wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText())); + } + } + + private static String wrapText(Element element, AnnotationMirror mirror, String text) { + StringBuilder b = new StringBuilder(); + if (element != null) { + b.append("Element " + element.toString()); + } + if (mirror != null) { + b.append(" at annotation @" + Utils.getSimpleName(mirror.getAnnotationType())); + } + + if (b.length() > 0) { + b.append(" is erroneous: ").append(text); + return b.toString(); + } else { + return text; + } + } + + public AnnotationMirror getMessageAnnotation() { + return null; + } + + public AnnotationValue getMessageAnnotationValue() { + return null; + } + + public final boolean hasErrors() { + return hasErrorsImpl(new HashSet()); + } + + public final List collectMessages() { + List collectedMessages = new ArrayList<>(); + collectMessagesImpl(collectedMessages, new HashSet()); + return collectedMessages; + } + + private void collectMessagesImpl(List collectedMessages, Set visitedSinks) { + collectedMessages.addAll(getMessages()); + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + return; + } + + visitedSinks.add(sink); + sink.collectMessagesImpl(collectedMessages, visitedSinks); + } + } + + private boolean hasErrorsImpl(Set visitedSinks) { + for (Message msg : getMessages()) { + if (msg.getKind() == Kind.ERROR) { + return true; + } + } + for (MessageContainer sink : findChildContainers()) { + if (visitedSinks.contains(sink)) { + return false; + } + + visitedSinks.add(sink); + + if (sink.hasErrorsImpl(visitedSinks)) { + return true; + } + } + return false; + } + + public List getMessages() { + return messages; + } + + public static final class Message { + + private final MessageContainer originalContainer; + private final String text; + private final Kind kind; + + public Message(MessageContainer originalContainer, String text, Kind kind) { + this.originalContainer = originalContainer; + this.text = text; + this.kind = kind; + } + + public MessageContainer getOriginalContainer() { + return originalContainer; + } + + public String getText() { + return text; + } + + public Kind getKind() { + return kind; + } + + @Override + public String toString() { + return kind + ": " + text; + } + + } + +} diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Thu Mar 14 01:09:43 2013 +0100 @@ -24,16 +24,25 @@ import java.util.*; +import javax.lang.model.type.*; + public class MethodSpec { + private final List implicitTypes; + private final ParameterSpec returnType; private final List parameters; - public MethodSpec(ParameterSpec returnType, List parameters) { + public MethodSpec(List prefixTypes, ParameterSpec returnType, List parameters) { + this.implicitTypes = prefixTypes; this.returnType = returnType; this.parameters = parameters; } + public List getImplicitTypes() { + return implicitTypes; + } + public ParameterSpec getReturnType() { return returnType; } @@ -41,4 +50,14 @@ public List getParameters() { return parameters; } + + public ParameterSpec findParameterSpec(String name) { + for (ParameterSpec spec : parameters) { + if (spec.getName().equals(name)) { + return spec; + } + } + return null; + } + } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Thu Mar 14 01:09:43 2013 +0100 @@ -37,11 +37,12 @@ } private final String name; - private final TypeMirror[] allowedTypes; + private final List allowedTypes; private final boolean optional; - private final Cardinality cardinality; + private Cardinality cardinality; + private boolean indexed; - public ParameterSpec(String name, TypeMirror[] allowedTypes, boolean optional, Cardinality cardinality) { + public ParameterSpec(String name, List allowedTypes, boolean optional, Cardinality cardinality) { this.allowedTypes = allowedTypes; this.name = name; this.optional = optional; @@ -50,7 +51,7 @@ /** Type constructor. */ public ParameterSpec(String name, TypeMirror singleFixedType, boolean optional) { - this(name, new TypeMirror[]{singleFixedType}, optional, Cardinality.ONE); + this(name, Arrays.asList(singleFixedType), optional, Cardinality.ONE); } /** Type system value constructor. */ @@ -63,7 +64,19 @@ this(name, nodeTypeMirrors(nodeData), optional, cardinality); } - private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) { + public boolean isIndexed() { + return indexed; + } + + public void setIndexed(boolean indexed) { + this.indexed = indexed; + } + + public void setCardinality(Cardinality cardinality) { + this.cardinality = cardinality; + } + + private static List nodeTypeMirrors(NodeData nodeData) { Set typeMirrors = new LinkedHashSet<>(); for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { @@ -72,7 +85,7 @@ typeMirrors.add(nodeData.getTypeSystem().getGenericType()); - return typeMirrors.toArray(new TypeMirror[typeMirrors.size()]); + return new ArrayList<>(typeMirrors); } public final String getName() { @@ -87,13 +100,12 @@ return cardinality; } - public TypeMirror[] getAllowedTypes() { + public List getAllowedTypes() { return allowedTypes; } public boolean matches(TypeMirror actualType) { - for (int i = 0; i < allowedTypes.length; i++) { - TypeMirror mirror = allowedTypes[i]; + for (TypeMirror mirror : allowedTypes) { if (Utils.typeEquals(actualType, mirror)) { return true; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java Thu Mar 14 01:09:43 2013 +0100 @@ -29,18 +29,34 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.api.element.*; -public abstract class Template { +public abstract class Template extends MessageContainer { private final TypeElement templateType; + private final String templateMethodName; private final AnnotationMirror annotation; private List extensionElements; - public Template(TypeElement templateType, AnnotationMirror annotation) { + public Template(TypeElement templateType, String templateMethodName, AnnotationMirror annotation) { this.templateType = templateType; + this.templateMethodName = templateMethodName; this.annotation = annotation; } + @Override + public Element getMessageElement() { + return templateType; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); + } + + public String getTemplateMethodName() { + return templateMethodName; + } + public TypeElement getTemplateType() { return templateType; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Thu Mar 14 01:09:43 2013 +0100 @@ -22,24 +22,32 @@ */ package com.oracle.truffle.codegen.processor.template; +import java.util.*; + import javax.lang.model.element.*; +import javax.lang.model.type.*; -public class TemplateMethod { +import com.oracle.truffle.codegen.processor.*; +public class TemplateMethod extends MessageContainer { + + private String id; private final Template template; private final MethodSpec specification; private final ExecutableElement method; private final AnnotationMirror markerAnnotation; private final ActualParameter returnType; - private final ActualParameter[] parameters; + private final List parameters; - public TemplateMethod(Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, ActualParameter[] parameters) { + public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, + List parameters) { this.template = template; this.specification = specification; this.method = method; this.markerAnnotation = markerAnnotation; this.returnType = returnType; this.parameters = parameters; + this.id = id; if (parameters != null) { for (ActualParameter param : parameters) { @@ -49,7 +57,31 @@ } public TemplateMethod(TemplateMethod method) { - this(method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); + this(method.id, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); + getMessages().addAll(method.getMessages()); + } + + @Override + public Element getMessageElement() { + return method; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return markerAnnotation; + } + + @Override + protected List findChildContainers() { + return Collections.emptyList(); + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; } public Template getTemplate() { @@ -64,34 +96,50 @@ return returnType; } - public ActualParameter[] getParameters() { + public List getParameters() { return parameters; } public ActualParameter findParameter(String valueName) { for (ActualParameter param : getParameters()) { - if (param.getSpecification().getName().equals(valueName)) { + if (param.getName().equals(valueName)) { return param; } } return null; } + public List getReturnTypeAndParameters() { + List allParameters = new ArrayList<>(getParameters().size() + 1); + allParameters.add(getReturnType()); + allParameters.addAll(getParameters()); + return Collections.unmodifiableList(allParameters); + } + public ActualParameter findParameter(ParameterSpec spec) { for (ActualParameter param : getParameters()) { - if (param.getSpecification() == spec) { + if (param.getSpecification().getName().equals(spec.getName())) { return param; } } return null; } + public boolean canBeAccessedByInstanceOf(TypeMirror type) { + TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType(); + return Utils.isAssignable(type, methodType) || Utils.isAssignable(methodType, type); + } + public ExecutableElement getMethod() { return method; } public String getMethodName() { - return getMethod().getSimpleName().toString(); + if (getMethod() != null) { + return getMethod().getSimpleName().toString(); + } else { + return "$synthetic"; + } } public AnnotationMirror getMarkerAnnotation() { @@ -100,7 +148,7 @@ @Override public String toString() { - return getClass().getSimpleName() + " [method = " + method + "]"; + return "id = " + getId() + ", " + getClass().getSimpleName() + " [method = " + getMethod() + "]"; } public ActualParameter getPreviousParam(ActualParameter searchParam) { diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -31,6 +31,7 @@ import javax.lang.model.type.*; import javax.lang.model.util.*; +import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; @@ -95,13 +96,14 @@ mirror = Utils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType); } - if (method.getModifiers().contains(Modifier.PRIVATE)) { - getContext().getLog().error(method, "Method must not be private."); + E parsedMethod = parse(method, mirror); + + if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) { + parsedMethod.addError("Method must not be private."); valid = false; continue; } - E parsedMethod = parse(method, mirror); if (parsedMethod != null) { parsedMethods.add(parsedMethod); } else { @@ -120,108 +122,126 @@ return null; } + String id = method.getSimpleName().toString(); + AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class); + if (idAnnotation != null) { + id = Utils.getAnnotationValue(String.class, idAnnotation, "value"); + } + List typeDefs = createTypeDefinitions(methodSpecification.getReturnType(), methodSpecification.getParameters()); ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); List parameterSpecs = new ArrayList<>(); parameterSpecs.addAll(methodSpecification.getParameters()); - ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template); + ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); if (returnTypeMirror == null) { - if (isEmitErrors()) { + if (emitErrors) { + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true); String actualReturnType = Utils.getSimpleName(method.getReturnType()); String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; + } + } - context.getLog().error(method, annotation, message); + List parameterTypes = new ArrayList<>(); + parameterTypes.addAll(methodSpecification.getImplicitTypes()); + for (VariableElement var : method.getParameters()) { + parameterTypes.add(var.asType()); + } + + List parameters = parseParameters(parameterTypes, parameterSpecs, methodSpecification.getImplicitTypes().size()); + if (parameters == null) { + if (isEmitErrors()) { + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); + String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), + createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); + invalidMethod.addError(message); + return invalidMethod; + } else { + return null; } - return null; } - Iterator variableIterator = method.getParameters().iterator(); + return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters)); + } + + private static String createActualSignature(MethodSpec spec, ExecutableElement method) { + List types = new ArrayList<>(); + for (TypeMirror implicitType : spec.getImplicitTypes()) { + types.add("implicit " + Utils.getSimpleName(implicitType)); + } + for (VariableElement var : method.getParameters()) { + types.add(Utils.getSimpleName(var.asType())); + } + + StringBuilder b = new StringBuilder("("); + for (Iterator iterator = types.iterator(); iterator.hasNext();) { + b.append(iterator.next()); + if (iterator.hasNext()) { + b.append(", "); + } + } + b.append(")"); + return b.toString(); + } + + private List parseParameters(List types, List parameterSpecs, int hiddenCount) { + Iterator parameterIterator = types.iterator(); Iterator specificationIterator = parameterSpecs.iterator(); - List resolvedMirrors = new ArrayList<>(); - VariableElement parameter = null; - ParameterSpec specification = null; - while (specificationIterator.hasNext() || specification != null) { - if (specification == null) { - specification = specificationIterator.next(); - } - - if (parameter == null && variableIterator.hasNext()) { - parameter = variableIterator.next(); - } - - if (parameter == null) { - if (specification.getCardinality() == Cardinality.MULTIPLE) { - specification = null; - continue; - } else if (!specification.isOptional()) { - if (isEmitErrors()) { - // non option type specification found -> argument missing - String expectedType = createTypeSignature(specification, typeDefs, false); - - String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType, - createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); + TypeMirror parameter = parameterIterator.hasNext() ? parameterIterator.next() : null; + ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null; - context.getLog().error(method, message); - } - return null; - } else { - // specification is optional -> continue - specification = null; + int globalParameterIndex = 0; + int specificationParameterIndex = 0; + List resolvedParameters = new ArrayList<>(); + while (parameter != null || specification != null) { + if (parameter == null || specification == null) { + if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) { + specification = specificationIterator.hasNext() ? specificationIterator.next() : null; + specificationParameterIndex = 0; continue; } - } - - ActualParameter resolvedMirror = resolveTypeMirror(specification, parameter.asType(), template); - - if (resolvedMirror == null) { - if (specification.isOptional()) { - specification = null; - continue; - } - - if (isEmitErrors()) { - String expectedReturnType = createTypeSignature(specification, typeDefs, false); - String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName(); - - String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, - createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); - - context.getLog().error(parameter, message); - } return null; } - resolvedMirrors.add(resolvedMirror); - parameter = null; // consume parameter + boolean hidden = globalParameterIndex < hiddenCount; + ActualParameter resolvedParameter = matchParameter(specification, parameter, template, specificationParameterIndex, hidden); + if (resolvedParameter == null) { + // mismatch + if (specification.isOptional()) { + specification = specificationIterator.hasNext() ? specificationIterator.next() : null; + specificationParameterIndex = 0; + } else { + return null; + } + } else { + resolvedParameters.add(resolvedParameter); - if (specification.getCardinality() != Cardinality.MULTIPLE) { - specification = null; + // match + if (specification.getCardinality() == Cardinality.ONE) { + parameter = parameterIterator.hasNext() ? parameterIterator.next() : null; + specification = specificationIterator.hasNext() ? specificationIterator.next() : null; + globalParameterIndex++; + specificationParameterIndex = 0; + } else if (specification.getCardinality() == Cardinality.MULTIPLE) { + parameter = parameterIterator.hasNext() ? parameterIterator.next() : null; + globalParameterIndex++; + specificationParameterIndex++; + } } } - - if (variableIterator.hasNext()) { - parameter = variableIterator.next(); - if (isEmitErrors()) { - String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName(); - String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType, - createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs)); - - context.getLog().error(parameter, message); - } - return null; - } - - ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]); - return create(new TemplateMethod(template, methodSpecification, method, annotation, returnTypeMirror, paramMirrors)); + return resolvedParameters; } - private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) { + private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean hidden) { TypeMirror resolvedType = mirror; if (hasError(resolvedType)) { resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem); @@ -230,7 +250,7 @@ if (!specification.matches(resolvedType)) { return null; } - return new ActualParameter(specification, resolvedType); + return new ActualParameter(specification, resolvedType, index, hidden); } protected List createTypeDefinitions(ParameterSpec returnType, List parameters) { @@ -242,12 +262,12 @@ int defIndex = 0; for (ParameterSpec spec : allParams) { - TypeMirror[] allowedTypes = spec.getAllowedTypes(); - TypeMirror[] types = spec.getAllowedTypes(); - if (types != null && allowedTypes.length > 1) { + List allowedTypes = spec.getAllowedTypes(); + List types = spec.getAllowedTypes(); + if (types != null && allowedTypes.size() > 1) { TypeDef foundDef = null; for (TypeDef def : typeDefs) { - if (Arrays.equals(allowedTypes, def.getTypes())) { + if (allowedTypes.equals(def.getTypes())) { foundDef = def; break; } @@ -267,11 +287,11 @@ protected static class TypeDef { - private final TypeMirror[] types; + private final List types; private final String name; private final List parameters = new ArrayList<>(); - public TypeDef(TypeMirror[] types, String name) { + public TypeDef(List types, String name) { this.types = types; this.name = name; } @@ -280,7 +300,7 @@ return parameters; } - public TypeMirror[] getTypes() { + public List getTypes() { return types; } @@ -349,7 +369,7 @@ private static String createTypeSignature(ParameterSpec spec, List typeDefs, boolean typeOnly) { StringBuilder builder = new StringBuilder(); - if (spec.getAllowedTypes().length > 1) { + if (spec.getAllowedTypes().size() > 1) { TypeDef foundTypeDef = null; for (TypeDef typeDef : typeDefs) { if (typeDef.getParameters().contains(spec)) { @@ -360,8 +380,8 @@ if (foundTypeDef != null) { builder.append("<" + foundTypeDef.getName() + ">"); } - } else if (spec.getAllowedTypes().length == 1) { - builder.append(Utils.getSimpleName(spec.getAllowedTypes()[0])); + } else if (spec.getAllowedTypes().size() == 1) { + builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0))); } else { builder.append("void"); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -43,9 +43,8 @@ return extensionParser; } - protected boolean verifyExclusiveMethodAnnotation(TypeElement type, Class... annotationTypes) { - boolean valid = true; - List methods = ElementFilter.methodsIn(type.getEnclosedElements()); + protected void verifyExclusiveMethodAnnotation(Template template, Class... annotationTypes) { + List methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements()); for (ExecutableElement method : methods) { List foundAnnotations = new ArrayList<>(); for (int i = 0; i < annotationTypes.length; i++) { @@ -61,34 +60,9 @@ annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType())); } - for (AnnotationMirror mirror : foundAnnotations) { - context.getLog().error(method, mirror, "Non exclusive usage of annotations %s.", annotationNames); - } - valid = false; + template.addError("Non exclusive usage of annotations %s.", annotationNames); } } - return valid; - } - - protected boolean verifyTemplateType(TypeElement template, AnnotationMirror annotation) { - // annotation type on class path!? - boolean valid = true; - TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); - if (annotationTypeElement == null) { - log.error(template, annotation, "Required class " + getAnnotationType().getName() + " is not on the classpath."); - valid = false; - } - if (template.getModifiers().contains(Modifier.PRIVATE)) { - log.error(template, annotation, "The annotated class must have at least package protected visibility."); - valid = false; - } - - if (template.getModifiers().contains(Modifier.FINAL)) { - log.error(template, annotation, "The annotated class must not be final."); - valid = false; - } - - return valid; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Thu Mar 14 01:09:43 2013 +0100 @@ -26,15 +26,8 @@ public class GuardData extends TemplateMethod { - private final Template origin; - - public GuardData(TemplateMethod method, Template origin) { + public GuardData(TemplateMethod method) { super(method); - this.origin = origin; - } - - public Template getOrigin() { - return origin; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -26,8 +26,8 @@ import java.util.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; -import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; @@ -39,6 +39,8 @@ public GuardParser(ProcessorContext context, Template template, TypeSystemData typeSystem) { super(context, template); this.typeSystem = typeSystem; + setEmitErrors(false); + setParseNullOnError(false); } @Override @@ -46,22 +48,22 @@ List specs = new ArrayList<>(); specs.add(new ParameterSpec("valueN", typeSystem, false, Cardinality.MULTIPLE)); ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), false); - return new MethodSpec(returnTypeSpec, specs); + return new MethodSpec(Collections. emptyList(), returnTypeSpec, specs); } @Override public boolean isParsable(ExecutableElement method) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + return true; } @Override public GuardData create(TemplateMethod method) { - return new GuardData(method, template); + return new GuardData(method); } @Override public Class getAnnotationType() { - return GuardCheck.class; + return null; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -26,6 +26,7 @@ import java.util.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; @@ -40,21 +41,21 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method, mirror, "as"); + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "as"); if (targetType == null) { return null; } List specs = new ArrayList<>(); specs.add(new ParameterSpec("value", getTypeSystem(), false, Cardinality.ONE)); ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType(), false); - MethodSpec spec = new MethodSpec(returnTypeSpec, specs); + MethodSpec spec = new MethodSpec(Collections. emptyList(), returnTypeSpec, specs); return spec; } @Override public TypeCastData create(TemplateMethod method) { - TypeData targetType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "as"); - ActualParameter parameter = method.findParameter("value"); + TypeData targetType = findTypeByMethodName(method, "as"); + ActualParameter parameter = method.findParameter("valueValue"); return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -26,6 +26,7 @@ import java.util.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; @@ -40,22 +41,22 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - TypeData targetType = findTypeByMethodName(method, mirror, "is"); + TypeData targetType = findTypeByMethodName(method.getSimpleName().toString(), "is"); if (targetType == null) { return null; } List specs = new ArrayList<>(); specs.add(new ParameterSpec("value", getTypeSystem(), false, Cardinality.ONE)); ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), false); - MethodSpec spec = new MethodSpec(returnTypeSpec, specs); + MethodSpec spec = new MethodSpec(Collections. emptyList(), returnTypeSpec, specs); return spec; } @Override public TypeCheckData create(TemplateMethod method) { - TypeData checkedType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "is"); + TypeData checkedType = findTypeByMethodName(method, "is"); assert checkedType != null; - ActualParameter parameter = method.findParameter("value"); + ActualParameter parameter = method.findParameter("valueValue"); assert parameter != null; return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem())); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Thu Mar 14 01:09:43 2013 +0100 @@ -30,21 +30,38 @@ import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.*; -public class TypeData extends Template { +public class TypeData extends MessageContainer { - protected TypeSystemData typeSystem; + private final TypeSystemData typeSystem; + private final AnnotationValue annotationValue; private final TypeMirror primitiveType; private final TypeMirror boxedType; private final List typeCasts = new ArrayList<>(); private final List typeChecks = new ArrayList<>(); - public TypeData(TypeElement templateType, AnnotationMirror annotation, TypeMirror primitiveType, TypeMirror boxedType) { - super(templateType, annotation); + public TypeData(TypeSystemData typeSystem, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) { + this.typeSystem = typeSystem; + this.annotationValue = value; this.primitiveType = primitiveType; this.boxedType = boxedType; } + @Override + public Element getMessageElement() { + return typeSystem.getMessageElement(); + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return typeSystem.getMessageAnnotation(); + } + + @Override + public AnnotationValue getMessageAnnotationValue() { + return annotationValue; + } + void addTypeCast(TypeCastData typeCast) { this.typeCasts.add(typeCast); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Thu Mar 14 01:09:43 2013 +0100 @@ -167,8 +167,8 @@ CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); - if (typeSystem.getTypes().length > 0) { - builder.typeLiteral(typeSystem.getTypes()[0].getBoxedType()); + if (!typeSystem.getTypes().isEmpty()) { + builder.typeLiteral(typeSystem.getTypes().get(0).getBoxedType()); } else { builder.null_(); } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java Thu Mar 14 01:09:43 2013 +0100 @@ -32,35 +32,42 @@ public class TypeSystemData extends Template { - private final TypeData[] types; - private final TypeMirror[] primitiveTypeMirrors; - private final TypeMirror[] boxedTypeMirrors; + private List types; + private List primitiveTypeMirrors = new ArrayList<>(); + private List boxedTypeMirrors = new ArrayList<>(); - private final TypeMirror genericType; + private TypeMirror genericType; + private TypeData voidType; + + public TypeSystemData(TypeElement templateType, AnnotationMirror annotation) { + super(templateType, null, annotation); + } - private final TypeData voidType; + void setTypes(List types) { + this.types = types; + if (types != null) { + for (TypeData typeData : types) { + primitiveTypeMirrors.add(typeData.getPrimitiveType()); + boxedTypeMirrors.add(typeData.getBoxedType()); + } + } + } - public TypeSystemData(TypeElement templateType, AnnotationMirror annotation, TypeData[] types, TypeMirror genericType, TypeData voidType) { - super(templateType, annotation); - this.types = types; + void setGenericType(TypeMirror genericType) { this.genericType = genericType; + } + + void setVoidType(TypeData voidType) { this.voidType = voidType; - this.primitiveTypeMirrors = new TypeMirror[types.length]; - for (int i = 0; i < types.length; i++) { - primitiveTypeMirrors[i] = types[i].getPrimitiveType(); - } + } - this.boxedTypeMirrors = new TypeMirror[types.length]; - for (int i = 0; i < types.length; i++) { - boxedTypeMirrors[i] = types[i].getBoxedType(); + @Override + protected List findChildContainers() { + List sinks = new ArrayList<>(); + if (types != null) { + sinks.addAll(types); } - - for (TypeData type : types) { - type.typeSystem = this; - } - if (voidType != null) { - voidType.typeSystem = this; - } + return sinks; } public boolean isGeneric(TypeMirror type) { @@ -71,16 +78,16 @@ return voidType; } - public TypeData[] getTypes() { - return types; + public List getBoxedTypeMirrors() { + return boxedTypeMirrors; } - public TypeMirror[] getPrimitiveTypeMirrors() { + public List getPrimitiveTypeMirrors() { return primitiveTypeMirrors; } - public TypeMirror[] getBoxedTypeMirrors() { - return boxedTypeMirrors; + public List getTypes() { + return types; } public TypeMirror getGenericType() { @@ -88,7 +95,7 @@ } public TypeData getGenericTypeData() { - TypeData result = types[types.length - 1]; + TypeData result = types.get(types.size() - 1); assert result.getBoxedType() == genericType; return result; } @@ -111,7 +118,7 @@ if (index == -1) { return null; } - return types[index]; + return types.get(index); } public int findType(TypeData typeData) { @@ -119,8 +126,8 @@ } public int findType(TypeMirror type) { - for (int i = 0; i < types.length; i++) { - if (Utils.typeEquals(types[i].getPrimitiveType(), type)) { + for (int i = 0; i < types.size(); i++) { + if (Utils.typeEquals(types.get(i).getPrimitiveType(), type)) { return i; } } @@ -129,7 +136,7 @@ @Override public String toString() { - return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + Arrays.toString(types) + "]"; + return getClass().getSimpleName() + "[template = " + Utils.getSimpleName(getTemplateType()) + ", types = " + types + "]"; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -43,18 +43,24 @@ return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; } - protected TypeData findTypeByMethodName(ExecutableElement method, AnnotationMirror annotationMirror, String prefix) { - String methodName = method.getSimpleName().toString(); + protected TypeData findTypeByMethodName(String methodName, String prefix) { + String typeName = methodName.substring(prefix.length(), methodName.length()); + TypeData type = getTypeSystem().findType(typeName); + return type; + } + + protected TypeData findTypeByMethodName(TemplateMethod method, String prefix) { + String methodName = method.getMethodName(); if (!methodName.startsWith(prefix)) { - String annotationName = Utils.getSimpleName(annotationMirror.getAnnotationType()); - getContext().getLog().error(method, "Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); + String annotationName = Utils.getSimpleName(method.getMessageAnnotation().getAnnotationType()); + method.addError("Methods annotated with %s must match the pattern '%s'.", annotationName, String.format("%s${typeName}", prefix)); return null; } String typeName = methodName.substring(prefix.length(), methodName.length()); TypeData type = getTypeSystem().findType(typeName); if (type == null) { String annotationName = TypeSystem.class.getSimpleName(); - getContext().getLog().error(method, "Type '%s' is not declared in this @%s.", typeName, annotationName); + method.addError("Type '%s' is not declared in this @%s.", typeName, annotationName); return null; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Thu Mar 14 01:09:43 2013 +0100 @@ -52,27 +52,39 @@ protected TypeSystemData parse(Element element, AnnotationMirror mirror) { TypeElement templateType = (TypeElement) element; AnnotationMirror templateTypeAnnotation = mirror; + TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation); - if (!verifyTemplateType(templateType, templateTypeAnnotation)) { - return null; + // annotation type on class path!? + TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); + if (annotationTypeElement == null) { + typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName()); + } + if (templateType.getModifiers().contains(Modifier.PRIVATE)) { + typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName()); } - TypeData[] types = parseTypes(templateType, templateTypeAnnotation); - if (types == null) { - return null; + if (templateType.getModifiers().contains(Modifier.FINAL)) { + typeSystem.addError("The @%s must not be final.", getAnnotationType().getName()); + } + if (typeSystem.hasErrors()) { + return typeSystem; + } + + typeSystem.setTypes(parseTypes(typeSystem)); + if (typeSystem.getTypes() == null) { + return typeSystem; } TypeMirror genericType = context.getType(Object.class); - TypeData voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class)); - - TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, genericType, voidType); + TypeData voidType = new TypeData(typeSystem, null, context.getType(void.class), context.getType(Void.class)); - if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class)) { - return null; - } + typeSystem.setGenericType(genericType); + typeSystem.setVoidType(voidType); + + verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); - typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType, elements)); + typeSystem.setExtensionElements(getExtensionParser().parseAll(typeSystem, elements)); if (typeSystem.getExtensionElements() != null) { elements.addAll(typeSystem.getExtensionElements()); } @@ -81,7 +93,7 @@ List checks = new TypeCheckParser(context, typeSystem).parse(elements); if (casts == null || checks == null) { - return null; + return typeSystem; } for (TypeCheckData check : checks) { @@ -92,24 +104,15 @@ cast.getTargetType().addTypeCast(cast); } - if (!verifyGenericTypeChecksAndCasts(types)) { - return null; - } - - if (!verifyMethodSignatures(element, types)) { - return null; - } - - if (!verifyNamesUnique(templateType, templateTypeAnnotation, types)) { - return null; - } + verifyGenericTypeChecksAndCasts(typeSystem); + verifyMethodSignatures(typeSystem); + verifyNamesUnique(typeSystem); return typeSystem; } - private boolean verifyGenericTypeChecksAndCasts(TypeData[] types) { - boolean valid = true; - for (TypeData type : types) { + private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { + for (TypeData type : typeSystem.getTypes()) { if (!type.getTypeChecks().isEmpty()) { boolean hasGeneric = false; for (TypeCheckData typeCheck : type.getTypeChecks()) { @@ -119,10 +122,9 @@ } } if (!hasGeneric) { - log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. " - + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), - Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), Object.class.getSimpleName()); - valid = false; + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCheck.class.getSimpleName(), + Object.class.getSimpleName()); } } if (!type.getTypeCasts().isEmpty()) { @@ -134,60 +136,55 @@ } } if (!hasGeneric) { - log.error(type.getTypeSystem().getTemplateType(), "No generic but specific @%s method %s for type %s specified. " - + "Specify a generic @%s method with parameter type %s to resolve this.", TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), - Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), Object.class.getSimpleName()); - valid = false; + type.addError("No generic but specific @%s method %s for type %s specified. " + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), TypeCast.class.getSimpleName(), + Object.class.getSimpleName()); } } } - return valid; } - private TypeData[] parseTypes(TypeElement templateType, AnnotationMirror templateTypeAnnotation) { - List typeMirrors = Utils.getAnnotationValueList(templateTypeAnnotation, "value"); - if (typeMirrors.size() == 0) { - log.error(templateType, templateTypeAnnotation, "At least one type must be defined."); - return null; + private List parseTypes(TypeSystemData typeSystem) { + List types = new ArrayList<>(); + List typeMirrors = Utils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value"); + if (typeMirrors.isEmpty()) { + typeSystem.addError("At least one type must be defined."); + return types; } - final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "value"); + final AnnotationValue annotationValue = Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value"); final TypeMirror objectType = context.getType(Object.class); - List types = new ArrayList<>(); for (TypeMirror primitiveType : typeMirrors) { + TypeMirror boxedType = Utils.boxType(context, primitiveType); + TypeData typeData = new TypeData(typeSystem, annotationValue, primitiveType, boxedType); if (isPrimitiveWrapper(primitiveType)) { - log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain primitive wrapper types."); - continue; + typeData.addError("Types must not contain primitive wrapper types."); } - TypeMirror boxedType = Utils.boxType(context, primitiveType); - if (Utils.typeEquals(boxedType, objectType)) { - log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain the generic type java.lang.Object."); - continue; + typeData.addError("Types must not contain the generic type java.lang.Object."); } - types.add(new TypeData(templateType, templateTypeAnnotation, primitiveType, boxedType)); + types.add(typeData); } - verifyTypeOrder(templateType, templateTypeAnnotation, annotationValue, types); + verifyTypeOrder(types); - types.add(new TypeData(templateType, templateTypeAnnotation, objectType, objectType)); + types.add(new TypeData(typeSystem, annotationValue, objectType, objectType)); - return types.toArray(new TypeData[types.size()]); + return types; } - private void verifyTypeOrder(TypeElement templateType, AnnotationMirror templateTypeAnnotation, AnnotationValue annotationValue, List types) { + private static void verifyTypeOrder(List types) { Map> invalidTypes = new HashMap<>(); for (int i = types.size() - 1; i >= 0; i--) { TypeData typeData = types.get(i); TypeMirror type = typeData.getBoxedType(); if (invalidTypes.containsKey(Utils.getQualifiedName(type))) { - log.error(templateType, templateTypeAnnotation, annotationValue, "Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", - invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); + typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); } List nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type)); nextInvalidTypes.add(getQualifiedName(type)); @@ -216,19 +213,18 @@ return false; } - private boolean verifyMethodSignatures(Element element, TypeData[] types) { + private void verifyMethodSignatures(TypeSystemData typeSystem) { Set generatedIsMethodNames = new HashSet<>(); Set generatedAsMethodNames = new HashSet<>(); Set generatedExpectMethodNames = new HashSet<>(); - for (TypeData typeData : types) { + for (TypeData typeData : typeSystem.getTypes()) { generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); } - boolean valid = true; - List methods = ElementFilter.methodsIn(element.getEnclosedElements()); + List methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements()); for (ExecutableElement method : methods) { if (method.getModifiers().contains(Modifier.PRIVATE)) { // will not conflict overridden methods @@ -238,51 +234,48 @@ } String methodName = method.getSimpleName().toString(); if (generatedIsMethodNames.contains(methodName)) { - valid &= verifyIsMethod(method); + verifyIsMethod(typeSystem, method); } else if (generatedAsMethodNames.contains(methodName)) { - valid &= verifyAsMethod(method); + verifyAsMethod(typeSystem, method); } else if (generatedExpectMethodNames.contains(methodName)) { - valid &= verifyExpectMethod(method); + verifyExpectMethod(typeSystem); } } - return valid; } - private boolean verifyIsMethod(ExecutableElement method) { + private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class); if (mirror == null) { - log.error(method, "Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); + typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); return false; } return true; } - private boolean verifyAsMethod(ExecutableElement method) { + private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class); if (mirror == null) { - log.error(method, "Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); + typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); return false; } return true; } - private boolean verifyExpectMethod(ExecutableElement method) { - log.error(method, "Method starting with the pattern expect${typeName} must not be declared manually."); + private static boolean verifyExpectMethod(TypeSystemData typeSystem) { + typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually."); return false; } - private boolean verifyNamesUnique(TypeElement templateType, AnnotationMirror templateTypeAnnotation, TypeData[] types) { - boolean valid = true; - for (int i = 0; i < types.length; i++) { - for (int j = i + 1; j < types.length; j++) { - String name1 = Utils.getSimpleName(types[i].getBoxedType()); - String name2 = Utils.getSimpleName(types[j].getBoxedType()); + private static void verifyNamesUnique(TypeSystemData typeSystem) { + List types = typeSystem.getTypes(); + for (int i = 0; i < types.size(); i++) { + for (int j = i + 1; j < types.size(); j++) { + String name1 = Utils.getSimpleName(types.get(i).getBoxedType()); + String name2 = Utils.getSimpleName(types.get(j).getBoxedType()); if (name1.equalsIgnoreCase(name2)) { - log.error(templateType, templateTypeAnnotation, "Two types result in the same name: %s, %s.", name1, name2); - valid = false; + typeSystem.addError("Two types result in the same name: %s, %s.", name1, name2); } } } - return valid; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Thu Mar 14 01:09:43 2013 +0100 @@ -27,8 +27,11 @@ import java.util.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.AddNodeFactory; +import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.DivNodeFactory; +import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.MulNodeFactory; +import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.SubNodeFactory; import com.oracle.truffle.sl.nodes.*; -import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.*; public class NodeFactory { diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java Thu Mar 14 01:09:43 2013 +0100 @@ -41,7 +41,7 @@ return (int) value; } else { int result = ((BigInteger) value).intValue(); - assert BigInteger.valueOf(result).equals(value) : "Loosing precision"; + assert BigInteger.valueOf(result).equals(value) : "Losing precision"; return result; } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Thu Mar 14 01:09:43 2013 +0100 @@ -37,11 +37,6 @@ super(node); } - @Generic - public Object doGeneric(Object left, Object right) { - throw new RuntimeException("Arithmetic not defined for types " + left.getClass().getSimpleName() + ", " + right.getClass().getSimpleName()); - } - public abstract static class AddNode extends ArithmeticNode { public AddNode(TypedNode left, TypedNode right) { @@ -52,9 +47,8 @@ super(node); } - @Specialization - @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger") - int doInteger(int left, int right) { + @Specialization(rewriteOn = ArithmeticException.class) + int doInt(int left, int right) { return ExactMath.addExact(left, right); } @@ -64,13 +58,12 @@ } @Specialization - String doStringDirect(String left, String right) { + String doString(String left, String right) { return left + right; } - @Specialization - @SpecializationGuard(methodName = "isString") - String doString(Object left, Object right) { + @Specialization(guards = "isString") + String add(Object left, Object right) { return left.toString() + right.toString(); } } @@ -85,16 +78,16 @@ super(node); } - @Specialization - @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger") - int doInteger(int left, int right) { + @Specialization(rewriteOn = ArithmeticException.class) + int sub(int left, int right) { return ExactMath.subtractExact(left, right); } @Specialization - BigInteger doBigInteger(BigInteger left, BigInteger right) { + BigInteger sub(BigInteger left, BigInteger right) { return left.subtract(right); } + } public abstract static class DivNode extends ArithmeticNode { @@ -107,14 +100,13 @@ super(node); } - @Specialization - @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger") - int doInteger(int left, int right) { + @Specialization(rewriteOn = ArithmeticException.class) + int div(int left, int right) { return left / right; } @Specialization - BigInteger doBigInteger(BigInteger left, BigInteger right) { + BigInteger div(BigInteger left, BigInteger right) { return left.divide(right); } } @@ -129,16 +121,16 @@ super(node); } - @Specialization - @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger") - int doInteger(int left, int right) { + @Specialization(rewriteOn = ArithmeticException.class) + int mul(int left, int right) { return ExactMath.multiplyExact(left, right); } @Specialization - BigInteger doBigInteger(BigInteger left, BigInteger right) { + BigInteger mul(BigInteger left, BigInteger right) { return left.multiply(right); } + } } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java Thu Mar 14 01:09:43 2013 +0100 @@ -46,8 +46,7 @@ return left.compareTo(right) < 0; } - @Specialization - @SpecializationGuard(methodName = "isString") + @Specialization(guards = "isString") public boolean doString(Object left, Object right) { return left.toString().compareTo(right.toString()) < 0; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java Thu Mar 14 01:09:43 2013 +0100 @@ -24,7 +24,6 @@ import java.math.*; -import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -49,7 +48,6 @@ public abstract Object executeGeneric(VirtualFrame frame); - @GuardCheck public boolean isString(Object a, Object b) { return a instanceof String || b instanceof String; } diff -r 53683dc2815e -r ff91c7101ed0 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Thu Mar 14 01:09:32 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Thu Mar 14 01:09:43 2013 +0100 @@ -41,31 +41,31 @@ } @Specialization - public int doInteger(VirtualFrame frame, int right) { + public int write(VirtualFrame frame, int right) { frame.setInt(slot, right); return right; } @Specialization - public BigInteger doBigInteger(VirtualFrame frame, BigInteger right) { + public BigInteger write(VirtualFrame frame, BigInteger right) { frame.setObject(slot, right); return right; } @Specialization - public boolean doBoolean(VirtualFrame frame, boolean right) { + public boolean write(VirtualFrame frame, boolean right) { frame.setBoolean(slot, right); return right; } @Specialization - public String doString(VirtualFrame frame, String right) { + public String write(VirtualFrame frame, String right) { frame.setObject(slot, right); return right; } @Generic - public Object doGeneric(VirtualFrame frame, Object right) { + public Object writeGeneric(VirtualFrame frame, Object right) { frame.setObject(slot, right); return right; } diff -r 53683dc2815e -r ff91c7101ed0 make/build-graal.xml --- a/make/build-graal.xml Thu Mar 14 01:09:32 2013 +0100 +++ b/make/build-graal.xml Thu Mar 14 01:09:43 2013 +0100 @@ -34,7 +34,7 @@ - + diff -r 53683dc2815e -r ff91c7101ed0 make/windows/makefiles/projectcreator.make --- a/make/windows/makefiles/projectcreator.make Thu Mar 14 01:09:32 2013 +0100 +++ b/make/windows/makefiles/projectcreator.make Thu Mar 14 01:09:43 2013 +0100 @@ -145,8 +145,10 @@ -ignorePath_TARGET c1_ ProjectCreatorIDEOptionsIgnoreGraal=\ - -ignorePath_TARGET graal - + -ignorePath_TARGET src/share/vm/graal \ + -ignorePath_TARGET graal/generated \ + -ignorePath_TARGET vm/graal + ProjectCreatorIDEOptionsIgnoreCompiler2=\ -ignorePath_TARGET compiler2 \ -ignorePath_TARGET tiered \ @@ -175,7 +177,6 @@ ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ -define_compiler1 COMPILER1 \ -ignorePath_compiler1 core \ - -ignorePath_compiler1 src/share/vm/graal \ $(ProjectCreatorIDEOptionsIgnoreGraal:TARGET=compiler1) \ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1) @@ -185,7 +186,6 @@ ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ -define_graal GRAAL \ -ignorePath_graal core \ - -ignorePath_graal src/share/vm/c1 \ $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=graal) \ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=graal) @@ -195,8 +195,9 @@ #NOTE! This list must be kept in sync with GENERATED_NAMES in adlc.make. ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ -define_compiler2 COMPILER2 \ + -define_compiler2 GRAAL \ -ignorePath_compiler2 core \ - -ignorePath_compiler2 src/share/vm/graal \ + -ignorePath_compiler2 graal/generated \ -additionalFile_compiler2 $(Platform_arch_model).ad \ -additionalFile_compiler2 ad_$(Platform_arch_model).cpp \ -additionalFile_compiler2 ad_$(Platform_arch_model).hpp \ @@ -209,7 +210,6 @@ -additionalFile_compiler2 ad_$(Platform_arch_model)_pipeline.cpp \ -additionalFile_compiler2 adGlobals_$(Platform_arch_model).hpp \ -additionalFile_compiler2 dfa_$(Platform_arch_model).cpp \ - $(ProjectCreatorIDEOptionsIgnoreGraal:TARGET=compiler2) \ $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=compiler2) # Add in the jvmti (JSR-163) options diff -r 53683dc2815e -r ff91c7101ed0 mx/commands.py --- a/mx/commands.py Thu Mar 14 01:09:32 2013 +0100 +++ b/mx/commands.py Thu Mar 14 01:09:43 2013 +0100 @@ -316,7 +316,7 @@ return join(jdk, 'jre', 'lib', _arch(), 'jvm.cfg') return join(_vmLibDirInJdk(jdk), 'jvm.cfg') -def _jdk(build='product', create=False): +def _jdk(build='product', vmToCheck=None, create=False): """ Get the JDK into which Graal is installed, creating it first if necessary. """ @@ -344,7 +344,6 @@ if not exists(jvmCfg): mx.abort(jvmCfg + ' does not exist') - lines = [] defaultVM = None with open(jvmCfg) as f: for line in f: @@ -353,17 +352,14 @@ assert len(parts) == 2, parts assert parts[1] == 'KNOWN', parts[1] defaultVM = parts[0][1:] - lines.append('-' + defaultVM + '0 KNOWN\n') - lines.append(line) assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg if mx.get_os() != 'windows': chmodRecursive(jdk, 0755) shutil.copytree(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), defaultVM + '0')) - with open(jvmCfg, 'w') as f: - for line in lines: - f.write(line) + with open(jvmCfg, 'w') as fp: + print >> fp, '-' + defaultVM + '0 KNOWN' # Install a copy of the disassembler library try: @@ -372,10 +368,21 @@ pass else: if not exists(jdk): - mx.abort('The ' + build + ' VM has not been created - run \'mx clean; mx build ' + build + '\'') + mx.abort('The ' + build + ' VM has not been created - run "mx build ' + build + '"') _installGraalJarInJdks(mx.distribution('GRAAL')) + if vmToCheck is not None: + jvmCfg = _vmCfgInJdk(jdk) + found = False + with open(jvmCfg) as f: + for line in f: + if line.strip() == '-' + vmToCheck + ' KNOWN': + found = True + break + if not found: + mx.abort('The ' + build + ' ' + vmToCheck + ' VM has not been created - run "mx --vm ' + vmToCheck + ' build ' + build + '"') + return jdk def _installGraalJarInJdks(graalDist): @@ -588,23 +595,18 @@ mx.abort(jvmCfg + ' does not exist') prefix = '-' + vm - vmKnown = prefix + ' KNOWN\n' - lines = [] + vmKnown = prefix + ' KNOWN' with open(jvmCfg) as f: for line in f: - if vmKnown in line: + if vmKnown == line.strip(): found = True break - if not line.startswith(prefix): - lines.append(line) if not found: mx.log('Appending "' + prefix + ' KNOWN" to ' + jvmCfg) - lines.append(vmKnown) if mx.get_os() != 'windows': os.chmod(jvmCfg, 0755) - with open(jvmCfg, 'w') as f: - for line in lines: - f.write(line) + with open(jvmCfg, 'a') as f: + print >> f, vmKnown if exists(timestampFile): os.utime(timestampFile, None) @@ -626,7 +628,7 @@ vm = _vm build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product' - jdk = _jdk(build) + jdk = _jdk(build, vmToCheck=vm) mx.expand_project_in_args(args) if _make_eclipse_launch: mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True)) @@ -818,6 +820,10 @@ tasks.append(t.stop()) _vmbuild = 'product' + t = Task('BootstrapWithRegisterPressure:product') + vm(['-G:RegisterPressure=rbx,r11,r14,xmm3,xmm11,xmm14', '-esa', '-version']) + tasks.append(t.stop()) + originalVm = _vm _vm = 'server' # hosted mode t = Task('UnitTests:hosted-product') diff -r 53683dc2815e -r ff91c7101ed0 mx/projects --- a/mx/projects Thu Mar 14 01:09:32 2013 +0100 +++ b/mx/projects Thu Mar 14 01:09:43 2013 +0100 @@ -366,21 +366,29 @@ # truffle.api.codegen project@com.oracle.truffle.api.codegen@subDir=graal project@com.oracle.truffle.api.codegen@sourceDirs=src -project@com.oracle.truffle.api.codegen@dependencies= +project@com.oracle.truffle.api.codegen@dependencies=com.oracle.truffle.api project@com.oracle.truffle.api.codegen@checkstyle=com.oracle.graal.graph project@com.oracle.truffle.api.codegen@javaCompliance=1.7 +# truffle.api.codegen.test +project@com.oracle.truffle.api.codegen.test@subDir=graal +project@com.oracle.truffle.api.codegen.test@sourceDirs=src +project@com.oracle.truffle.api.codegen.test@dependencies=com.oracle.truffle.api.codegen,JUNIT +project@com.oracle.truffle.api.codegen.test@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.api.codegen.test@javaCompliance=1.7 +project@com.oracle.truffle.api.codegen.test@annotationProcessors=com.oracle.truffle.codegen.processor + # truffle.codegen.processor project@com.oracle.truffle.codegen.processor@subDir=graal project@com.oracle.truffle.codegen.processor@sourceDirs=src -project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen,com.oracle.truffle.api +project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen project@com.oracle.truffle.codegen.processor@checkstyle=com.oracle.graal.graph project@com.oracle.truffle.codegen.processor@javaCompliance=1.7 # truffle.sl project@com.oracle.truffle.sl@subDir=graal project@com.oracle.truffle.sl@sourceDirs=src -project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.codegen,com.oracle.truffle.api +project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.codegen project@com.oracle.truffle.sl@checkstyle=com.oracle.graal.graph project@com.oracle.truffle.sl@javaCompliance=1.7 project@com.oracle.truffle.sl@annotationProcessors=com.oracle.truffle.codegen.processor diff -r 53683dc2815e -r ff91c7101ed0 src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Thu Mar 14 01:09:32 2013 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Thu Mar 14 01:09:43 2013 +0100 @@ -925,19 +925,6 @@ __ movptr(rsp, rbp); __ pop(rbp); - Label nonNullExceptionOop; - __ testptr(rax, rax); - __ jcc(Assembler::notZero, nonNullExceptionOop); - { - __ enter(); - oop_maps = new OopMapSet(); - OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0); - oop_maps->add_gc_map(call_offset, oop_map); - __ leave(); - } - __ bind(nonNullExceptionOop); - __ set_info("unwind_exception", dont_gc_arguments); // note: no stubframe since we are about to leave the current // activation and we are calling a leaf VM function only. diff -r 53683dc2815e -r ff91c7101ed0 src/cpu/x86/vm/macroAssembler_x86.cpp --- a/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Mar 14 01:09:32 2013 +0100 +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Mar 14 01:09:43 2013 +0100 @@ -2058,7 +2058,7 @@ } // !defined(COMPILER2) is because of stupid core builds -#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) +#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) || defined(GRAAL) void MacroAssembler::empty_FPU_stack() { if (VM_Version::supports_mmx()) { emms(); diff -r 53683dc2815e -r ff91c7101ed0 src/share/tools/ProjectCreator/FileTreeCreatorVC10.java --- a/src/share/tools/ProjectCreator/FileTreeCreatorVC10.java Thu Mar 14 01:09:32 2013 +0100 +++ b/src/share/tools/ProjectCreator/FileTreeCreatorVC10.java Thu Mar 14 01:09:43 2013 +0100 @@ -50,7 +50,8 @@ if (addFile.equals(fileName)) { // supress any ignore // TODO - may need some adjustments - if (file.toAbsolutePath().toString().contains(cfg.get("Flavour"))) { + String relativePath = startDir.toUri().relativize(file.toUri()).getPath(); + if (relativePath.contains(cfg.get("Flavour"))) { currentFileAttr.removeFromIgnored(cfg); } }