# HG changeset patch # User Christian Haeubl # Date 1366699447 -7200 # Node ID 6aea59f0965cbbc9a3e6d0f5a705c2d057bb3860 # Parent 8f01fe16e473395c686d7a6ced4ba656e7e3cf2e# Parent 374ece5ff845e42d87b565cfc0184b09ae2e8724 Merge. diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Tue Apr 23 08:44:07 2013 +0200 @@ -25,7 +25,6 @@ /** * Enumeration of reasons for why a deoptimization is happening. */ -// @formatter:off public enum DeoptimizationReason { None, NullCheckException, diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java --- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java Tue Apr 23 08:44:07 2013 +0200 @@ -59,7 +59,7 @@ * Determines if this method should be substituted in all cases, even if inlining thinks it is * not important. * - * Not that this is still depending on whether inlining sees the correct call target, so it's + * Note that this is still depending on whether inlining sees the correct call target, so it's * only a hard guarantee for static and special invocations. */ boolean forced() default false; diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Apr 23 08:44:07 2013 +0200 @@ -156,23 +156,15 @@ append(createMove(dst, src)); } - private AMD64AddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + private AMD64AddressValue prepareAddress(Kind kind, Value base, long displacement, Value index, int scale) { AllocatableValue baseRegister; - int finalDisp = displacement; + long finalDisp = displacement; if (isConstant(base)) { if (asConstant(base).isNull()) { baseRegister = AllocatableValue.UNUSED; - } else if (asConstant(base).getKind() != Kind.Object) { - long newDisplacement = displacement + asConstant(base).asLong(); - if (NumUtil.isInt(newDisplacement)) { - assert !runtime.needsDataPatch(asConstant(base)); - finalDisp = (int) newDisplacement; - baseRegister = AllocatableValue.UNUSED; - } else { - Variable newBase = newVariable(Kind.Long); - emitMove(newBase, base); - baseRegister = newBase; - } + } else if (asConstant(base).getKind() != Kind.Object && !runtime.needsDataPatch(asConstant(base))) { + finalDisp += asConstant(base).asLong(); + baseRegister = AllocatableValue.UNUSED; } else { baseRegister = load(base); } @@ -187,19 +179,8 @@ if (index != Value.ILLEGAL && scale != 0) { scaleEnum = Scale.fromInt(scale); if (isConstant(index)) { - long newDisplacement = finalDisp + asConstant(index).asLong() * scale; - // only use the constant index if the resulting displacement fits into a 32 bit - // offset - if (NumUtil.isInt(newDisplacement)) { - finalDisp = (int) newDisplacement; - indexRegister = AllocatableValue.UNUSED; - } else { - // create a temporary variable for the index, the pointer load cannot handle a - // constant index - Variable newIndex = newVariable(Kind.Long); - emitMove(newIndex, index); - indexRegister = newIndex; - } + finalDisp += asConstant(index).asLong() * scale; + indexRegister = AllocatableValue.UNUSED; } else { indexRegister = asAllocatable(index); } @@ -208,11 +189,27 @@ scaleEnum = Scale.Times1; } - return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, finalDisp); + int displacementInt; + if (NumUtil.isInt(finalDisp)) { + displacementInt = (int) finalDisp; + } else { + displacementInt = 0; + AllocatableValue displacementRegister = load(Constant.forLong(finalDisp)); + if (baseRegister == AllocatableValue.UNUSED) { + baseRegister = displacementRegister; + } else if (indexRegister == AllocatableValue.UNUSED) { + indexRegister = displacementRegister; + scaleEnum = Scale.Times1; + } else { + baseRegister = emitAdd(baseRegister, displacementRegister); + } + } + + return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, displacementInt); } @Override - public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) { + public Variable emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting) { AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null)); @@ -220,7 +217,7 @@ } @Override - public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { + public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); LIRFrameState state = deopting != null ? state(deopting) : null; @@ -237,7 +234,7 @@ } @Override - public Variable emitLea(Value base, int displacement, Value index, int scale) { + public Variable emitLea(Value base, long displacement, Value index, int scale) { Variable result = newVariable(target().wordKind); AMD64AddressValue address = prepareAddress(result.getKind(), base, displacement, index, scale); append(new LeaOp(result, address)); diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Tue Apr 23 08:44:07 2013 +0200 @@ -137,7 +137,7 @@ } } - private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + private PTXAddressValue prepareAddress(Kind kind, Value base, long displacement, Value index, int scale) { AllocatableValue baseRegister; long finalDisp = displacement; if (isConstant(base)) { @@ -181,7 +181,7 @@ } @Override - public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) { + public Variable emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting) { PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null)); @@ -189,14 +189,14 @@ } @Override - public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { + public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); Variable input = load(inputVal); append(new StoreOp(storeAddress, input, deopting != null ? state(deopting) : null)); } @Override - public Variable emitLea(Value base, int displacement, Value index, int scale) { + public Variable emitLea(Value base, long displacement, Value index, int scale) { throw new InternalError("NYI"); } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Tue Apr 23 08:44:07 2013 +0200 @@ -214,19 +214,19 @@ } @Override - public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode canTrap) { + public Value emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode canTrap) { // SPARC: Auto-generated method stub return null; } @Override - public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode canTrap) { + public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value input, DeoptimizingNode canTrap) { // SPARC: Auto-generated method stub } @Override - public Value emitLea(Value base, int displacement, Value index, int scale) { + public Value emitLea(Value base, long displacement, Value index, int scale) { // SPARC: Auto-generated method stub return null; } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Apr 23 08:44:07 2013 +0200 @@ -363,6 +363,7 @@ public long logPrimitiveStub; public long logObjectStub; public long logPrintfStub; + public long stubPrintfStub; public int deoptReasonNone; public long threadIsInterruptedStub; public long identityHashCodeStub; diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 23 08:44:07 2013 +0200 @@ -262,6 +262,14 @@ /* arg2: value */ Kind.Long, /* arg3: value */ Kind.Long)); + addRuntimeCall(Stub.STUB_PRINTF, config.stubPrintfStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: format */ javaCallingConvention(Kind.Long, + /* arg1: value */ Kind.Long, + /* arg2: value */ Kind.Long, + /* arg3: value */ Kind.Long)); + addRuntimeCall(LOG_OBJECT, config.logObjectStub, /* temps */ null, /* ret */ ret(Kind.Void), @@ -507,7 +515,7 @@ if (n instanceof ArrayLengthNode) { ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; ValueNode array = arrayLengthNode.array(); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt())); + ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt())); arrayLengthRead.dependencies().add(tool.createNullCheckGuard(array)); graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); } else if (n instanceof Invoke) { @@ -533,8 +541,9 @@ // as HotSpot does not guarantee they are final values. assert vtableEntryOffset > 0; LoadHubNode hub = graph.add(new LoadHubNode(receiver, wordKind)); - ReadNode metaspaceMethod = graph.add(new ReadNode(hub, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()))); - ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), + ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), + StampFactory.forKind(wordKind()))); + ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), StampFactory.forKind(wordKind()))); loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), @@ -558,7 +567,7 @@ HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object(); assert loadField.kind() != Kind.Illegal; - ReadNode memoryRead = graph.add(new ReadNode(object, LocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp())); + ReadNode memoryRead = graph.add(new ReadNode(object, ConstantLocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp())); memoryRead.dependencies().add(tool.createNullCheckGuard(object)); graph.replaceFixedWithFixed(loadField, memoryRead); @@ -573,7 +582,7 @@ StoreFieldNode storeField = (StoreFieldNode) n; HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object(); - LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph); + LocationNode location = ConstantLocationNode.create(field, field.getKind(), field.offset(), graph); WriteBarrierType barrierType = getFieldStoreBarrierType(storeField); WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location, barrierType)); memoryWrite.dependencies().add(tool.createNullCheckGuard(object)); @@ -621,7 +630,7 @@ } } else { LoadHubNode arrayClass = graph.add(new LoadHubNode(array, wordKind)); - LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); + LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind()))); CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value)); graph.addBeforeFixed(storeIndexed, checkcast); @@ -656,7 +665,7 @@ } else if (n instanceof LoadHubNode) { LoadHubNode loadHub = (LoadHubNode) n; assert loadHub.kind() == wordKind; - LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph); + LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph); ValueNode object = loadHub.object(); assert !object.isConstant() || object.asConstant().isNull(); ValueNode guard = tool.createNullCheckGuard(object); diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import static com.oracle.graal.graph.UnsafeAccess.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; + +/** + * Converts a compile-time constant Java string into a malloc'ed C string. The malloc'ed string is + * never reclaimed so this should only be used for strings in permanent code such as compiled stubs. + */ +public final class CStringNode extends FloatingNode implements Lowerable { + + private final String string; + + public CStringNode(String string) { + super(StampFactory.forWord()); + this.string = string; + } + + @Override + public void lower(LoweringTool tool) { + byte[] formatBytes = string.getBytes(); + long cstring = unsafe.allocateMemory(formatBytes.length + 1); + for (int i = 0; i < formatBytes.length; i++) { + unsafe.putByte(cstring + i, formatBytes[i]); + } + unsafe.putByte(cstring + formatBytes.length, (byte) 0); + StructuredGraph graph = (StructuredGraph) graph(); + ConstantNode replacement = ConstantNode.forLong(cstring, graph); + graph.replaceFloating(this, replacement); + } + + @NodeIntrinsic + public static native Word cstring(@ConstantNodeParameter String string); +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue Apr 23 08:44:07 2013 +0200 @@ -208,40 +208,4 @@ private static boolean forceSlowPath() { return Boolean.getBoolean("graal.newInstanceStub.forceSlowPath"); } - - static void log(boolean enabled, String format, long value) { - if (enabled) { - Log.printf(format, value); - } - } - - static void log(boolean enabled, String format, WordBase value) { - if (enabled) { - Log.printf(format, value.rawValue()); - } - } - - static void log(boolean enabled, String format, long v1, long v2) { - if (enabled) { - Log.printf(format, v1, v2); - } - } - - static void log(boolean enabled, String format, Word v1, long v2) { - if (enabled) { - Log.printf(format, v1.rawValue(), v2); - } - } - - static void log(boolean enabled, String format, Word v1, Word v2) { - if (enabled) { - Log.printf(format, v1.rawValue(), v2.rawValue()); - } - } - - static void log(boolean enabled, String format, long v1, long v2, long v3) { - if (enabled) { - Log.printf(format, v1, v2, v3); - } - } } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Apr 23 08:44:07 2013 +0200 @@ -22,19 +22,25 @@ */ package com.oracle.graal.hotspot.stubs; +import static com.oracle.graal.hotspot.nodes.CStringNode.*; + import java.util.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; @@ -43,6 +49,7 @@ import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; /** * Base class for implementing some low level code providing the out-of-line slow path for a @@ -156,4 +163,52 @@ } return code; } + + static void log(boolean enabled, String format, long value) { + if (enabled) { + printf(format, value); + } + } + + static void log(boolean enabled, String format, WordBase value) { + if (enabled) { + printf(format, value.rawValue()); + } + } + + static void log(boolean enabled, String format, Word v1, long v2) { + if (enabled) { + printf(format, v1.rawValue(), v2); + } + } + + static void log(boolean enabled, String format, Word v1, Word v2) { + if (enabled) { + printf(format, v1.rawValue(), v2.rawValue()); + } + } + + public static final Descriptor STUB_PRINTF = new Descriptor("stubPrintf", false, void.class, Word.class, long.class, long.class, long.class); + + @NodeIntrinsic(RuntimeCallNode.class) + private static native void printf(@ConstantNodeParameter Descriptor stubPrintf, Word format, long v1, long v2, long v3); + + /** + * Prints a formatted string to the log stream. + * + * @param format a C style printf format value that can contain at most one conversion specifier + * (i.e., a sequence of characters starting with '%'). + * @param value the value associated with the conversion specifier + */ + public static void printf(String format, long value) { + printf(STUB_PRINTF, cstring(format), value, 0L, 0L); + } + + public static void printf(String format, long v1, long v2) { + printf(STUB_PRINTF, cstring(format), v1, v2, 0L); + } + + public static void printf(String format, long v1, long v2, long v3) { + printf(STUB_PRINTF, cstring(format), v1, v2, v3); + } } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Apr 23 08:44:07 2013 +0200 @@ -285,7 +285,7 @@ ValueNode value; if (kind == Kind.Object) { value = frameState.xpop(); - // astore and astore_ may be used to store a returnAddress (jsr) see JVMS par. 6.5.astore + // astore and astore_ may be used to store a returnAddress (jsr) assert value.kind() == Kind.Object || value.kind() == Kind.Int; } else { value = frameState.pop(kind); @@ -1169,7 +1169,7 @@ createInvokeNode(callTarget, resultType); } - protected Invoke createInvokeNode(MethodCallTargetNode callTarget, Kind resultType) { + protected Invoke createInvokeNode(CallTargetNode callTarget, Kind resultType) { // be conservative if information was not recorded (could result in endless recompiles // otherwise) if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java Tue Apr 23 08:44:07 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.jtt.*; import org.junit.*; -//@formatter:off public class HP_idea extends JTTTest { public boolean test() { @@ -60,7 +59,7 @@ /* * buildTestData - * + * * Builds the data used for the test -- each time the test is run. */ @@ -115,10 +114,11 @@ /* * calcEncryptKey - * - * Builds the 52 16-bit encryption subkeys Z[] from the user key and stores in 32-bit int array. The routing - * corrects an error in the source code in the Schnier book. Basically, the sense of the 7- and 9-bit shifts are - * reversed. It still works reversed, but would encrypted code would not decrypt with someone else's IDEA code. + * + * Builds the 52 16-bit encryption subkeys Z[] from the user key and stores in 32-bit int array. + * The routing corrects an error in the source code in the Schnier book. Basically, the sense of + * the 7- and 9-bit shifts are reversed. It still works reversed, but would encrypted code would + * not decrypt with someone else's IDEA code. */ private void calcEncryptKey() { @@ -168,9 +168,9 @@ /* * calcDecryptKey - * - * Builds the 52 16-bit encryption subkeys DK[] from the encryption- subkeys Z[]. DK[] is a 32-bit int array holding - * 16-bit values as unsigned. + * + * Builds the 52 16-bit encryption subkeys DK[] from the encryption- subkeys Z[]. DK[] is a + * 32-bit int array holding 16-bit values as unsigned. */ private void calcDecryptKey() { @@ -215,12 +215,14 @@ /* * cipher_idea - * - * IDEA encryption/decryption algorithm. It processes plaintext in 64-bit blocks, one at a time, breaking the block - * into four 16-bit unsigned subblocks. It goes through eight rounds of processing using 6 new subkeys each time, - * plus four for last step. The source text is in array text1, the destination text goes into array text2 The - * routine represents 16-bit subblocks and subkeys as type int so that they can be treated more easily as unsigned. - * Multiplication modulo 0x10001 interprets a zero sub-block as 0x10000; it must to fit in 16 bits. + * + * IDEA encryption/decryption algorithm. It processes plaintext in 64-bit blocks, one at a time, + * breaking the block into four 16-bit unsigned subblocks. It goes through eight rounds of + * processing using 6 new subkeys each time, plus four for last step. The source text is in + * array text1, the destination text goes into array text2 The routine represents 16-bit + * subblocks and subkeys as type int so that they can be treated more easily as unsigned. + * Multiplication modulo 0x10001 interprets a zero sub-block as 0x10000; it must to fit in 16 + * bits. */ @SuppressWarnings("static-method") @@ -356,35 +358,40 @@ /* * mul - * - * Performs multiplication, modulo (2**16)+1. This code is structured on the assumption that untaken branches are - * cheaper than taken branches, and that the compiler doesn't schedule branches. Java: Must work with 32-bit int and - * one 64-bit long to keep 16-bit values and their products "unsigned." The routine assumes that both a and b could - * fit in 16 bits even though they come in as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit. - * Also, because the routine stores mod (2**16)+1 results in a 2**16 space, the result is truncated to zero whenever - * the result would zero, be 2**16. And if one of the multiplicands is 0, the result is not zero, but (2**16) + 1 - * minus the other multiplicand (sort of an additive inverse mod 0x10001). - * - * NOTE: The java conversion of this routine works correctly, but is half the speed of using Java's modulus division - * function (%) on the multiplication with a 16-bit masking of the result--running in the Symantec Caje IDE. So it's - * not called for now; the test uses Java % instead. + * + * Performs multiplication, modulo (2**16)+1. This code is structured on the assumption that + * untaken branches are cheaper than taken branches, and that the compiler doesn't schedule + * branches. Java: Must work with 32-bit int and one 64-bit long to keep 16-bit values and their + * products "unsigned." The routine assumes that both a and b could fit in 16 bits even though + * they come in as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit. Also, + * because the routine stores mod (2**16)+1 results in a 2**16 space, the result is truncated to + * zero whenever the result would zero, be 2**16. And if one of the multiplicands is 0, the + * result is not zero, but (2**16) + 1 minus the other multiplicand (sort of an additive inverse + * mod 0x10001). + * + * NOTE: The java conversion of this routine works correctly, but is half the speed of using + * Java's modulus division function (%) on the multiplication with a 16-bit masking of the + * result--running in the Symantec Caje IDE. So it's not called for now; the test uses Java % + * instead. */ /* - * private int mul(int a, int b) throws ArithmeticException { long p; // Large enough to catch 16-bit multiply // - * without hitting sign bit. if (a != 0) { if (b != 0) { p = (long) a * b; b = (int) p & 0xFFFF; // Lower 16 bits. a - * = (int) p >>> 16; // Upper 16 bits. - * - * return (b - a + (b < a ? 1 : 0) & 0xFFFF); } else return ((1 - a) & 0xFFFF); // If b = 0, then same as // 0x10001 - * - a. } else // If a = 0, then return return((1 - b) & 0xFFFF); // same as 0x10001 - b. } + * private int mul(int a, int b) throws ArithmeticException { long p; // Large enough to catch + * 16-bit multiply // without hitting sign bit. if (a != 0) { if (b != 0) { p = (long) a * b; b + * = (int) p & 0xFFFF; // Lower 16 bits. a = (int) p >>> 16; // Upper 16 bits. + * + * return (b - a + (b < a ? 1 : 0) & 0xFFFF); } else return ((1 - a) & 0xFFFF); // If b = 0, + * then same as // 0x10001 - a. } else // If a = 0, then return return((1 - b) & 0xFFFF); // + * same as 0x10001 - b. } */ /* * inv - * - * Compute multiplicative inverse of x, modulo (2**16)+1 using extended Euclid's GCD (greatest common divisor) - * algorithm. It is unrolled twice to avoid swapping the meaning of the registers. And some subtracts are changed to - * adds. Java: Though it uses signed 32-bit ints, the interpretation of the bits within is strictly unsigned 16-bit. + * + * Compute multiplicative inverse of x, modulo (2**16)+1 using extended Euclid's GCD (greatest + * common divisor) algorithm. It is unrolled twice to avoid swapping the meaning of the + * registers. And some subtracts are changed to adds. Java: Though it uses signed 32-bit ints, + * the interpretation of the bits within is strictly unsigned 16-bit. */ @SuppressWarnings("static-method") @@ -432,7 +439,7 @@ /* * freeTestData - * + * * Nulls arrays and forces garbage collection to free up memory. */ diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.extended; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Location node that is the sum of two other location nodes. Can represent locations in the form of + * [(base + x) + y] where base is a node and x and y are location nodes. + */ +@NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}") +public final class AddLocationNode extends LocationNode implements Canonicalizable { + + @Input private ValueNode x; + @Input private ValueNode y; + + public LocationNode getX() { + return (LocationNode) x; + } + + public LocationNode getY() { + return (LocationNode) y; + } + + public static AddLocationNode create(LocationNode x, LocationNode y, Graph graph) { + assert x.getValueKind().equals(y.getValueKind()) && x.locationIdentity() == y.locationIdentity(); + return graph.unique(new AddLocationNode(x.locationIdentity(), x.getValueKind(), x, y)); + } + + private AddLocationNode(Object identity, Kind kind, ValueNode x, ValueNode y) { + super(identity, kind); + this.x = x; + this.y = y; + } + + @Override + protected LocationNode addDisplacement(long displacement) { + LocationNode added = getX().addDisplacement(displacement); + return graph().unique(new AddLocationNode(locationIdentity(), getValueKind(), added, getY())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x instanceof ConstantLocationNode) { + return getY().addDisplacement(((ConstantLocationNode) x).displacement()); + } + if (y instanceof ConstantLocationNode) { + return getX().addDisplacement(((ConstantLocationNode) y).displacement()); + } + + if (x instanceof IndexedLocationNode && y instanceof IndexedLocationNode) { + IndexedLocationNode xIdx = (IndexedLocationNode) x; + IndexedLocationNode yIdx = (IndexedLocationNode) y; + if (xIdx.indexScaling() == yIdx.indexScaling()) { + long displacement = xIdx.displacement() + yIdx.displacement(); + ValueNode index = IntegerArithmeticNode.add(xIdx.index(), yIdx.index()); + return IndexedLocationNode.create(locationIdentity(), getValueKind(), displacement, index, graph(), xIdx.indexScaling()); + } + } + + return this; + } + + @Override + public Value generateLea(LIRGeneratorTool gen, Value base) { + Value xAddr = getX().generateLea(gen, base); + return getY().generateLea(gen, xAddr); + } + + @Override + public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) { + Value xAddr = getX().generateLea(gen, base); + return getY().generateLoad(gen, xAddr, deopting); + } + + @Override + public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) { + Value xAddr = getX().generateLea(gen, base); + getY().generateStore(gen, xAddr, value, deopting); + } + + @NodeIntrinsic + public static native Location addLocation(@ConstantNodeParameter Object identity, @ConstantNodeParameter Kind kind, Location x, Location y); +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -49,7 +49,7 @@ @Override public void generate(LIRGeneratorTool gen) { - Value addr = getLocation().generateLea(gen, getObject()); + Value addr = getLocation().generateLea(gen, gen.operand(getObject())); gen.setResult(this, addr); } } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.extended; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Location node that has a constant displacement. Can represent addresses of the form [base + disp] + * where base is a node and disp is a constant. + */ +@NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") +public class ConstantLocationNode extends LocationNode { + + private final long displacement; + + public long displacement() { + return displacement; + } + + public static ConstantLocationNode create(Object identity, Kind kind, long displacement, Graph graph) { + return graph.unique(new ConstantLocationNode(identity, kind, displacement)); + } + + protected ConstantLocationNode(Object identity, Kind kind, long displacement) { + super(identity, kind); + this.displacement = displacement; + } + + @Override + protected ConstantLocationNode addDisplacement(long x) { + return create(locationIdentity(), getValueKind(), displacement + x, graph()); + } + + @Override + public Value generateLea(LIRGeneratorTool gen, Value base) { + return gen.emitLea(base, displacement(), Value.ILLEGAL, 0); + } + + @Override + public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) { + return gen.emitLoad(getValueKind(), base, displacement(), Value.ILLEGAL, 0, deopting); + } + + @Override + public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) { + gen.emitStore(getValueKind(), base, displacement(), Value.ILLEGAL, 0, value, deopting); + } +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -53,7 +53,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, location().generateLoad(gen, object(), this)); + gen.setResult(this, location().generateLoad(gen, gen.operand(object()), this)); } @Override diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -28,13 +28,15 @@ import com.oracle.graal.nodes.spi.*; /** - * Extension of a {@linkplain LocationNode location} to include a scaled index. Can represent - * locations in the form of [base + index * scale + disp] where base and index are nodes and scale - * and disp are integer constants. + * Location node that has a displacement and a scaled index. Can represent locations in the form of + * [base + index * scale + disp] where base and index are nodes and scale and disp are integer + * constants. */ +@NodeInfo(nameTemplate = "IdxLoc {p#locationIdentity/s}") public final class IndexedLocationNode extends LocationNode implements Canonicalizable { @Input private ValueNode index; + private final long displacement; private final int indexScaling; /** @@ -44,8 +46,8 @@ return index; } - public static Object getArrayLocation(Kind elementKind) { - return elementKind; + public long displacement() { + return displacement; } /** @@ -55,43 +57,53 @@ return indexScaling; } - public static IndexedLocationNode create(Object identity, Kind kind, int displacement, ValueNode index, Graph graph, int indexScaling) { - return graph.unique(new IndexedLocationNode(identity, kind, index, displacement, indexScaling)); + public static IndexedLocationNode create(Object identity, Kind kind, long displacement, ValueNode index, Graph graph, int indexScaling) { + return graph.unique(new IndexedLocationNode(identity, kind, displacement, index, indexScaling)); + } + + private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int indexScaling) { + this(identity, kind, 0, index, indexScaling); } - private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int displacement, int indexScaling) { - super(identity, kind, displacement); + private IndexedLocationNode(Object identity, Kind kind, long displacement, ValueNode index, int indexScaling) { + super(identity, kind); this.index = index; + this.displacement = displacement; this.indexScaling = indexScaling; } @Override + protected LocationNode addDisplacement(long x) { + return create(locationIdentity(), getValueKind(), displacement + x, index, graph(), indexScaling); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { Constant constantIndex = index.asConstant(); if (constantIndex != null) { long constantIndexLong = constantIndex.asLong(); constantIndexLong *= indexScaling; - constantIndexLong += displacement(); - int constantIndexInt = (int) constantIndexLong; - if (constantIndexLong == constantIndexInt) { - return LocationNode.create(locationIdentity(), getValueKind(), constantIndexInt, graph()); - } + constantIndexLong += displacement; + return ConstantLocationNode.create(locationIdentity(), getValueKind(), constantIndexLong, graph()); } return this; } @Override - public Value generateLea(LIRGeneratorTool gen, ValueNode base) { - return gen.emitLea(gen.operand(base), displacement(), gen.operand(index()), indexScaling()); + public Value generateLea(LIRGeneratorTool gen, Value base) { + return gen.emitLea(base, displacement, gen.operand(index()), indexScaling()); } @Override - public Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) { - return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), deopting); + public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) { + return gen.emitLoad(getValueKind(), base, displacement, gen.operand(index()), indexScaling(), deopting); } @Override - public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) { - gen.emitStore(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), gen.operand(value), deopting); + public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) { + gen.emitStore(getValueKind(), base, displacement, gen.operand(index()), indexScaling(), value, deopting); } + + @NodeIntrinsic + public static native Location indexedLocation(@ConstantNodeParameter Object identity, @ConstantNodeParameter Kind kind, int index, @ConstantNodeParameter int indexScaling); } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -31,14 +30,12 @@ import com.oracle.graal.nodes.type.*; /** - * A location for a memory access in terms of the kind of value accessed and how to access it. The - * base version can represent addresses of the form [base + disp] where base is a node and disp is a - * constant. + * A location for a memory access in terms of the kind of value accessed and how to access it. All + * locations have the form [base + location], where base is a node and location is defined by + * subclasses of the {@link LocationNode}. */ -@NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") -public class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { +public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { - private int displacement; private Kind valueKind; private Object locationIdentity; @@ -70,22 +67,19 @@ */ public static final Object FINAL_LOCATION = createLocation("FINAL_LOCATION"); + /** + * Marker interface for locations in snippets. + */ + public interface Location { + } + public static Object getArrayLocation(Kind elementKind) { return elementKind; } - public int displacement() { - return displacement; - } - - public static LocationNode create(Object identity, Kind kind, int displacement, Graph graph) { - return graph.unique(new LocationNode(identity, kind, displacement)); - } - - protected LocationNode(Object identity, Kind kind, int displacement) { + protected LocationNode(Object identity, Kind kind) { super(StampFactory.extension()); assert kind != Kind.Illegal && kind != Kind.Void; - this.displacement = displacement; this.valueKind = kind; this.locationIdentity = identity; } @@ -98,20 +92,16 @@ return locationIdentity; } + protected abstract LocationNode addDisplacement(long displacement); + @Override public void generate(LIRGeneratorTool generator) { // nothing to do... } - public Value generateLea(LIRGeneratorTool gen, ValueNode base) { - return gen.emitLea(gen.operand(base), displacement(), Value.ILLEGAL, 0); - } + public abstract Value generateLea(LIRGeneratorTool gen, Value base); - public Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) { - return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, deopting); - } + public abstract Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting); - public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) { - gen.emitStore(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, gen.operand(value), deopting); - } + public abstract void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting); } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -44,7 +44,7 @@ } private ReadNode(ValueNode object, int displacement, Object locationIdentity, Kind kind) { - super(object, object.graph().add(new LocationNode(locationIdentity, kind, displacement)), StampFactory.forKind(kind)); + super(object, ConstantLocationNode.create(locationIdentity, kind, displacement, object.graph()), StampFactory.forKind(kind)); } private ReadNode(ValueNode object, ValueNode location, ValueNode dependency) { @@ -57,7 +57,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, location().generateLoad(gen, object(), this)); + gen.setResult(this, location().generateLoad(gen, gen.operand(object()), this)); } @Override @@ -73,8 +73,8 @@ public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) { MetaAccessProvider runtime = tool.runtime(); if (runtime != null && object != null && object.isConstant()) { - if (location.locationIdentity() == LocationNode.FINAL_LOCATION && location.getClass() == LocationNode.class) { - long displacement = location.displacement(); + if (location.locationIdentity() == LocationNode.FINAL_LOCATION && location instanceof ConstantLocationNode) { + long displacement = ((ConstantLocationNode) location).displacement(); Kind kind = location.getValueKind(); if (object.kind() == Kind.Object) { Object base = object.asConstant().asObject(); diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -84,7 +84,7 @@ @Override public void generate(LIRGeneratorTool gen) { - location().generateStore(gen, object(), value(), this); + location().generateStore(gen, gen.operand(object()), gen.operand(value()), this); } @NodeIntrinsic diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Tue Apr 23 08:44:07 2013 +0200 @@ -57,11 +57,11 @@ public abstract void emitMove(Value dst, Value src); - public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting); + public abstract Value emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting); - public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode deopting); + public abstract void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value input, DeoptimizingNode deopting); - public abstract Value emitLea(Value base, int displacement, Value index, int scale); + public abstract Value emitLea(Value base, long displacement, Value index, int scale); public abstract Value emitLea(StackSlot slot); diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java Tue Apr 23 08:44:07 2013 +0200 @@ -78,7 +78,7 @@ * Determines if this method should be substituted in all cases, even if inlining thinks it is * not important. * - * Not that this is still depending on whether inlining sees the correct call target, so it's + * Note that this is still depending on whether inlining sees the correct call target, so it's * only a hard guarantee for static and special invocations. */ boolean forced() default false; diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Tue Apr 23 08:44:07 2013 +0200 @@ -33,7 +33,7 @@ private final GenericStampType type; protected GenericStamp(GenericStampType type) { - super(Kind.Void); + super(type == GenericStampType.Void ? Kind.Void : Kind.Illegal); this.type = type; } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Tue Apr 23 08:44:07 2013 +0200 @@ -218,6 +218,10 @@ } private boolean isImplicitNullCheck(LocationNode location) { - return !(location instanceof IndexedLocationNode) && location.displacement() < target.implicitNullCheckLimit; + if (location instanceof ConstantLocationNode) { + return ((ConstantLocationNode) location).displacement() < target.implicitNullCheckLimit; + } else { + return false; + } } } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java Tue Apr 23 08:44:07 2013 +0200 @@ -22,6 +22,9 @@ */ package com.oracle.truffle.api.codegen.test; +import static com.oracle.truffle.api.codegen.test.TestHelper.*; +import static org.junit.Assert.*; + import org.junit.*; import com.oracle.truffle.api.codegen.*; @@ -29,9 +32,6 @@ import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; -import static junit.framework.Assert.*; -import static com.oracle.truffle.api.codegen.test.TestHelper.*; - public class BinaryNodeTest { @Test @@ -49,31 +49,12 @@ executeWith(node, new Object(), new Object()); } + @NodeChildren({@NodeChild("left"), @NodeChild("right")}) 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); - } } abstract static class AddNode extends BinaryNode { - public AddNode(ValueNode left, ValueNode right) { - super(left, right); - } - - public AddNode(AddNode prev) { - super(prev); - } - @Specialization int add(int left, int right) { return left + right; diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java Tue Apr 23 08:44:07 2013 +0200 @@ -23,7 +23,7 @@ package com.oracle.truffle.api.codegen.test; import static com.oracle.truffle.api.codegen.test.TestHelper.*; -import static junit.framework.Assert.*; +import static org.junit.Assert.*; import org.junit.*; @@ -32,7 +32,6 @@ import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrConcatFactory; import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrLengthFactory; import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrSubstrFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ChildrenNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; @@ -97,7 +96,7 @@ assertSame(context, executeWith(node)); } - @NodeClass(BuiltinNode.class) + @NodeClass(value = BuiltinNode.class, splitByMethodName = true) static class Str { private final String internal; @@ -162,23 +161,22 @@ } } - abstract static class BuiltinNode extends ChildrenNode { + @NodeChild(value = "children", type = ValueNode[].class) + abstract static class BuiltinNode extends ValueNode { protected final Context context; public BuiltinNode(BuiltinNode node) { - this(node.context, node.children); + this(node.context); } - public BuiltinNode(Context context, ValueNode... children) { - super(children); + public BuiltinNode(Context context) { this.context = context; } public Context getContext() { return context; } - } static class Context { diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.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/ExecuteEvaluatedTest.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,69 @@ +/* + * 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.*; +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; +import com.oracle.truffle.api.frame.*; + +public class ExecuteEvaluatedTest { + + /* Represents target[element] */ + @NodeChildren({@NodeChild("target"), @NodeChild("element")}) + abstract static class ReadElementNode extends ValueNode { + + @Specialization + int getInt(Object[] target, int element) { + return (int) target[element]; + } + + public abstract Object executeWith(VirtualFrame frame, Object targetValue); + } + + /* Represents target[element]() */ + @NodeChildren({@NodeChild("target"), @NodeChild(value = "element", type = ReadElementNode.class, executeWith = "target")}) + abstract static class ElementCallNode extends ValueNode { + + @Specialization + Object call(Object receiver, Object callTarget) { + return ((CallTarget) callTarget).call(new TestArguments(receiver)); + } + + } + + public static class TestArguments extends Arguments { + + private final Object receiver; + + public TestArguments(Object receiver) { + this.receiver = receiver; + } + + public Object getReceiver() { + return receiver; + } + + } + +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java Tue Apr 23 08:44:07 2013 +0200 @@ -23,14 +23,13 @@ package com.oracle.truffle.api.codegen.test; import static com.oracle.truffle.api.codegen.test.TestHelper.*; -import static junit.framework.Assert.*; import org.junit.*; +import static org.junit.Assert.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.codegen.test.GuardsTestFactory.GlobalFlagGuardFactory; import com.oracle.truffle.api.codegen.test.GuardsTestFactory.InvocationGuardFactory; -import com.oracle.truffle.api.codegen.test.TypeSystemTest.ChildrenNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode; @@ -52,19 +51,12 @@ assertEquals(1, InvocationGuard.genericInvocations); } - public abstract static class InvocationGuard extends ChildrenNode { + @NodeChildren({@NodeChild("value0"), @NodeChild("value1")}) + public abstract static class InvocationGuard extends ValueNode { static int specializedInvocations = 0; static int genericInvocations = 0; - public InvocationGuard(ValueNode... children) { - super(children); - } - - public InvocationGuard(InvocationGuard node) { - super(node); - } - boolean guard(int value0, int value1) { return value0 != Integer.MAX_VALUE; } @@ -95,18 +87,11 @@ assertEquals(42, executeWith(root, NULL)); } - public abstract static class GlobalFlagGuard extends ChildrenNode { + @NodeChild("expression") + public abstract static class GlobalFlagGuard extends ValueNode { static boolean globalFlag = false; - public GlobalFlagGuard(ValueNode... children) { - super(children); - } - - public GlobalFlagGuard(GlobalFlagGuard node) { - super(node); - } - static boolean globalFlagGuard() { return globalFlag; } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Tue Apr 23 08:44:07 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.codegen.test.BuiltinTest.*; import com.oracle.truffle.api.codegen.test.TypeSystemTest.*; /** @@ -46,7 +47,7 @@ List argumentList = new ArrayList<>(); argumentList.addAll(Arrays.asList(constants)); - if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) { + if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass()) || BuiltinNode.class.isAssignableFrom(factory.getNodeClass())) { argumentList.add(argumentNodes); } else { argumentList.addAll(Arrays.asList(argumentNodes)); diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java Tue Apr 23 08:44:07 2013 +0200 @@ -30,41 +30,40 @@ public class TypeSystemTest { - @TypeSystem({int.class, Str.class}) + @TypeSystem({int.class, Str.class, CallTarget.class, Object[].class}) static class SimpleTypes { } @TypeSystemReference(SimpleTypes.class) - abstract static class ValueNode extends Node { + public abstract static class ValueNode extends Node { - int executeInt(VirtualFrame frame) throws UnexpectedResultException { + public int executeInt(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectInteger(execute(frame)); } - Str executeStr(VirtualFrame frame) throws UnexpectedResultException { + public Str executeStr(VirtualFrame frame) throws UnexpectedResultException { return SimpleTypesGen.SIMPLETYPES.expectStr(execute(frame)); } - abstract Object execute(VirtualFrame frame); + public Object[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException { + return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame)); + } + + public abstract Object execute(VirtualFrame frame); + + @Override + public ValueNode copy() { + return (ValueNode) super.copy(); + } } - @TypeSystemReference(SimpleTypes.class) - abstract static class ChildrenNode extends ValueNode { - - @Children protected ValueNode[] children; - - public ChildrenNode(ValueNode... children) { - this.children = adoptChildren(children); - } - - public ChildrenNode(ChildrenNode node) { - this(node.children); - } + @NodeChild(value = "children", type = ValueNode[].class) + public abstract static class ChildrenNode extends ValueNode { } @TypeSystemReference(SimpleTypes.class) - static class TestRootNode extends RootNode { + public static class TestRootNode extends RootNode { @Child private E node; @@ -82,7 +81,7 @@ } } - static class TestArguments extends Arguments { + public static class TestArguments extends Arguments { private final Object[] values; @@ -100,7 +99,7 @@ } - static class ArgumentNode extends ValueNode { + public static class ArgumentNode extends ValueNode { final int index; @@ -109,7 +108,7 @@ } @Override - Object execute(VirtualFrame frame) { + public Object execute(VirtualFrame frame) { return ((TestArguments) frame.getArguments()).get(index); } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,36 @@ +/* + * 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.TYPE}) +public @interface NodeChild { + + String value() default ""; + + Class type() default NodeClass.InheritNode.class; + + String[] executeWith() default {}; +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChildren.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChildren.java Tue Apr 23 08:44:07 2013 +0200 @@ -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.TYPE}) +public @interface NodeChildren { + + NodeChild[] value() default {}; + +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java Tue Apr 23 08:44:07 2013 +0200 @@ -30,6 +30,11 @@ @Target({ElementType.TYPE}) public @interface NodeClass { - Class value(); + public static final class InheritNode extends Node { + } + + Class value() default InheritNode.class; + + boolean splitByMethodName() default false; } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java Tue Apr 23 08:44:07 2013 +0200 @@ -24,11 +24,6 @@ import java.lang.annotation.*; -/** - * - * - * - */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD}) public @interface TypeCast { diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -27,6 +27,7 @@ import javax.annotation.processing.*; import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; import com.oracle.truffle.codegen.processor.template.*; @@ -49,6 +50,7 @@ public final M parse(RoundEnvironment env, Element element) { this.roundEnv = env; + M model = null; try { AnnotationMirror mirror = null; if (getAnnotationType() != null) { @@ -58,13 +60,16 @@ if (!context.getTruffleTypes().verify(context, element, mirror)) { return null; } - M model = parse(element, mirror); + model = parse(element, mirror); if (model == null) { return null; } model.emitMessages((TypeElement) element, log); return filterErrorElements(model); + } catch (CompileErrorException e) { + log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); + return null; } finally { this.roundEnv = null; } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/CompileErrorException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/CompileErrorException.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,33 @@ +/* + * 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; + +public class CompileErrorException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public CompileErrorException(String message) { + super(message); + } + +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java Tue Apr 23 08:44:07 2013 +0200 @@ -29,7 +29,9 @@ import javax.annotation.processing.*; import javax.lang.model.element.*; import javax.lang.model.type.*; +import javax.lang.model.util.*; +import com.oracle.truffle.codegen.processor.ast.*; import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror; import com.oracle.truffle.codegen.processor.template.*; @@ -185,4 +187,26 @@ } + public TypeMirror reloadTypeElement(TypeElement type) { + return getType(type.getQualifiedName().toString()); + } + + public TypeMirror reloadType(TypeMirror type) { + if (type instanceof CodeTypeMirror) { + return type; + } else if (type.getKind().isPrimitive()) { + return type; + } + Types types = getEnvironment().getTypeUtils(); + + switch (type.getKind()) { + case ARRAY: + return types.getArrayType(reloadType(((ArrayType) type).getComponentType())); + case WILDCARD: + return types.getWildcardType(((WildcardType) type).getExtendsBound(), ((WildcardType) type).getSuperBound()); + case DECLARED: + return reloadTypeElement((TypeElement) (((DeclaredType) type).asElement())); + } + return type; + } } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Tue Apr 23 08:44:07 2013 +0200 @@ -43,8 +43,8 @@ private final TypeMirror nodeArray; private final TypeMirror unexpectedValueException; private final TypeMirror frame; - private final TypeMirror stableAnnotation; - private final TypeMirror contentStableAnnotation; + private final DeclaredType childAnnotation; + private final DeclaredType childrenAnnotation; private final TypeMirror typeConversion; private final TypeMirror truffleIntrinsics; @@ -55,8 +55,8 @@ nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node); unexpectedValueException = getRequired(context, UnexpectedResultException.class); frame = getRequired(context, VirtualFrame.class); - stableAnnotation = getRequired(context, Child.class); - contentStableAnnotation = getRequired(context, Children.class); + childAnnotation = getRequired(context, Child.class); + childrenAnnotation = getRequired(context, Children.class); typeConversion = getRequired(context, TypeConversion.class); truffleIntrinsics = getRequired(context, TruffleIntrinsics.class); } @@ -73,12 +73,12 @@ return false; } - private TypeMirror getRequired(ProcessorContext context, Class clazz) { + private DeclaredType getRequired(ProcessorContext context, Class clazz) { TypeMirror type = context.getType(clazz); if (type == null) { errors.add(String.format("Could not find required type: %s", clazz.getSimpleName())); } - return type; + return (DeclaredType) type; } public TypeMirror getTruffleIntrinsics() { @@ -105,11 +105,11 @@ return unexpectedValueException; } - public TypeMirror getStableAnnotation() { - return stableAnnotation; + public DeclaredType getChildAnnotation() { + return childAnnotation; } - public TypeMirror getContentStableAnnotation() { - return contentStableAnnotation; + public DeclaredType getChildrenAnnotation() { + return childrenAnnotation; } } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Tue Apr 23 08:44:07 2013 +0200 @@ -32,6 +32,7 @@ import javax.lang.model.util.*; import com.oracle.truffle.codegen.processor.ast.*; +import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror; import com.oracle.truffle.codegen.processor.compiler.*; /** @@ -63,17 +64,20 @@ return types; } + public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { + return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs)); + } + public static List collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, Class annotationClass) { - List result = Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName); + List result = new ArrayList<>(); + if (markerAnnotation != null) { + result.addAll(Utils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName)); + } AnnotationMirror explicit = Utils.findAnnotationMirror(context.getEnvironment(), element, annotationClass); if (explicit != null) { result.add(explicit); } - - for (AnnotationMirror mirror : result) { - assert Utils.typeEquals(mirror.getAnnotationType(), context.getType(annotationClass)); - } return result; } @@ -141,33 +145,100 @@ } } - /** - * True if t1 is assignable to t2. - */ - public static boolean isAssignable(TypeMirror t1, TypeMirror t2) { - if (typeEquals(t1, t2)) { + public static boolean isAssignable(ProcessorContext context, TypeMirror from, TypeMirror to) { + if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) { + return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to)); + } else { + return isAssignableImpl(context, from, to); + } + } + + private static boolean isAssignableImpl(ProcessorContext context, TypeMirror from, TypeMirror to) { + // JLS 5.1.1 identity conversion + if (Utils.typeEquals(from, to)) { return true; } - if (isPrimitive(t1) || isPrimitive(t2)) { - // non-equal primitive types + + // JLS 5.1.2 widening primitives + if (Utils.isPrimitive(from) && Utils.isPrimitive(to)) { + TypeKind fromKind = from.getKind(); + TypeKind toKind = to.getKind(); + switch (fromKind) { + case BYTE: + switch (toKind) { + case SHORT: + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case SHORT: + switch (toKind) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case CHAR: + switch (toKind) { + case INT: + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case INT: + switch (toKind) { + case LONG: + case FLOAT: + case DOUBLE: + return true; + } + break; + case LONG: + switch (toKind) { + case FLOAT: + case DOUBLE: + return true; + } + break; + case FLOAT: + switch (toKind) { + case DOUBLE: + return true; + } + break; + + } return false; - } - if (t1 instanceof ArrayType && t2 instanceof ArrayType) { - return isAssignable(((ArrayType) t1).getComponentType(), ((ArrayType) t2).getComponentType()); - } - - TypeElement e1 = fromTypeMirror(t1); - TypeElement e2 = fromTypeMirror(t2); - if (e1 == null || e2 == null) { + } else if (Utils.isPrimitive(from) || Utils.isPrimitive(to)) { return false; } - List superTypes = getSuperTypes(e1); + if (from instanceof ArrayType && to instanceof ArrayType) { + return isAssignable(context, ((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType()); + } + + TypeElement fromType = Utils.fromTypeMirror(from); + TypeElement toType = Utils.fromTypeMirror(to); + if (fromType == null || toType == null) { + return false; + } + // JLS 5.1.6 narrowing reference conversion + + List superTypes = Utils.getSuperTypes(fromType); for (TypeElement superType : superTypes) { - if (typeEquals(superType.asType(), t2)) { + if (Utils.typeEquals(superType.asType(), to)) { return true; } } + + // TODO more spec return false; } @@ -210,6 +281,8 @@ return b.toString(); case TYPEVAR: return "Any"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); default: throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); } @@ -247,6 +320,8 @@ return getWildcardName((WildcardType) mirror); case TYPEVAR: return "?"; + case ERROR: + throw new CompileErrorException("Type error " + mirror); default: throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); } @@ -313,6 +388,10 @@ return "void"; case TYPEVAR: return getSimpleName(mirror); + case ERROR: + throw new CompileErrorException("Type error " + mirror); + case NONE: + return "$none"; default: throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); } @@ -326,6 +405,10 @@ return mirror.getKind().isPrimitive(); } + public static boolean isPrimitiveOrVoid(TypeMirror mirror) { + return isPrimitive(mirror) || isVoid(mirror); + } + public static List getQualifiedSuperTypeNames(TypeElement element) { List types = getSuperTypes(element); List qualifiedNames = new ArrayList<>(); @@ -361,7 +444,7 @@ return null; } - private static List getElementHierarchy(Element e) { + public static List getElementHierarchy(Element e) { List elements = new ArrayList<>(); elements.add(e); @@ -579,7 +662,7 @@ @Override public Object visitEnumConstant(VariableElement c, Void p) { - return c.getConstantValue(); + return c; } @Override @@ -762,11 +845,7 @@ public static Modifier getVisibility(Set modifier) { for (Modifier mod : modifier) { - if (mod == Modifier.PUBLIC) { - return mod; - } else if (mod == Modifier.PRIVATE) { - return mod; - } else if (mod == Modifier.PROTECTED) { + if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) { return mod; } } @@ -803,4 +882,20 @@ return getQualifiedName(actualType).equals("java.lang.Object"); } + public static boolean isFieldAccessible(Element element, VariableElement variable) { + TypeElement type = Utils.findNearestEnclosingType(element); + TypeElement varType = Utils.findNearestEnclosingType(variable); + + while (type != null) { + if (typeEquals(type.asType(), varType.asType())) { + return true; + } + if (type.getSuperclass() != null) { + type = Utils.fromTypeMirror(type.getSuperclass()); + } else { + type = null; + } + } + return false; + } } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Tue Apr 23 08:44:07 2013 +0200 @@ -215,7 +215,7 @@ copy.addAnnotationMirror(mirror); } for (VariableElement var : method.getParameters()) { - copy.addParameter(var); + copy.addParameter(CodeVariableElement.clone(var)); } for (Element element : method.getEnclosedElements()) { copy.add(element); diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Tue Apr 23 08:44:07 2013 +0200 @@ -46,6 +46,11 @@ this.parent = parent; } + @Override + public String toString() { + return root.toString(); + } + public int getTreeCount() { return treeCount; } @@ -277,7 +282,13 @@ } public CodeTreeBuilder tree(CodeTree treeToAdd) { - return push((BuilderCodeTree) treeToAdd).end(); + if (treeToAdd instanceof BuilderCodeTree) { + return push((BuilderCodeTree) treeToAdd).end(); + } else { + BuilderCodeTree tree = new BuilderCodeTree(GROUP, null, null); + tree.add(treeToAdd); + return push(tree).end(); + } } public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeVariable.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,60 @@ +/* + * 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.ast; + +public class CodeTreeVariable extends CodeTree { + + private final String name; + + private CodeTree value; + + public CodeTreeVariable() { + super(CodeTreeKind.GROUP, null, null); + this.name = ""; + } + + public CodeTreeVariable(String name) { + super(CodeTreeKind.GROUP, null, null); + this.name = name; + } + + public String getName() { + return name; + } + + public void set(CodeTree tree) { + if (value == tree) { + return; + } + if (this.value != null) { + remove(this.value); + } + this.value = tree; + add(tree); + } + + public CodeTree get() { + return value; + } + +} diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Tue Apr 23 08:44:07 2013 +0200 @@ -64,11 +64,17 @@ public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType { - private final CodeTypeElement clazz; + private final TypeElement clazz; + private final List typeArguments; - public DeclaredCodeTypeMirror(CodeTypeElement clazz) { + public DeclaredCodeTypeMirror(TypeElement clazz) { + this(clazz, Collections. emptyList()); + } + + public DeclaredCodeTypeMirror(TypeElement clazz, List typeArguments) { super(TypeKind.DECLARED); this.clazz = clazz; + this.typeArguments = typeArguments; } @Override @@ -83,7 +89,7 @@ @Override public List getTypeArguments() { - return Collections.emptyList(); + return typeArguments; } @Override diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Tue Apr 23 08:44:07 2013 +0200 @@ -123,9 +123,9 @@ writeClassImpl(e); } - private String useImport(TypeMirror type) { + private String useImport(Element enclosedType, TypeMirror type) { if (imports != null) { - return imports.useImport(type); + return imports.createTypeReference(enclosedType, type); } else { return Utils.getSimpleName(type); } @@ -133,7 +133,7 @@ private void writeClassImpl(CodeTypeElement e) { for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(annotation); + visitAnnotation(e, annotation); writeLn(); } @@ -145,12 +145,12 @@ } write(e.getSimpleName()); if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { - write(" extends ").write(useImport(e.getSuperclass())); + write(" extends ").write(useImport(e, e.getSuperclass())); } if (e.getImplements().size() > 0) { write(" implements "); for (int i = 0; i < e.getImplements().size(); i++) { - write(useImport(e.getImplements().get(i))); + write(useImport(e, e.getImplements().get(i))); if (i < e.getImplements().size() - 1) { write(", "); } @@ -255,8 +255,8 @@ Element parent = f.getEnclosingElement(); for (AnnotationMirror annotation : f.getAnnotationMirrors()) { - visitAnnotation(annotation); - writeLn(); + visitAnnotation(f, annotation); + write(" "); } CodeTree init = null; @@ -275,7 +275,7 @@ } } else { writeModifiers(f.getModifiers()); - write(useImport(f.asType())); + write(useImport(f, f.asType())); if (f.getEnclosingElement().getKind() == ElementKind.METHOD) { ExecutableElement method = (ExecutableElement) f.getEnclosingElement(); @@ -294,8 +294,8 @@ return null; } - public void visitAnnotation(AnnotationMirror e) { - write("@").write(useImport(e.getAnnotationType())); + public void visitAnnotation(Element enclosedElement, AnnotationMirror e) { + write("@").write(useImport(enclosedElement, e.getAnnotationType())); if (!e.getElementValues().isEmpty()) { write("("); @@ -303,7 +303,7 @@ Map values = e.getElementValues(); if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) { - visitAnnotationValue(values.get(defaultElement)); + visitAnnotationValue(enclosedElement, values.get(defaultElement)); } else { Set methodsSet = values.keySet(); List methodsList = new ArrayList<>(); @@ -327,7 +327,7 @@ AnnotationValue value = values.get(method); write(method.getSimpleName().toString()); write(" = "); - visitAnnotationValue(value); + visitAnnotationValue(enclosedElement, value); if (i < methodsList.size() - 1) { write(", "); @@ -339,12 +339,18 @@ } } - public void visitAnnotationValue(AnnotationValue e) { - e.accept(new AnnotationValueWriterVisitor(), null); + public void visitAnnotationValue(Element enclosedElement, AnnotationValue e) { + e.accept(new AnnotationValueWriterVisitor(enclosedElement), null); } private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7 { + private final Element enclosedElement; + + public AnnotationValueWriterVisitor(Element enclosedElement) { + this.enclosedElement = enclosedElement; + } + @Override public Void visitBoolean(boolean b, Void p) { write(Boolean.toString(b)); @@ -403,14 +409,14 @@ @Override public Void visitType(TypeMirror t, Void p) { - write(useImport(t)); + write(useImport(enclosedElement, t)); write(".class"); return null; } @Override public Void visitEnumConstant(VariableElement c, Void p) { - write(useImport(c.asType())); + write(useImport(enclosedElement, c.asType())); write("."); write(c.getSimpleName().toString()); return null; @@ -418,7 +424,7 @@ @Override public Void visitAnnotation(AnnotationMirror a, Void p) { - AbstractCodeWriter.this.visitAnnotation(a); + AbstractCodeWriter.this.visitAnnotation(enclosedElement, a); return null; } @@ -427,7 +433,7 @@ write("{"); for (int i = 0; i < vals.size(); i++) { AnnotationValue value = vals.get(i); - AbstractCodeWriter.this.visitAnnotationValue(value); + AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value); if (i < vals.size() - 1) { write(", "); } @@ -459,14 +465,14 @@ @Override public Void visitExecutable(CodeExecutableElement e, Void p) { for (AnnotationMirror annotation : e.getAnnotationMirrors()) { - visitAnnotation(annotation); + visitAnnotation(e, annotation); writeLn(); } writeModifiers(e.getModifiers()); if (e.getReturnType() != null) { - write(useImport(e.getReturnType())); + write(useImport(e, e.getReturnType())); write(" "); } write(e.getSimpleName()); @@ -485,7 +491,7 @@ if (throwables.size() > 0) { write(" throws "); for (int i = 0; i < throwables.size(); i++) { - write(useImport(throwables.get(i))); + write(useImport(e, throwables.get(i))); if (i < throwables.size() - 1) { write(", "); } @@ -549,20 +555,20 @@ break; case STATIC_FIELD_REFERENCE: if (e.getString() != null) { - write(imports.useStaticFieldImport(e.getType(), e.getString())); + write(imports.createStaticFieldReference(e, e.getType(), e.getString())); } else { write("null"); } break; case STATIC_METHOD_REFERENCE: if (e.getString() != null) { - write(imports.useStaticMethodImport(e.getType(), e.getString())); + write(imports.createStaticMethodReference(e, e.getType(), e.getString())); } else { write("null"); } break; case TYPE: - write(useImport(e.getType())); + write(useImport(e, e.getType())); break; default: assert false; diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Tue Apr 23 08:44:07 2013 +0200 @@ -35,8 +35,7 @@ public final class OrganizedImports { - private final Map importUsage = new HashMap<>(); - private final Map staticImportUsage = new HashMap<>(); + private final Set staticImportUsage = new HashSet<>(); private final Map simpleNamesUsed = new HashMap<>(); @@ -53,16 +52,33 @@ public static OrganizedImports organize(CodeTypeElement topLevelClass) { OrganizedImports organized = new OrganizedImports(topLevelClass); - - OrganizedImports.ReferenceCollector reference = new ReferenceCollector(); - topLevelClass.accept(reference, null); - - OrganizedImports.ImportResolver resolver = new ImportResolver(reference, organized); - topLevelClass.accept(resolver, null); + organized.organizeImpl(); return organized; } - public String useImport(TypeMirror type) { + private void organizeImpl() { + ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor(); + topLevelClass.accept(reference, null); + + processStaticImports(topLevelClass); + List types = Utils.getSuperTypes(topLevelClass); + for (TypeElement typeElement : types) { + processStaticImports(typeElement); + } + + for (TypeMirror type : staticImportUsage) { + TypeElement element = fromTypeMirror(type); + if (element != null) { + // already processed by supertype + if (types.contains(element)) { + continue; + } + processStaticImports(element); + } + } + } + + public String createTypeReference(Element enclosedElement, TypeMirror type) { switch (type.getKind()) { case BOOLEAN: case BYTE: @@ -75,11 +91,11 @@ case VOID: return Utils.getSimpleName(type); case DECLARED: - return createDeclaredTypeName((DeclaredType) type); + return createDeclaredTypeName(enclosedElement, (DeclaredType) type); case ARRAY: - return useImport(((ArrayType) type).getComponentType()) + "[]"; + return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]"; case WILDCARD: - return createWildcardName((WildcardType) type); + return createWildcardName(enclosedElement, (WildcardType) type); case TYPEVAR: return "?"; default: @@ -87,29 +103,50 @@ } } - private String createWildcardName(WildcardType type) { + public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) { + return createStaticReference(enclosedElement, type, fieldName, ambiguousStaticFields, declaredStaticFields); + } + + public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) { + return createStaticReference(enclosedElement, type, methodName, ambiguousStaticMethods, declaredStaticMethods); + } + + private String createStaticReference(Element enclosedElement, TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { + if (ambiguousSymbols.contains(name)) { + // ambiguous import + return createTypeReference(enclosedElement, type) + "." + name; + } else if (!declaredSymbols.contains(name)) { + // not imported at all + return createTypeReference(enclosedElement, type) + "." + name; + } else { + // import declared and not ambiguous + return name; + } + } + + private String createWildcardName(Element enclosedElement, WildcardType type) { StringBuilder b = new StringBuilder(); if (type.getExtendsBound() != null) { - b.append("? extends ").append(useImport(type.getExtendsBound())); + b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound())); } else if (type.getSuperBound() != null) { - b.append("? super ").append(useImport(type.getExtendsBound())); + b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound())); } return b.toString(); } - private String createDeclaredTypeName(DeclaredType type) { + private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) { String name = type.asElement().getSimpleName().toString(); - TypeMirror usedByType = simpleNamesUsed.get(name); - if (usedByType == null) { - simpleNamesUsed.put(name, type); - usedByType = type; - } + if (needsImport(enclosedElement, type)) { + TypeMirror usedByType = simpleNamesUsed.get(name); + if (usedByType == null) { + simpleNamesUsed.put(name, type); + usedByType = type; + } - if (typeEquals(type, usedByType)) { - addUsage(type, importUsage); - } else { - name = getQualifiedName(type); + if (!typeEquals(type, usedByType)) { + name = getQualifiedName(type); + } } if (type.getTypeArguments().size() == 0) { @@ -120,7 +157,7 @@ b.append("<"); if (type.getTypeArguments().size() > 0) { for (int i = 0; i < type.getTypeArguments().size(); i++) { - b.append(useImport(type.getTypeArguments().get(i))); + b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i))); if (i < type.getTypeArguments().size() - 1) { b.append(", "); } @@ -130,44 +167,15 @@ return b.toString(); } - public String useStaticFieldImport(TypeMirror type, String fieldName) { - return useStaticImport(type, fieldName, ambiguousStaticFields, declaredStaticFields); - } - - public String useStaticMethodImport(TypeMirror type, String methodName) { - return useStaticImport(type, methodName, ambiguousStaticMethods, declaredStaticMethods); - } - - private String useStaticImport(TypeMirror type, String name, Set ambiguousSymbols, Set declaredSymbols) { - if (ambiguousSymbols.contains(name)) { - // ambiguous import - return useImport(type) + "." + name; - } else if (!declaredSymbols.contains(name)) { - // not imported at all - return useImport(type) + "." + name; - } else { - // import declared and not ambiguous - addUsage(type, staticImportUsage); - return name; - } - } - public Set generateImports() { Set imports = new HashSet<>(); - imports.addAll(generateImports(topLevelClass, importUsage.keySet())); - imports.addAll(generateStaticImports(topLevelClass, staticImportUsage.keySet())); + imports.addAll(generateImports(simpleNamesUsed.values())); + imports.addAll(generateStaticImports(staticImportUsage)); return imports; } - void clearStaticImports() { - declaredStaticFields.clear(); - declaredStaticMethods.clear(); - ambiguousStaticFields.clear(); - ambiguousStaticMethods.clear(); - } - boolean processStaticImports(TypeElement element) { Set importedMethods = new HashSet<>(); List methods = ElementFilter.methodsIn(element.getEnclosedElements()); @@ -217,37 +225,39 @@ return allAmbiguous; } - private static Set generateImports(CodeTypeElement e, Set toGenerate) { - Set autoImportedTypes = new HashSet<>(); + private boolean needsImport(Element enclosedElement, TypeMirror importType) { + String importPackagName = getPackageName(importType); + if (importPackagName == null) { + return false; + } else if (importPackagName.equals("java.lang")) { + return false; + } else if (importPackagName.equals(getPackageName(topLevelClass)) && Utils.isTopLevelClass(importType)) { + return false; // same package name -> no import + } + + List elements = Utils.getElementHierarchy(enclosedElement); - // if type is declared inside a super type of this class -> no import - collectSuperTypeImports(e, autoImportedTypes); - collectInnerTypeImports(e, autoImportedTypes); + Set autoImportedTypes = new HashSet<>(); + for (Element element : elements) { + if (element.getKind().isClass()) { + collectSuperTypeImports((TypeElement) element, autoImportedTypes); + collectInnerTypeImports((TypeElement) element, autoImportedTypes); + } + } + String qualifiedName = getQualifiedName(importType); + if (autoImportedTypes.contains(qualifiedName)) { + return false; + } + + return true; + } + + private static Set generateImports(Collection toGenerate) { TreeSet importObjects = new TreeSet<>(); for (TypeMirror importType : toGenerate) { - String importTypePackageName = getPackageName(importType); - if (importTypePackageName == null) { - continue; // no package name -> no import - } - - if (importTypePackageName.equals("java.lang")) { - continue; // java.lang is automatically imported - } - - if (importTypePackageName.equals(getPackageName(e)) && Utils.isTopLevelClass(importType)) { - continue; // same package name -> no import - } - - String qualifiedName = getQualifiedName(importType); - - if (autoImportedTypes.contains(qualifiedName)) { - continue; - } - importObjects.add(new CodeImport(importType, getQualifiedName(importType), false)); } - return importObjects; } @@ -268,12 +278,12 @@ } } - private static Set generateStaticImports(CodeTypeElement e, Set toGenerate) { + private Set generateStaticImports(Set toGenerate) { Set autoImportedStaticTypes = new HashSet<>(); // if type is declared inside a super type of this class -> no import - autoImportedStaticTypes.add(getQualifiedName(e)); - autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(e)); + autoImportedStaticTypes.add(getQualifiedName(topLevelClass)); + autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(topLevelClass)); TreeSet importObjects = new TreeSet<>(); for (TypeMirror importType : toGenerate) { @@ -292,73 +302,52 @@ return importObjects; } - private static void addUsage(TypeMirror type, Map usageMap) { - if (type != null) { - Integer value = usageMap.get(type); - if (value == null) { - usageMap.put(type, 1); - } else { - usageMap.put(type, value + 1); - } - } - } - - private static class ReferenceCollector extends CodeElementScanner { - - final Map typeReferences = new HashMap<>(); - final Map staticTypeReferences = new HashMap<>(); + private abstract static class TypeReferenceVisitor extends CodeElementScanner { @Override public void visitTree(CodeTree e, Void p) { if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - addStaticImport(e.getType()); + visitStaticFieldReference(e, e.getType(), e.getString()); } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - addStaticImport(e.getType()); - } else { - addImport(e.getType()); + visitStaticMethodReference(e, e.getType(), e.getString()); + } else if (e.getType() != null) { + visitTypeReference(e, e.getType()); } super.visitTree(e, p); } @Override public Void visitExecutable(CodeExecutableElement e, Void p) { - visitAnnotations(e.getAnnotationMirrors()); + visitAnnotations(e, e.getAnnotationMirrors()); if (e.getReturnType() != null) { - addImport(e.getReturnType()); + visitTypeReference(e, e.getReturnType()); } for (TypeMirror type : e.getThrownTypes()) { - addImport(type); + visitTypeReference(e, type); } return super.visitExecutable(e, p); } @Override public Void visitType(CodeTypeElement e, Void p) { - visitAnnotations(e.getAnnotationMirrors()); + visitAnnotations(e, e.getAnnotationMirrors()); - addImport(e.getSuperclass()); + visitTypeReference(e, e.getSuperclass()); for (TypeMirror type : e.getImplements()) { - addImport(type); + visitTypeReference(e, type); } return super.visitType(e, p); } - @Override - public Void visitVariable(VariableElement f, Void p) { - visitAnnotations(f.getAnnotationMirrors()); - addImport(f.asType()); - return super.visitVariable(f, p); - } - - private void visitAnnotations(List mirrors) { + private void visitAnnotations(Element enclosingElement, List mirrors) { for (AnnotationMirror mirror : mirrors) { - visitAnnotation(mirror); + visitAnnotation(enclosingElement, mirror); } } - public void visitAnnotation(AnnotationMirror e) { - addImport(e.getAnnotationType()); + public void visitAnnotation(Element enclosingElement, AnnotationMirror e) { + visitTypeReference(enclosingElement, e.getAnnotationType()); if (!e.getElementValues().isEmpty()) { Map values = e.getElementValues(); Set methodsSet = values.keySet(); @@ -372,17 +361,23 @@ for (int i = 0; i < methodsList.size(); i++) { AnnotationValue value = values.get(methodsList.get(i)); - visitAnnotationValue(value); + visitAnnotationValue(enclosingElement, value); } } } - public void visitAnnotationValue(AnnotationValue e) { - e.accept(new AnnotationValueReferenceVisitor(), null); + public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) { + e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null); } private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7 { + private final Element enclosingElement; + + public AnnotationValueReferenceVisitor(Element enclosedElement) { + this.enclosingElement = enclosedElement; + } + @Override public Void visitBoolean(boolean b, Void p) { return null; @@ -430,95 +425,67 @@ @Override public Void visitType(TypeMirror t, Void p) { - addImport(t); + visitTypeReference(enclosingElement, t); return null; } @Override public Void visitEnumConstant(VariableElement c, Void p) { - addImport(c.asType()); + visitTypeReference(enclosingElement, c.asType()); return null; } @Override public Void visitAnnotation(AnnotationMirror a, Void p) { - ReferenceCollector.this.visitAnnotation(a); + TypeReferenceVisitor.this.visitAnnotation(enclosingElement, 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)); + TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i)); } return null; } } @Override + public Void visitVariable(VariableElement f, Void p) { + visitAnnotations(f, f.getAnnotationMirrors()); + visitTypeReference(f, f.asType()); + return super.visitVariable(f, p); + } + + @Override public void visitImport(CodeImport e, Void p) { } - private void addStaticImport(TypeMirror type) { - addUsage(type, staticTypeReferences); + public abstract void visitTypeReference(Element enclosedType, TypeMirror type); + + public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName); + + public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName); + + } + + private class ImportTypeReferenceVisitor extends TypeReferenceVisitor { + + @Override + public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); } - private void addImport(TypeMirror type) { - addUsage(type, typeReferences); + @Override + public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) { + staticImportUsage.add(type); + } + + @Override + public void visitTypeReference(Element enclosedType, TypeMirror type) { + createTypeReference(enclosedType, type); } } - private static class ImportResolver extends CodeElementScanner { - - private final ReferenceCollector collector; - private final OrganizedImports organizedImports; - - public ImportResolver(OrganizedImports.ReferenceCollector collector, OrganizedImports organizedImports) { - this.collector = collector; - this.organizedImports = organizedImports; - } - - @Override - public Void visitType(CodeTypeElement e, Void p) { - if (e.isTopLevelClass()) { - organizedImports.clearStaticImports(); - - organizedImports.processStaticImports(e); - List types = Utils.getSuperTypes(e); - for (TypeElement typeElement : types) { - organizedImports.processStaticImports(typeElement); - } - - for (TypeMirror type : collector.staticTypeReferences.keySet()) { - TypeElement element = fromTypeMirror(type); - if (element != null) { - // already processed by supertype - if (types.contains(element)) { - continue; - } - organizedImports.processStaticImports(element); - } - } - - for (TypeMirror imp : collector.typeReferences.keySet()) { - organizedImports.useImport(imp); - } - } - return super.visitType(e, p); - } - - @Override - public void visitTree(CodeTree e, Void p) { - if (e.getCodeKind() == CodeTreeKind.TYPE) { - organizedImports.useImport(e.getType()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { - organizedImports.useStaticFieldImport(e.getType(), e.getString()); - } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { - organizedImports.useStaticMethodImport(e.getType(), e.getString()); - } - super.visitTree(e, p); - } - } - } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java Tue Apr 23 08:44:07 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.codegen.processor.node; +import java.util.*; + import javax.lang.model.element.*; import com.oracle.truffle.codegen.processor.*; @@ -59,6 +61,47 @@ return getMethod().getModifiers().contains(Modifier.FINAL); } + public boolean isAbstract() { + return getMethod().getModifiers().contains(Modifier.ABSTRACT); + } + + public int getEvaluatedCount() { + int count = 0; + for (ActualParameter parameter : getParameters()) { + if (parameter.getSpecification().isSignature()) { + count++; + } + } + return count; + } + + public boolean startsWithSignature(TemplateMethod method) { + for (ActualParameter param : getParameters()) { + if (!param.getSpecification().isSignature()) { + continue; + } + ActualParameter foundParam = method.findParameter(param.getLocalName()); + if (foundParam != null) { + TypeData actualType = param.getTypeSystemType(); + TypeData foundType = foundParam.getTypeSystemType(); + if (actualType == null || foundType == null || !actualType.equalsType(foundType)) { + return false; + } + } + } + return true; + } + + public boolean hasGenericSignature() { + List types = getSignature(); + for (TypeData typeData : types) { + if (!typeData.isGeneric()) { + return false; + } + } + return true; + } + @Override public int hashCode() { return type.hashCode(); diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -29,6 +29,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -42,27 +43,37 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - - List types = new ArrayList<>(); - types.addAll(getNode().getTypeSystem().getPrimitiveTypeMirrors()); - types.add(getContext().getType(void.class)); - - ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types); - returnTypeSpec.setSignature(true); - MethodSpec spec = new MethodSpec(returnTypeSpec); - spec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); + spec.setVariableRequiredArguments(true); + ParameterSpec other = new ParameterSpec("other", nodeTypeMirrors(getNode())); + other.setCardinality(Cardinality.MANY); + other.setSignature(true); + other.setIndexed(true); + spec.addRequired(other); return spec; } @Override public final boolean isParsable(ExecutableElement method) { - boolean parsable = method.getSimpleName().toString().startsWith("execute"); - return parsable; + if (method.getModifiers().contains(Modifier.STATIC)) { + return false; + } else if (method.getModifiers().contains(Modifier.NATIVE)) { + return false; + } + return method.getSimpleName().toString().startsWith("execute"); + } + + @Override + protected List nodeTypeMirrors(NodeData nodeData) { + // executable types not yet available + List types = new ArrayList<>(nodeData.getTypeSystem().getPrimitiveTypeMirrors()); + types.add(nodeData.getTypeSystem().getVoidType().getPrimitiveType()); + return types; } @Override public ExecutableTypeData create(TemplateMethod method) { - TypeData resolvedType = method.getReturnType().getActualTypeData(getNode().getTypeSystem()); + TypeData resolvedType = method.getReturnType().getTypeSystemType(); return new ExecutableTypeData(method, getNode().getTypeSystem(), resolvedType); } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -40,7 +40,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, null); + return createDefaultMethodSpec(method, mirror, true, null); } @Override diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.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/NodeChildData.java Tue Apr 23 08:44:07 2013 +0200 @@ -0,0 +1,119 @@ +/* + * 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.node; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.template.*; + +public class NodeChildData extends MessageContainer { + + public enum Cardinality { + ONE, MANY; + + public boolean isMany() { + return this == MANY; + } + + public boolean isOne() { + return this == ONE; + } + } + + public enum ExecutionKind { + DEFAULT, SHORT_CIRCUIT + } + + private final Element sourceElement; + private final AnnotationMirror sourceAnnotationMirror; + + private final String name; + private final TypeMirror type; + private final Element accessElement; + + private final Cardinality cardinality; + private final ExecutionKind executionKind; + private NodeData nodeData; + + public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, Element accessElement, Cardinality cardinality, ExecutionKind executionKind) { + this.sourceElement = sourceElement; + this.sourceAnnotationMirror = sourceMirror; + this.name = name; + this.type = nodeType; + this.accessElement = accessElement; + this.cardinality = cardinality; + this.executionKind = executionKind; + } + + @Override + public Element getMessageElement() { + return sourceElement; + } + + @Override + public AnnotationMirror getMessageAnnotation() { + return sourceAnnotationMirror; + } + + public boolean isShortCircuit() { + return executionKind == ExecutionKind.SHORT_CIRCUIT; + } + + void setNode(NodeData nodeData) { + this.nodeData = nodeData; + if (nodeData != null) { + getMessages().addAll(nodeData.collectMessages()); + } + } + + public Element getAccessElement() { + return accessElement; + } + + public TypeMirror getNodeType() { + return type; + } + + public Cardinality getCardinality() { + return cardinality; + } + + public ExecutionKind getExecutionKind() { + return executionKind; + } + + public NodeData getNodeData() { + return nodeData; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", execution=" + executionKind + ", node=" + getNodeData() + "]"; + } + +} diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Tue Apr 23 08:44:07 2013 +0200 @@ -34,8 +34,8 @@ import com.oracle.truffle.api.codegen.*; 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.node.NodeChildData.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -88,11 +88,12 @@ continue; } - method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); + method.addParameter(new CodeVariableElement(parameter.getType(), valueName(parameter))); } } - private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) { + private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, + boolean includeImplicit) { if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) { builder.string("frameValue"); } @@ -109,15 +110,34 @@ continue; } + ActualParameter sourceParameter = source.findParameter(parameter.getLocalName()); + if (unexpectedValueName != null && parameter.getLocalName().equals(unexpectedValueName)) { - builder.cast(parameter.getActualType(), CodeTreeBuilder.singleString("ex.getResult()")); + builder.cast(parameter.getType(), CodeTreeBuilder.singleString("ex.getResult()")); + } else if (sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); } else { builder.string(valueName(parameter)); } } } - private static CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { + private static String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) { + if (sourceParameter != null) { + if (!sourceParameter.getSpecification().isSignature()) { + return valueName(targetParameter); + } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) { + if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) { + return castValueName(targetParameter); + } + } + return valueName(targetParameter); + } else { + return valueName(targetParameter); + } + } + + private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { CodeTreeBuilder builder = parent.create(); boolean castedValues = sourceMethod != targetMethod; @@ -129,9 +149,8 @@ } TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement()); NodeData node = (NodeData) targetMethod.getTemplate(); - TypeSystemData typeSystem = node.getTypeSystem(); - boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType()); + boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType()); if (accessible) { if (builder.findMethod().getModifiers().contains(STATIC)) { if (method.getModifiers().contains(STATIC)) { @@ -140,7 +159,11 @@ builder.string(THIS_NODE_LOCAL_VAR_NAME); } } else { - builder.string("super"); + if (targetMethod instanceof ExecutableTypeData) { + builder.string("this"); + } else { + builder.string("super"); + } } } else { if (method.getModifiers().contains(STATIC)) { @@ -156,17 +179,8 @@ ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); assert parameter != null; - if (castedValues) { - NodeFieldData field = node.findField(parameter.getSpecification().getName()); - if (field == null) { - builder.string(valueName(parameter)); - } else { - if (Utils.typeEquals(sourceParameter.getActualType(), parameter.getActualType())) { - builder.string(valueName(parameter)); - } else { - builder.string(castValueName(parameter)); - } - } + if (castedValues && sourceParameter != null) { + builder.string(valueName(sourceParameter, parameter)); } else { builder.string(valueName(parameter)); } @@ -180,7 +194,7 @@ if (valueParameter == null) { valueParameter = targetParameter; } - TypeData targetType = targetParameter.getActualTypeData(typeSystem); + TypeData targetType = targetParameter.getTypeSystemType(); if (targetParameter.isImplicit() || valueParameter.isImplicit()) { continue; @@ -188,7 +202,7 @@ TypeData valueType = null; if (valueParameter != null) { - valueType = valueParameter.getActualTypeData(typeSystem); + valueType = valueParameter.getTypeSystemType(); } if (targetParameter.getSpecification().isLocal()) { @@ -203,7 +217,15 @@ } else if (unexpectedValueName != null && targetParameter.getLocalName().equals(unexpectedValueName)) { builder.string("ex.getResult()"); } else if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { + builder.startGroup(); + + if (valueType != null && sourceMethod.getMethodName().equals(targetMethod.getMethodName()) && !valueType.isGeneric() && targetType.isGeneric()) { + builder.string("("); + builder.type(targetType.getPrimitiveType()); + builder.string(") "); + } builder.string(valueName(targetParameter)); + builder.end(); } else { builder.string(castValueName(targetParameter)); } @@ -214,8 +236,14 @@ return builder.getRoot(); } - private static String genClassName(Template operation) { - return getSimpleName(operation.getTemplateType()) + "Gen"; + private static String genClassName(NodeData node) { + String nodeid = node.getNodeId(); + if (nodeid.endsWith("Node") && !nodeid.equals("Node")) { + nodeid = nodeid.substring(0, nodeid.length() - 4); + } + String name = Utils.firstLetterUpperCase(nodeid); + name += "GenNode"; + return name; } private String generatedGenericMethodName(SpecializationData specialization) { @@ -243,10 +271,10 @@ return prefix; } - private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, String value) { + private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, CodeTree value) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); startCallTypeSystemMethod(context, builder, node, methodName); - builder.string(value); + builder.tree(value); builder.end().end(); return builder.getRoot(); } @@ -277,11 +305,11 @@ valuesNeedsCast = new HashSet<>(); for (GuardData guard : targetSpecialization.getGuards()) { for (ActualParameter parameter : guard.getParameters()) { - NodeFieldData field = node.findField(parameter.getSpecification().getName()); + NodeChildData field = node.findChild(parameter.getSpecification().getName()); if (field == null) { continue; } - TypeData typeData = parameter.getActualTypeData(node.getTypeSystem()); + TypeData typeData = parameter.getTypeSystemType(); if (typeData != null && !typeData.isGeneric()) { valuesNeedsCast.add(parameter.getLocalName()); } @@ -325,7 +353,7 @@ return builder.getRoot(); } - private static CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { + private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { CodeTreeBuilder builder = new CodeTreeBuilder(parent); String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; if (guardedSpecialization.getGuards().size() > 0) { @@ -344,8 +372,8 @@ CodeTreeBuilder builder = new CodeTreeBuilder(parent); // Implict guards based on method signature for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { continue; } ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); @@ -369,8 +397,8 @@ // Implict guards based on method signature String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; for (ActualParameter guardedParam : guardedSpecialization.getParameters()) { - NodeFieldData field = guardedSpecialization.getNode().findField(guardedParam.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName()); + if (field == null) { continue; } ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName()); @@ -388,12 +416,12 @@ return builder.isEmpty() ? null : builder.getRoot(); } - private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { NodeData node = field.getNodeData(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); - TypeData targetType = target.getActualTypeData(node.getTypeSystem()); - TypeData sourceType = source.getActualTypeData(node.getTypeSystem()); + TypeData targetType = target.getTypeSystemType(); + TypeData sourceType = source.getTypeSystemType(); if (targetType.equalsType(sourceType) || targetType.isGeneric()) { return null; @@ -409,7 +437,7 @@ builder.string(" || "); } - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem()))); + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getTypeSystemType())); builder.string(valueName(source)); builder.end().end(); // call @@ -422,14 +450,12 @@ return builder.getRoot(); } - private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, ActualParameter target) { NodeData node = field.getNodeData(); - TypeSystemData typeSystem = node.getTypeSystem(); + TypeData sourceType = source.getTypeSystemType(); + TypeData targetType = target.getTypeSystemType(); - TypeData sourceType = source.getActualTypeData(typeSystem); - TypeData targetType = target.getActualTypeData(typeSystem); - - if (targetType.equalsType(sourceType) || targetType.isGeneric()) { + if (!sourceType.needsCastTo(targetType)) { return null; } @@ -440,9 +466,9 @@ condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); } - CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target)); + CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), CodeTreeBuilder.singleString(valueName(target))); - return createLazyAssignment(parent, castValueName(target), target.getActualType(), condition, value); + return createLazyAssignment(parent, castValueName(target), target.getType(), condition, value); } /** @@ -483,22 +509,49 @@ builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); } + private static List findUserConstructors(TypeMirror nodeType) { + List constructors = new ArrayList<>(); + for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(nodeType).getEnclosedElements())) { + if (constructor.getModifiers().contains(PRIVATE)) { + continue; + } + if (isCopyConstructor(constructor)) { + continue; + } + constructors.add(constructor); + } + + if (constructors.isEmpty()) { + constructors.add(new CodeExecutableElement(null, Utils.getSimpleName(nodeType))); + } + + return constructors; + } + + private static boolean isCopyConstructor(ExecutableElement element) { + if (element.getParameters().size() != 1) { + return false; + } + VariableElement var = element.getParameters().get(0); + TypeElement type = Utils.findNearestEnclosingType(var); + + if (!Utils.typeEquals(var.asType(), type.asType())) { + return false; + } + return true; + } + @Override protected void createChildren(NodeData node) { Map> childTypes = new LinkedHashMap<>(); - if (node.getDeclaredChildren() != null && !node.getDeclaredChildren().isEmpty()) { - for (NodeData nodeChild : node.getDeclaredChildren()) { + if (node.getDeclaredNodes() != null && !node.getDeclaredNodes().isEmpty()) { + for (NodeData nodeChild : node.getDeclaredNodes()) { NodeCodeGenerator generator = new NodeCodeGenerator(getContext()); childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements()); } } - if (node.getExtensionElements() != null && !node.getExtensionElements().isEmpty()) { - NodeGenFactory factory = new NodeGenFactory(context); - add(factory, node); - } - - if (node.needsFactory() || node.getNodeChildren().size() > 0) { + if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) { add(new NodeFactoryFactory(context, childTypes), node); } } @@ -511,36 +564,138 @@ @Override protected CodeTypeElement create(NodeData node) { - CodeTypeElement clazz = createClass(node, modifiers(PUBLIC, ABSTRACT), genClassName(node), node.getTemplateType().asType(), false); + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), genClassName(node), node.getNodeType(), false); - for (ExecutableElement executable : ElementFilter.constructorsIn(node.getTemplateType().getEnclosedElements())) { - CodeExecutableElement superConstructor = createSuperConstructor(clazz, executable); + for (NodeChildData child : node.getChildren()) { + clazz.add(createChildField(child)); - if (superConstructor != null) { - if (superConstructor.getParameters().size() == 1 && Utils.typeEquals(superConstructor.getParameters().get(0).asType(), node.getTemplateType().asType())) { - String originalName = superConstructor.getParameters().get(0).getSimpleName().toString(); - superConstructor.getParameters().clear(); - superConstructor.getParameters().add(new CodeVariableElement(clazz.asType(), originalName)); - } - clazz.add(superConstructor); + if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) { + ExecutableElement getter = (ExecutableElement) child.getAccessElement(); + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter); + method.getModifiers().remove(Modifier.ABSTRACT); + method.createBuilder().startReturn().string("this.").string(child.getName()).end(); + clazz.add(method); } } + createConstructors(node, clazz); + if (node.getExtensionElements() != null) { clazz.getEnclosedElements().addAll(node.getExtensionElements()); } - node.setNodeType(clazz.asType()); - return clazz; } + private void createConstructors(NodeData node, CodeTypeElement clazz) { + List signatureConstructors = new ArrayList<>(); + ExecutableElement copyConstructor = null; + List constructors = ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements()); + for (ExecutableElement constructor : constructors) { + if (constructor.getModifiers().contains(Modifier.PRIVATE) || constructor.getParameters().isEmpty()) { + continue; + } + + if (isCopyConstructor(constructor)) { + assert copyConstructor == null; + copyConstructor = createConstructor(clazz, constructor, true); + } else { + signatureConstructors.add(createConstructor(clazz, constructor, false)); + } + } + + if (copyConstructor == null && node.needsRewrites(getContext())) { + clazz.add(createConstructor(clazz, null, true)); + } else if (copyConstructor != null) { + clazz.add(copyConstructor); + } + + if (signatureConstructors.isEmpty() && !node.getChildren().isEmpty()) { + clazz.add(createConstructor(clazz, null, false)); + } else { + clazz.getEnclosedElements().addAll(signatureConstructors); + } + } + + private CodeExecutableElement createConstructor(CodeTypeElement type, ExecutableElement superConstructor, boolean copyConstructor) { + CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + if (!copyConstructor) { + if (superConstructor != null) { + for (VariableElement param : superConstructor.getParameters()) { + method.getParameters().add(CodeVariableElement.clone(param)); + } + } + for (NodeChildData child : getModel().getChildren()) { + method.getParameters().add(new CodeVariableElement(child.getNodeType(), child.getName())); + } + } else { + if (!(superConstructor == null && getModel().getChildren().isEmpty())) { + method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); + } + } + + if (superConstructor != null) { + builder.startStatement(); + builder.startSuperCall(); + if (copyConstructor) { + builder.string("copy"); + } else { + for (VariableElement param : superConstructor.getParameters()) { + builder.string(param.getSimpleName().toString()); + } + } + builder.end(); + builder.end(); + } + + for (NodeChildData child : getModel().getChildren()) { + + builder.startStatement(); + builder.string("this.").string(child.getName()).string(" = "); + + if (child.getCardinality() == Cardinality.MANY) { + builder.startCall("adoptChildren"); + } else { + builder.startCall("adoptChild"); + } + + builder.startGroup(); + if (copyConstructor) { + builder.string("copy."); + } + builder.string(child.getName()); + builder.end(); + + builder.end(); + builder.end(); + + } + + return method; + } + + private CodeVariableElement createChildField(NodeChildData child) { + DeclaredType annotationType; + if (child.getCardinality() == Cardinality.MANY) { + annotationType = getContext().getTruffleTypes().getChildrenAnnotation(); + } else { + annotationType = getContext().getTruffleTypes().getChildAnnotation(); + } + + CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName()); + var.getModifiers().add(Modifier.PROTECTED); + var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType)); + return var; + } } private class NodeFactoryFactory extends ClassElementFactory { private final Map> childTypes; + private CodeTypeElement generatedNode; + public NodeFactoryFactory(ProcessorContext context, Map> childElements) { super(context); this.childTypes = childElements; @@ -565,6 +720,10 @@ Modifier createVisibility = Utils.getVisibility(clazz.getModifiers()); if (node.needsFactory()) { + NodeGenFactory factory = new NodeGenFactory(context); + add(factory, node); + generatedNode = factory.getElement(); + createFactoryMethods(node, clazz, createVisibility); if (node.getSpecializations().size() > 1) { @@ -583,15 +742,15 @@ } for (SpecializationData specialization : node.getSpecializations()) { - add(new SpecializedNodeFactory(context), specialization); + add(new SpecializedNodeFactory(context, generatedNode), specialization); } - TypeMirror nodeFactory = getContext().getEnvironment().getTypeUtils().getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); + TypeMirror nodeFactory = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); clazz.getImplements().add(nodeFactory); clazz.add(createCreateNodeMethod(node)); clazz.add(createCreateNodeSpecializedMethod(node)); clazz.add(createGetNodeClassMethod(node)); - clazz.add(createGetNodeSignaturesMethod(node)); + clazz.add(createGetNodeSignaturesMethod()); clazz.add(createGetChildrenSignatureMethod(node)); clazz.add(createGetInstanceMethod(node, createVisibility)); clazz.add(createInstanceConstant(node, clazz.asType())); @@ -616,7 +775,7 @@ } } - List children = node.getNodeChildren(); + List children = node.getNodeDeclaringChildren(); if (node.getParent() == null && children.size() > 0) { clazz.add(createGetFactories(node)); } @@ -624,24 +783,22 @@ } private CodeExecutableElement createGetNodeClassMethod(NodeData node) { - Types types = getContext().getEnvironment().getTypeUtils(); - TypeMirror returnType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); + TypeMirror returnType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); CodeTreeBuilder builder = method.createBuilder(); builder.startReturn().typeLiteral(node.getNodeType()).end(); return method; } - private CodeExecutableElement createGetNodeSignaturesMethod(NodeData node) { - Types types = getContext().getEnvironment().getTypeUtils(); + private CodeExecutableElement createGetNodeSignaturesMethod() { TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); TypeMirror classType = getContext().getType(Class.class); - TypeMirror returnType = types.getDeclaredType(listType, types.getDeclaredType(listType, classType)); + TypeMirror returnType = Utils.getDeclaredType(listType, Utils.getDeclaredType(listType, classType)); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); builder.startStaticCall(getContext().getType(Arrays.class), "asList"); - List constructors = findUserConstructors(node); + List constructors = findUserConstructors(generatedNode.asType()); for (ExecutableElement constructor : constructors) { builder.tree(createAsList(builder, Utils.asTypeMirrors(constructor.getParameters()), classType)); } @@ -656,8 +813,8 @@ 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); + classType = Utils.getDeclaredType(Utils.fromTypeMirror(classType), wildcardNodeType); + TypeMirror returnType = Utils.getDeclaredType(listType, classType); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getExecutionSignature"); CodeTreeBuilder builder = method.createBuilder(); @@ -667,16 +824,16 @@ SpecializationData data = node.getSpecializations().get(0); for (ActualParameter parameter : data.getParameters()) { ParameterSpec spec = parameter.getSpecification(); - NodeFieldData field = node.findField(spec.getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + NodeChildData field = node.findChild(spec.getName()); + if (field == null) { continue; } TypeMirror type; - if (field.getKind() == FieldKind.CHILDREN && field.getType().getKind() == TypeKind.ARRAY) { - type = ((ArrayType) field.getType()).getComponentType(); + if (field.getCardinality() == Cardinality.MANY && field.getNodeType().getKind() == TypeKind.ARRAY) { + type = ((ArrayType) field.getNodeType()).getComponentType(); } else { - type = field.getType(); + type = field.getNodeType(); } signatureTypes.add(type); @@ -706,7 +863,7 @@ method.addParameter(arguments); CodeTreeBuilder builder = method.createBuilder(); - List signatures = findUserConstructors(node); + List signatures = findUserConstructors(generatedNode.asType()); boolean ifStarted = false; for (ExecutableElement element : signatures) { @@ -785,9 +942,8 @@ } private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { - Types types = getContext().getEnvironment().getTypeUtils(); TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class)); - TypeMirror returnType = types.getDeclaredType(nodeFactoryType, node.getNodeType()); + TypeMirror returnType = Utils.getDeclaredType(nodeFactoryType, node.getNodeType()); CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance"); if (visibility != null) { @@ -830,7 +986,7 @@ } private ExecutableElement createGetFactories(NodeData node) { - List children = node.getNodeChildren(); + List children = node.getNodeDeclaringChildren(); if (node.needsFactory()) { children.add(node); } @@ -851,11 +1007,11 @@ TypeMirror factoryType = getContext().getType(NodeFactory.class); TypeMirror baseType; if (allSame) { - baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); + baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); } else { - baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); + baseType = Utils.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); } - TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); + TypeMirror listType = Utils.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); @@ -884,28 +1040,12 @@ } private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { - List constructors = findUserConstructors(node); + List constructors = findUserConstructors(generatedNode.asType()); for (ExecutableElement constructor : constructors) { clazz.add(createCreateMethod(node, createVisibility, constructor)); } } - private List findUserConstructors(NodeData node) { - List constructors = new ArrayList<>(); - for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) { - if (constructor.getModifiers().contains(PRIVATE)) { - continue; - } - - // skip node rewrite constructor - if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) { - continue; - } - constructors.add(constructor); - } - return constructors; - } - private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); method.setSimpleName(CodeNames.of("create")); @@ -942,6 +1082,12 @@ method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass")); CodeTreeBuilder body = method.createBuilder(); + + body.startStatement(); + body.type(generatedNode.asType()).string(" ").string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); + body.string(" = ").string("(").type(generatedNode.asType()).string(") ").string(THIS_NODE_LOCAL_VAR_NAME); + body.end(); + boolean first = true; for (TypeData type : node.getTypeSystem().getTypes()) { SpecializationData specialization = node.findUniqueSpecialization(type); @@ -954,21 +1100,21 @@ } body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); body.startReturn().startNew(nodeSpecializationClassName(specialization)); - body.string(THIS_NODE_LOCAL_VAR_NAME); + body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); body.end().end(); // new, return body.end(); // if } } body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization())); - body.string(THIS_NODE_LOCAL_VAR_NAME); + body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast"); body.end().end(); return method; } private CodeExecutableElement createSpecializeMethod(NodeData node) { 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(generatedNode.asType(), THIS_NODE_LOCAL_VAR_NAME)); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); addInternalValueParameters(method, node.getGenericSpecialization(), true); @@ -992,7 +1138,7 @@ } private List createGeneratedGenericMethod(NodeData node) { - TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getActualType(); + TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType(); if (node.needsRewrites(context)) { List methods = new ArrayList<>(); @@ -1037,7 +1183,7 @@ nextBuilder.startReturn().startCall(generatedGenericMethodName(next)); nextBuilder.string(THIS_NODE_LOCAL_VAR_NAME); - addInternalValueParameterNames(nextBuilder, next, null, true, true); + addInternalValueParameterNames(nextBuilder, next, next, null, true, true); nextBuilder.end().end(); invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot()); @@ -1069,7 +1215,7 @@ builder.startReturn().startCall(generatedGenericMethodName(exception.getTransitionTo())); builder.string(THIS_NODE_LOCAL_VAR_NAME); - addInternalValueParameterNames(builder, exception.getTransitionTo(), null, true, true); + addInternalValueParameterNames(builder, exception.getTransitionTo(), exception.getTransitionTo(), null, true, true); builder.end().end(); } builder.end(); @@ -1080,14 +1226,21 @@ private class SpecializedNodeFactory extends ClassElementFactory { - public SpecializedNodeFactory(ProcessorContext context) { + private final CodeTypeElement nodeGen; + + public SpecializedNodeFactory(ProcessorContext context, CodeTypeElement nodeGen) { super(context); + this.nodeGen = nodeGen; } @Override public CodeTypeElement create(SpecializationData specialization) { NodeData node = specialization.getNode(); - CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), node.getNodeType(), false); + TypeMirror baseType = node.getNodeType(); + if (nodeGen != null) { + baseType = nodeGen.asType(); + } + CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); return clazz; } @@ -1108,20 +1261,14 @@ if (execType.isFinal()) { continue; } - CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); - if (method.getParameters().size() == 1) { - CodeVariableElement var = CodeVariableElement.clone(method.getParameters().get(0)); - var.setName("frameValue"); - method.getParameters().set(0, var); - } - method.getModifiers().remove(Modifier.ABSTRACT); - clazz.add(method); - - TypeData primaryType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); - if (primaryType == execType.getType()) { - buildFunctionalExecuteMethod(method.createBuilder(), specialization); + CodeExecutableElement executeMethod = createExecutableTypeOverride(execType); + clazz.add(executeMethod); + CodeTreeBuilder builder = executeMethod.createBuilder(); + CodeTree result = createExecuteBody(builder, specialization, execType); + if (result != null) { + builder.tree(result); } else { - buildCastingExecuteMethod(method.createBuilder(), specialization, execType.getType()); + clazz.remove(executeMethod); } } @@ -1130,23 +1277,111 @@ } } - private void buildCastingExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization, TypeData type) { + private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType) { + TypeData primaryType = specialization.getReturnType().getTypeSystemType(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + ExecutableTypeData foundEvaluatedPrimaryType = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); + + if (execType == foundEvaluatedPrimaryType || foundEvaluatedPrimaryType == null) { + builder.tree(createFunctionalExecute(builder, specialization, execType)); + } else if (needsCastingExecuteMethod(execType, primaryType)) { + builder.tree(createCastingExecute(builder, specialization, execType, foundEvaluatedPrimaryType)); + } else { + return null; + } + + return builder.getRoot(); + } + + private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType) { + CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod()); + + int i = 0; + for (VariableElement param : method.getParameters()) { + CodeVariableElement var = CodeVariableElement.clone(param); + var.setName(valueName(execType.getParameters().get(i))); + method.getParameters().set(i, var); + i++; + } + + method.getAnnotationMirrors().clear(); + method.getModifiers().remove(Modifier.ABSTRACT); + return method; + } + + private boolean needsCastingExecuteMethod(ExecutableTypeData execType, TypeData primaryType) { + if (execType.isAbstract()) { + return true; + } + if (Utils.isPrimitiveOrVoid(primaryType.getPrimitiveType()) && Utils.isPrimitiveOrVoid(execType.getType().getPrimitiveType())) { + return true; + } + if (execType.getType().isGeneric()) { + return true; + } + return false; + } + + private ExecutableTypeData findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { + TypeData primaryType = specialization.getReturnType().getTypeSystemType(); + List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); + + List filteredTypes = new ArrayList<>(); + for (ExecutableTypeData compareType : otherTypes) { + if (!Utils.typeEquals(compareType.getType().getPrimitiveType(), primaryType.getPrimitiveType())) { + continue; + } + filteredTypes.add(compareType); + } + + for (ExecutableTypeData compareType : filteredTypes) { + if (compareType.startsWithSignature(specialization)) { + return compareType; + } + } + + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.startsWithSignature(specialization)) { + return compareType; + } + } + + return null; + } + + private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { + TypeData type = executable.getType(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); NodeData node = specialization.getNode(); - TypeSystemData typeSystem = node.getTypeSystem(); ExecutableTypeData castedType = node.findExecutableType(type); - TypeData primaryType = specialization.getReturnType().getActualTypeData(typeSystem); - ExecutableTypeData execType = specialization.getNode().findExecutableType(primaryType); + TypeData primaryType = castExecutable.getType(); - boolean needsTry = execType.hasUnexpectedValue(getContext()); + boolean needsTry = castExecutable.hasUnexpectedValue(getContext()); boolean returnVoid = type.isVoid(); - CodeTree primaryExecuteCall = null; + List executeParameters = new ArrayList<>(); + for (ActualParameter sourceParameter : executable.getParameters()) { + NodeChildData field = specialization.getNode().findChild(sourceParameter.getSpecification().getName()); + if (field == null) { + continue; + } - CodeTreeBuilder executeBuilder = CodeTreeBuilder.createBuilder(); - buildExecute(executeBuilder, null, null, execType); - primaryExecuteCall = executeBuilder.getRoot(); + ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName()); + if (targetParameter != null) { + TypeData sourceType = sourceParameter.getTypeSystemType(); + TypeData targetType = targetParameter.getTypeSystemType(); + if (sourceType.needsCastTo(targetType)) { + executeParameters.add(targetParameter); + } + } + } + builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true)); + + CodeTree primaryExecuteCall = createTemplateMethodCall(builder, executable, castExecutable, null); if (needsTry) { if (!returnVoid) { builder.declaration(primaryType.getPrimitiveType(), "value"); @@ -1186,6 +1421,8 @@ builder.end(); } } + + return builder.getRoot(); } private CodeTree createExpectType(NodeData node, ExecutableTypeData castedType, CodeTree value) { @@ -1211,25 +1448,28 @@ return builder.getRoot(); } - private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) { + private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (specialization.isUninitialized()) { builder.tree(createDeoptimize(builder)); } - builder.tree(createExecuteChildren(builder, specialization)); + builder.tree(createExecuteChildren(builder, executable, specialization, specialization.getParameters(), null, false)); CodeTree executeNode; if (specialization.isUninitialized()) { - builder.tree(createSpecializeCall(builder, specialization)); + builder.tree(createSpecializeCall(builder, executable, specialization)); } - executeNode = createExecute(builder, specialization); + executeNode = createExecute(builder, executable, specialization); SpecializationData next = specialization.findNextSpecialization(); CodeTree returnSpecialized = null; if (next != null) { - returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); + returnSpecialized = createReturnSpecializeAndExecute(builder, executable, next, null); } builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized)); + + return builder.getRoot(); } private CodeTree createDeoptimize(CodeTreeBuilder parent) { @@ -1240,7 +1480,7 @@ return builder.getRoot(); } - private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) { + private CodeTree createSpecializeCall(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); @@ -1252,7 +1492,7 @@ builder.startCall(factoryClassName(node), "specialize"); builder.string("this"); builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); - addInternalValueParameterNames(builder, specialization, null, true, true); + addInternalValueParameterNames(builder, executable, specialization, null, true, true); builder.end(); // call replace, call specialize } else { builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); @@ -1261,19 +1501,20 @@ return builder.getRoot(); } - private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) { + private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) { NodeData node = specialization.getNode(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (!specialization.getExceptions().isEmpty()) { builder.startTryBlock(); } + CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent); if (specialization.isUninitialized()) { String genericMethodName = generatedGenericMethodName(null); - builder.startReturn().startCall(factoryClassName(node), genericMethodName); - builder.string("this"); - addInternalValueParameterNames(builder, specialization, null, true, true); - builder.end().end(); + returnBuilder.startCall(factoryClassName(node), genericMethodName); + returnBuilder.string("this"); + addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true); + returnBuilder.end(); } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { emitEncounteredSynthetic(builder); } else if (specialization.isGeneric()) { @@ -1284,36 +1525,81 @@ genericMethodName = generatedGenericMethodName(null); } - builder.startReturn().startCall(factoryClassName(node), genericMethodName); - builder.string("this"); - addInternalValueParameterNames(builder, specialization, null, true, true); - builder.end().end(); + returnBuilder.startCall(factoryClassName(node), genericMethodName); + returnBuilder.string("this"); + addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true); + returnBuilder.end(); } else { + returnBuilder.tree(createTemplateMethodCall(returnBuilder, executable, specialization, null)); + } + + if (!returnBuilder.isEmpty()) { builder.startReturn(); - builder.tree(createTemplateMethodCall(builder, specialization, specialization, null)); - builder.end(); // return + + TypeData targetType = node.getTypeSystem().findTypeData(builder.findMethod().getReturnType()); + TypeData sourceType = specialization.getReturnType().getTypeSystemType(); + + if (targetType == null || sourceType == null) { + builder.tree(returnBuilder.getRoot()); + } else if (sourceType.needsCastTo(targetType)) { + builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot())); + } else { + builder.tree(returnBuilder.getRoot()); + } + builder.end(); } if (!specialization.getExceptions().isEmpty()) { for (SpecializationThrowsData exception : specialization.getExceptions()) { builder.end().startCatchBlock(exception.getJavaClass(), "ex"); - builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null)); + builder.tree(createReturnSpecializeAndExecute(parent, executable, exception.getTransitionTo(), null)); } builder.end(); } return builder.getRoot(); } - private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { + private CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List targetParameters, + ActualParameter unexpectedParameter, boolean cast) { + NodeData sourceNode = specialization.getNode(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); - for (ActualParameter parameter : specialization.getParameters()) { - NodeFieldData field = specialization.getNode().findField(parameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + for (ActualParameter targetParameter : targetParameters) { + NodeChildData field = sourceNode.findChild(targetParameter.getSpecification().getName()); + if (field == null) { continue; } + TypeData targetType = targetParameter.getTypeSystemType(); - buildFieldExecute(builder, specialization, parameter, field, null); + ExecutableTypeData targetExecutable = field.getNodeData().findExecutableType(targetType); + + ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName()); + + String targetVariableName = null; + CodeTree executionExpression = null; + if (cast || sourceParameter != null) { + TypeData sourceType = sourceParameter.getTypeSystemType(); + if (!sourceType.needsCastTo(targetType)) { + if (field.isShortCircuit() && sourceParameter != null) { + builder.tree(createShortCircuitValue(builder, sourceExecutable, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter)); + } + continue; + } + executionExpression = createExpectType(sourceNode, targetExecutable, CodeTreeBuilder.singleString(valueName(targetParameter))); + targetVariableName = castValueName(targetParameter); + } else if (sourceParameter == null) { + targetVariableName = valueName(targetParameter); + executionExpression = createExecuteChildExpression(builder, field, targetParameter); + } + + CodeTreeVariable executionVar = new CodeTreeVariable(); + CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, sourceExecutable, specialization, targetParameter, unexpectedParameter); + CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter, + shortCircuitTree != executionVar); + + executionVar.set(unexpectedTree); + builder.tree(shortCircuitTree); } return builder.getRoot(); } @@ -1326,62 +1612,66 @@ } } - 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()); + private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ExecutableTypeData currentExecutable, + ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + boolean unexpected = targetExecutable.hasUnexpectedValue(getContext()); + builder.startStatement(); - if (!shortCircuit && unexpected) { - builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); + if (!shortCircuit) { + builder.type(param.getType()).string(" ").string(targetVariableName); } if (unexpected) { + if (!shortCircuit) { + builder.end(); + } builder.startTryBlock(); + builder.startStatement(); + builder.string(targetVariableName); + } else if (shortCircuit) { + builder.startStatement(); + builder.string(targetVariableName); } - - if (!shortCircuit && !unexpected) { - builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).string(" = "); - } else { - builder.startStatement().string(valueName(param)).string(" = "); - } - buildExecute(builder, param, field, execType); + builder.string(" = "); + builder.tree(body); 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 || field.getKind() == FieldKind.FIELD) { - continue; - } - if (execute) { - buildFieldExecute(builder, specialization.getNode().getGenericSpecialization(), exParam, exField, param); - } else if (exParam.getLocalName().equals(param.getLocalName())) { - execute = true; - } - } - builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param)); + ActualParameter genericParameter = generic.findParameter(param.getLocalName()); + + List genericParameters = generic.getParametersAfter(genericParameter); + builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); + builder.tree(createReturnSpecializeAndExecute(builder, currentExecutable, specialization.findNextSpecialization(), param)); builder.end(); // catch block } - endShortCircuit(builder, shortCircuit); - builder.newLine(); + return builder.getRoot(); } - private void buildExecute(CodeTreeBuilder builder, ActualParameter parameter, NodeFieldData field, ExecutableTypeData execType) { - if (field != null) { - Element accessElement = field.getAccessElement(); - if (accessElement.getKind() == ElementKind.METHOD) { - builder.startCall(accessElement.getSimpleName().toString()).end(); + private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter) { + TypeData type = sourceParameter.getTypeSystemType(); + ExecutableTypeData execType = targetField.getNodeData().findExecutableType(type); + + /* + * FIXME Temporary deactivated due to partial evaluation failure else if + * (accessElement.getKind() == ElementKind.METHOD) { + * builder.startCall(accessElement.getSimpleName().toString()).end(); } + */ + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (targetField != null) { + Element accessElement = targetField.getAccessElement(); + if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) { + builder.string("this.").string(targetField.getName()); } else if (accessElement.getKind() == ElementKind.FIELD) { builder.string("this.").string(accessElement.getSimpleName().toString()); } else { throw new AssertionError(); } - if (parameter.getSpecification().isIndexed()) { - builder.string("[" + parameter.getIndex() + "]"); + if (sourceParameter.getSpecification().isIndexed()) { + builder.string("[" + sourceParameter.getIndex() + "]"); } builder.string("."); } @@ -1390,22 +1680,40 @@ builder.string("frameValue"); } builder.end(); + return builder.getRoot(); } - private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) { - NodeFieldData forField = specialization.getNode().findField(parameter.getSpecification().getName()); + private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, ExecutableTypeData currentExecutable, SpecializationData specialization, + ActualParameter parameter, ActualParameter exceptionParam) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName()); if (forField == null) { - return false; + return body; } if (forField.getExecutionKind() != ExecutionKind.SHORT_CIRCUIT) { - return false; + return body; } ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter); + builder.tree(createShortCircuitValue(builder, currentExecutable, specialization, forField, shortCircuitParam, exceptionParam)); + + builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType())); + builder.startIf().string(shortCircuitParam.getLocalName()).end(); + builder.startBlock(); + builder.tree(body); + builder.end(); + + return builder.getRoot(); + } + + private CodeTree createShortCircuitValue(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, NodeChildData forField, + ActualParameter shortCircuitParam, ActualParameter exceptionParam) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); int shortCircuitIndex = 0; - for (NodeFieldData field : specialization.getNode().getFields()) { + for (NodeChildData field : specialization.getNode().getChildren()) { if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { if (field == forField) { break; @@ -1414,51 +1722,36 @@ } } - builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); + builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex); - - builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); - + builder.tree(createTemplateMethodCall(builder, currentExecutable, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null)); builder.end(); // statement - builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); - builder.startIf().string(shortCircuitParam.getLocalName()).end(); - builder.startBlock(); - - return true; + return builder.getRoot(); } - private void endShortCircuit(CodeTreeBuilder builder, boolean shortCircuit) { - if (shortCircuit) { - builder.end(); - } - } - - private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ActualParameter exceptionParam) { + private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam) { CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); specializeCall.startCall("specializeAndExecute"); specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); - addInternalValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); + addInternalValueParameterNames(specializeCall, executable, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, + true); specializeCall.end().end(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); builder.startReturn(); - builder.tree(specializeCall.getRoot()); + builder.tree(createExpectType(nextSpecialization.getNode(), executable, specializeCall.getRoot())); builder.end(); + return builder.getRoot(); } private void buildSpecializeAndExecute(CodeTypeElement clazz, SpecializationData specialization) { NodeData node = specialization.getNode(); - TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); - ExecutableTypeData returnExecutableType = node.findExecutableType(returnType); - boolean canThrowUnexpected = returnExecutableType == null ? true : returnExecutableType.hasUnexpectedValue(getContext()); + TypeData returnType = node.getGenericSpecialization().getReturnType().getTypeSystemType(); CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); - if (canThrowUnexpected) { - method.addThrownType(getUnexpectedValueException()); - } addInternalValueParameters(method, specialization.getNode().getGenericSpecialization(), true); clazz.add(method); @@ -1470,7 +1763,7 @@ builder.startStatement(); builder.startCall("replace"); builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState"); - addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, true, true); + addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), specialization.getNode().getGenericSpecialization(), null, true, true); builder.end(); builder.end(); // call replace builder.end(); // statement @@ -1486,10 +1779,10 @@ CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); genericExecute.string("this"); - addInternalValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true, true); + addInternalValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), specialization.getNode().getGenericSpecialization(), null, true, true); genericExecute.end(); // call generated generic - CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); + CodeTree genericInvocation = genericExecute.getRoot(); if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { builder.statement(genericInvocation); diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Tue Apr 23 08:44:07 2013 +0200 @@ -28,8 +28,7 @@ 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.FieldKind; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -37,17 +36,18 @@ private final String nodeId; private NodeData declaringNode; - private List declaredChildren = new ArrayList<>(); + private List declaredNodes = new ArrayList<>(); + private boolean splitByMethodName; private TypeSystemData typeSystem; + private List children; private List fields; private TypeMirror nodeType; private ParameterSpec instanceParameterSpec; private List specializations; private List specializationListeners; - private List guards; - private List executableTypes; + private Map> executableTypes; private List shortCircuits; public NodeData(TypeElement type, String id) { @@ -59,53 +59,69 @@ super(splitSource.getTemplateType(), templateMethodName, null); this.nodeId = nodeId; this.declaringNode = splitSource.declaringNode; - this.declaredChildren = splitSource.declaredChildren; + this.declaredNodes = splitSource.declaredNodes; 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; + this.children = splitSource.children; + } + + public boolean isSplitByMethodName() { + return splitByMethodName; } void setTypeSystem(TypeSystemData typeSystem) { this.typeSystem = typeSystem; } + void setFields(List fields) { + this.fields = fields; + } + + public List getFields() { + return fields; + } + + void setSplitByMethodName(boolean splitByMethodName) { + this.splitByMethodName = splitByMethodName; + } + @Override protected List findChildContainers() { - List children = new ArrayList<>(); - if (declaredChildren != null) { - children.addAll(declaredChildren); + List containerChildren = new ArrayList<>(); + if (declaredNodes != null) { + containerChildren.addAll(declaredNodes); } if (typeSystem != null) { - children.add(typeSystem); + containerChildren.add(typeSystem); } if (specializations != null) { for (MessageContainer specialization : specializations) { if (specialization.getMessageElement() != null) { - children.add(specialization); + containerChildren.add(specialization); } } } if (specializationListeners != null) { - children.addAll(specializationListeners); - } - if (guards != null) { - children.addAll(guards); + containerChildren.addAll(specializationListeners); } if (executableTypes != null) { - children.addAll(executableTypes); + containerChildren.addAll(getExecutableTypes()); } if (shortCircuits != null) { - children.addAll(shortCircuits); + containerChildren.addAll(shortCircuits); + } + if (children != null) { + containerChildren.addAll(children); } if (fields != null) { - children.addAll(fields); + containerChildren.addAll(fields); } - return children; + return containerChildren; } public ParameterSpec getInstanceParameterSpec() { @@ -131,6 +147,10 @@ if (specializations == null) { return false; } + if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + return false; + } + boolean noSpecialization = true; for (SpecializationData specialization : specializations) { noSpecialization = noSpecialization && specialization.isGeneric() || specialization.isUninitialized(); @@ -139,27 +159,29 @@ } public boolean supportsFrame() { - for (ExecutableTypeData execType : executableTypes) { - if (execType.findParameter("frameValue") == null) { - return false; + if (executableTypes != null) { + for (ExecutableTypeData execType : getExecutableTypes(-1)) { + if (execType.findParameter("frameValue") == null) { + return false; + } } } return true; } - public List getNodeChildren() { - List children = new ArrayList<>(); - for (NodeData child : getDeclaredChildren()) { + public List getNodeDeclaringChildren() { + List nodeChildren = new ArrayList<>(); + for (NodeData child : getDeclaredNodes()) { if (child.needsFactory()) { - children.add(child); + nodeChildren.add(child); } - children.addAll(child.getNodeChildren()); + nodeChildren.addAll(child.getNodeDeclaringChildren()); } - return children; + return nodeChildren; } - void setDeclaredChildren(List declaredChildren) { - this.declaredChildren = declaredChildren; + void setDeclaredNodes(List declaredChildren) { + this.declaredNodes = declaredChildren; for (NodeData child : declaredChildren) { child.declaringNode = this; @@ -170,8 +192,8 @@ return declaringNode; } - public List getDeclaredChildren() { - return declaredChildren; + public List getDeclaredNodes() { + return declaredNodes; } public void setNodeType(TypeMirror nodeType) { @@ -218,9 +240,21 @@ return null; } + public List getExecutableTypes(int evaluatedCount) { + if (evaluatedCount == -1) { + List typeData = new ArrayList<>(); + for (int currentEvaluationCount : executableTypes.keySet()) { + typeData.addAll(executableTypes.get(currentEvaluationCount)); + } + return typeData; + } else { + return executableTypes.get(evaluatedCount); + } + } + public List findGenericExecutableTypes(ProcessorContext context) { List types = new ArrayList<>(); - for (ExecutableTypeData type : executableTypes) { + for (ExecutableTypeData type : getExecutableTypes(0)) { if (!type.hasUnexpectedValue(context)) { types.add(type); } @@ -229,7 +263,7 @@ } public ExecutableTypeData findExecutableType(TypeData prmitiveType) { - for (ExecutableTypeData type : executableTypes) { + for (ExecutableTypeData type : getExecutableTypes(0)) { if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) { return type; } @@ -240,7 +274,7 @@ public SpecializationData findUniqueSpecialization(TypeData type) { SpecializationData result = null; for (SpecializationData specialization : specializations) { - if (specialization.getReturnType().getActualTypeData(getTypeSystem()) == type) { + if (specialization.getReturnType().getTypeSystemType() == type) { if (result != null) { // Result not unique; return null; @@ -251,33 +285,14 @@ return result; } - public List getExecutablePrimitiveTypeMirrors() { - List typeMirrors = new ArrayList<>(); - for (ExecutableTypeData executableType : executableTypes) { - typeMirrors.add(executableType.getType().getPrimitiveType()); - } - return typeMirrors; - } - - public NodeFieldData[] filterFields(FieldKind fieldKind, ExecutionKind usage) { - List filteredFields = new ArrayList<>(); - for (NodeFieldData field : getFields()) { + public NodeChildData[] filterFields(ExecutionKind usage) { + List filteredFields = new ArrayList<>(); + for (NodeChildData field : getChildren()) { if (usage == null || field.getExecutionKind() == usage) { - if (fieldKind == null || field.getKind() == fieldKind) { - filteredFields.add(field); - } + filteredFields.add(field); } } - return filteredFields.toArray(new NodeFieldData[filteredFields.size()]); - } - - public boolean hasUnexpectedExecutableTypes(ProcessorContext context) { - for (ExecutableTypeData type : getExecutableTypes()) { - if (type.hasUnexpectedValue(context)) { - return true; - } - } - return false; + return filteredFields.toArray(new NodeChildData[filteredFields.size()]); } public boolean needsRewrites(ProcessorContext context) { @@ -321,13 +336,13 @@ dumpProperty(builder, indent, "templateClass", Utils.getQualifiedName(getTemplateType())); dumpProperty(builder, indent, "typeSystem", getTypeSystem()); - dumpProperty(builder, indent, "fields", getFields()); + dumpProperty(builder, indent, "fields", getChildren()); dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); dumpProperty(builder, indent, "specializations", getSpecializations()); dumpProperty(builder, indent, "messages", collectMessages()); - if (getDeclaredChildren().size() > 0) { + if (getDeclaredNodes().size() > 0) { builder.append(String.format("\n%s children = [", indent)); - for (NodeData node : getDeclaredChildren()) { + for (NodeData node : getDeclaredNodes()) { builder.append("\n"); builder.append(node.dump(level + 1)); } @@ -373,8 +388,8 @@ return b.toString(); } - public NodeFieldData findField(String name) { - for (NodeFieldData field : getFields()) { + public NodeChildData findChild(String name) { + for (NodeChildData field : getChildren()) { if (field.getName().equals(name)) { return field; } @@ -382,12 +397,12 @@ return null; } - public List getFields() { - return fields; + public List getChildren() { + return children; } - void setFields(List fields) { - this.fields = fields; + void setChildren(List fields) { + this.children = fields; } public List getSpecializations() { @@ -412,12 +427,8 @@ return specializationListeners; } - public List getGuards() { - return guards; - } - public List getExecutableTypes() { - return executableTypes; + return getExecutableTypes(-1); } public List getShortCircuits() { @@ -437,11 +448,7 @@ this.specializationListeners = specializationListeners; } - void setGuards(List guards) { - this.guards = guards; - } - - void setExecutableTypes(List executableTypes) { + void setExecutableTypes(Map> executableTypes) { this.executableTypes = executableTypes; } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Tue Apr 23 08:44:07 2013 +0200 @@ -29,88 +29,27 @@ public class NodeFieldData extends MessageContainer { - public enum FieldKind { - CHILD, CHILDREN, FIELD - } - - public enum ExecutionKind { - DEFAULT, IGNORE, SHORT_CIRCUIT - } - - private final VariableElement fieldElement; - private final Element accessElement; - private final AnnotationMirror childAnnotationMirror; - - private final FieldKind fieldKind; - private final ExecutionKind executionKind; - private NodeData nodeData; + private VariableElement variable; - public NodeFieldData(VariableElement fieldElement, Element accessElement, AnnotationMirror childAnnotationMirror, FieldKind fieldKind, ExecutionKind executionKind) { - this.fieldElement = fieldElement; - this.accessElement = accessElement; - this.childAnnotationMirror = childAnnotationMirror; - 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; + public NodeFieldData(VariableElement var) { + this.variable = var; } @Override public Element getMessageElement() { - return fieldElement; - } - - public boolean isShortCircuit() { - return executionKind == ExecutionKind.SHORT_CIRCUIT; + return variable; } - void setNode(NodeData nodeData) { - this.nodeData = nodeData; - getMessages().addAll(nodeData.collectMessages()); - } - - public VariableElement getFieldElement() { - return fieldElement; - } - - public Element getAccessElement() { - return accessElement; - } - - public AnnotationMirror getChildAnnotationMirror() { - return childAnnotationMirror; + public String getName() { + return variable.getSimpleName().toString(); } public TypeMirror getType() { - return fieldElement.asType(); - } - - public FieldKind getKind() { - return fieldKind; - } - - public ExecutionKind getExecutionKind() { - return executionKind; + return variable.asType(); } - public NodeData getNodeData() { - return nodeData; - } - - public String getName() { - return fieldElement.getSimpleName().toString(); - } - - @Override - public String toString() { - return "NodeFieldData[name=" + getName() + ", kind=" + fieldKind + ", execution=" + executionKind + ", node=" + getNodeData() + "]"; + public VariableElement getVariable() { + return variable; } } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -28,9 +28,9 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.*; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; public abstract class NodeMethodParser extends TemplateMethodParser { @@ -48,7 +48,7 @@ return spec; } - private static List nodeTypeMirrors(NodeData nodeData) { + protected List nodeTypeMirrors(NodeData nodeData) { Set typeMirrors = new LinkedHashSet<>(); for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { @@ -66,11 +66,15 @@ @Override public boolean isParsable(ExecutableElement method) { - return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + if (getAnnotationType() != null) { + return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; + } + + return true; } @SuppressWarnings("unused") - protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) { + protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) { MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); if (getNode().supportsFrame()) { @@ -80,35 +84,36 @@ resolveAndAddImplicitThis(methodSpec, method); for (NodeFieldData field : getNode().getFields()) { - if (field.getKind() == FieldKind.FIELD) { + if (!Utils.isFieldAccessible(method, field.getVariable())) { ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); spec.setLocal(true); methodSpec.addOptional(spec); } } - for (NodeFieldData field : getNode().getFields()) { - if (field.getExecutionKind() == ExecutionKind.IGNORE) { - continue; - } + // children are null when parsing executable types + if (getNode().getChildren() != null) { + for (NodeChildData child : getNode().getChildren()) { + if (child.getExecutionKind() == ExecutionKind.DEFAULT) { + ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData()); + if (child.getCardinality().isMany()) { + spec.setCardinality(Cardinality.MANY); + spec.setIndexed(true); + } + methodSpec.addRequired(spec); + } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { + String valueName = child.getName(); + if (shortCircuitName != null && valueName.equals(shortCircuitName)) { + break; + } - if (field.getExecutionKind() == ExecutionKind.DEFAULT) { - ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData()); - if (field.getKind() == FieldKind.CHILDREN) { - spec.setCardinality(Cardinality.MULTIPLE); - spec.setIndexed(true); + if (shortCircuitsEnabled) { + methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); + } + methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData())); + } else { + assert false; } - methodSpec.addRequired(spec); - } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { - String valueName = field.getName(); - if (shortCircuitName != null && valueName.equals(shortCircuitName)) { - break; - } - - methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); - methodSpec.addRequired(createValueParameterSpec(valueName, field.getNodeData())); - } else { - assert false; } } @@ -118,7 +123,7 @@ protected void resolveAndAddImplicitThis(MethodSpec methodSpec, ExecutableElement method) { TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); - if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(declaredType, getContext().getTruffleTypes().getNode())) { + if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) { methodSpec.addImplicitRequiredType(getNode().getTemplateType().asType()); } } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -31,18 +31,17 @@ import javax.tools.Diagnostic.Kind; import com.oracle.truffle.api.codegen.*; -import com.oracle.truffle.api.nodes.Node.Child; -import com.oracle.truffle.api.nodes.Node.Children; +import com.oracle.truffle.api.codegen.NodeClass.InheritNode; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.FieldKind; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; public class NodeParser extends TemplateParser { public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class, - ExecuteChildren.class, NodeClass.class, NodeId.class); + ExecuteChildren.class, NodeClass.class, NodeChild.class, NodeChildren.class, NodeId.class); private Map parsedNodes; @@ -73,7 +72,7 @@ @Override protected NodeData filterErrorElements(NodeData model) { - for (Iterator iterator = model.getDeclaredChildren().iterator(); iterator.hasNext();) { + for (Iterator iterator = model.getDeclaredNodes().iterator(); iterator.hasNext();) { NodeData node = filterErrorElements(iterator.next()); if (node == null) { iterator.remove(); @@ -114,87 +113,97 @@ parsedNodes.put(typeName, rootNode); if (rootNode != null) { - children.addAll(rootNode.getDeclaredChildren()); - rootNode.setDeclaredChildren(children); + children.addAll(rootNode.getDeclaredNodes()); + rootNode.setDeclaredNodes(children); } return rootNode; } - private NodeData parseNode(TypeElement type) { - if (Utils.findAnnotationMirror(processingEnv, type, GeneratedBy.class) != null) { + private NodeData parseNode(TypeElement originalTemplateType) { + // reloading the type elements is needed for ecj + TypeElement templateType = Utils.fromTypeMirror(context.reloadTypeElement(originalTemplateType)); + + if (Utils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) { // generated nodes should not get called again. return null; } - AnnotationMirror methodNodes = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class); + List lookupTypes = findSuperClasses(new ArrayList(), templateType); + Collections.reverse(lookupTypes); - if (methodNodes == null && !Utils.isAssignable(type.asType(), context.getTruffleTypes().getNode())) { - return null; // not a node + AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class); + TypeMirror nodeType = null; + if (Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) { + nodeType = templateType.asType(); } - - if (type.getModifiers().contains(Modifier.PRIVATE)) { - // TODO error message here!? - return null; // not visible, not a node + if (nodeClass != null) { + nodeType = inheritType(nodeClass, "value", nodeType); } - TypeElement nodeType; - boolean needsSplit; - if (methodNodes != null) { - needsSplit = methodNodes != null; - nodeType = Utils.fromTypeMirror(Utils.getAnnotationValue(TypeMirror.class, methodNodes, "value")); - } else { - needsSplit = false; - nodeType = type; + if (nodeType == null) { + if (nodeClass == null) { + // no node + return null; + } else { + // FIXME nodeType not specified error + return null; + } } - NodeData nodeData = parseNodeData(type, nodeType); + Set elementSet = new HashSet<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); + if (!Utils.typeEquals(templateType.asType(), nodeType)) { + elementSet.addAll(context.getEnvironment().getElementUtils().getAllMembers(Utils.fromTypeMirror(nodeType))); - if (nodeData.hasErrors()) { - return nodeData; // error sync point - } + List nodeLookupTypes = findSuperClasses(new ArrayList(), Utils.fromTypeMirror(nodeType)); + Collections.reverse(nodeLookupTypes); + lookupTypes.addAll(nodeLookupTypes); - if (Utils.typeEquals(nodeType.asType(), type.asType())) { - // filter fields if they were not split. (field are accessible anyway) - for (ListIterator iterator = nodeData.getFields().listIterator(); iterator.hasNext();) { - NodeFieldData field = iterator.next(); - if (field.getKind() == FieldKind.FIELD) { + Set types = new HashSet<>(); + for (ListIterator iterator = lookupTypes.listIterator(); iterator.hasNext();) { + TypeElement typeElement = iterator.next(); + if (types.contains(typeElement)) { iterator.remove(); + } else { + types.add(typeElement); } } } + List elements = new ArrayList<>(elementSet); - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); - nodeData.setExtensionElements(getExtensionParser().parseAll(nodeData, elements)); - if (nodeData.getExtensionElements() != null) { - elements.addAll(nodeData.getExtensionElements()); + NodeData node = parseNodeData(templateType, nodeType, elements, lookupTypes); + + if (node.hasErrors()) { + return node; // error sync point } - parseMethods(nodeData, elements); + + parseMethods(node, elements); - if (nodeData.hasErrors()) { - return nodeData; + if (node.hasErrors()) { + return node; } List nodes; - if (needsSplit) { - nodes = splitNodeData(nodeData); + + if (node.isSplitByMethodName()) { + nodes = splitNodeData(node); } else { nodes = new ArrayList<>(); - nodes.add(nodeData); + nodes.add(node); } for (NodeData splittedNode : nodes) { finalizeSpecializations(elements, splittedNode); - verifyNode(splittedNode); + verifyNode(splittedNode, elements); } - if (needsSplit) { - nodeData.setDeclaredChildren(nodes); - nodeData.setSpecializationListeners(new ArrayList()); - nodeData.setSpecializations(new ArrayList()); - return nodeData; + if (node.isSplitByMethodName()) { + node.setDeclaredNodes(nodes); + node.setSpecializationListeners(new ArrayList()); + node.setSpecializations(new ArrayList()); + return node; } else { - return nodeData; + return node; } } @@ -299,25 +308,30 @@ } else if (node.needsRewrites(context)) { SpecializationData specialization = specializations.get(0); GenericParser parser = new GenericParser(context, node); - MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, null); + MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null); ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context); assert anyGenericReturnType != null; - ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType().getPrimitiveType(), 0, false); + ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 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 || field.getKind() == FieldKind.FIELD) { - actualType = specializationParameter.getActualType(); + NodeChildData child = node.findChild(parameterSpec.getName()); + TypeData actualType; + if (child == null) { + actualType = specializationParameter.getTypeSystemType(); } else { - ExecutableTypeData paramType = field.getNodeData().findAnyGenericExecutableType(context); + ExecutableTypeData paramType = child.getNodeData().findAnyGenericExecutableType(context); assert paramType != null; - actualType = paramType.getType().getPrimitiveType(); + actualType = paramType.getType(); } - parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit())); + + if (actualType != null) { + parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit())); + } else { + parameters.add(new ActualParameter(parameterSpec, specializationParameter.getType(), specializationParameter.getIndex(), specializationParameter.isImplicit())); + } } TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters); genericSpecialization = new SpecializationData(genericMethod, true, false); @@ -328,18 +342,18 @@ if (genericSpecialization != null) { if (genericSpecialization.isUseSpecializationsForGeneric()) { for (ActualParameter parameter : genericSpecialization.getReturnTypeAndParameters()) { - if (Utils.isObject(parameter.getActualType())) { + if (Utils.isObject(parameter.getType())) { continue; } Set types = new HashSet<>(); for (SpecializationData specialization : specializations) { ActualParameter actualParameter = specialization.findParameter(parameter.getLocalName()); if (actualParameter != null) { - types.add(Utils.getQualifiedName(actualParameter.getActualType())); + types.add(Utils.getQualifiedName(actualParameter.getType())); } } if (types.size() > 1) { - genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericType())); + genericSpecialization.replaceParameter(parameter.getLocalName(), new ActualParameter(parameter, node.getTypeSystem().getGenericTypeData())); } } } @@ -364,9 +378,13 @@ needsId.add(specialization); } } - List ids = calculateSpecializationIds(needsId); - for (int i = 0; i < ids.size(); i++) { - needsId.get(i).setId(ids.get(i)); + + // verify specialization parameter length + if (verifySpecializationParameters(node)) { + List ids = calculateSpecializationIds(needsId); + for (int i = 0; i < ids.size(); i++) { + needsId.get(i).setId(ids.get(i)); + } } } @@ -403,12 +421,12 @@ continue; } List paramIds = new LinkedList<>(); - paramIds.add(Utils.getTypeId(other.getReturnType().getActualType())); + paramIds.add(Utils.getTypeId(other.getReturnType().getType())); for (ActualParameter param : other.getParameters()) { - if (other.getNode().findField(param.getSpecification().getName()) == null) { + if (other.getNode().findChild(param.getSpecification().getName()) == null) { continue; } - paramIds.add(Utils.getTypeId(param.getActualType())); + paramIds.add(Utils.getTypeId(param.getType())); } assert lastSize == -1 || lastSize == paramIds.size(); if (lastSize != -1 && lastSize != paramIds.size()) { @@ -507,64 +525,57 @@ return signatures; } - private void verifyNode(NodeData nodeData) { - // verify specialization parameter length - verifySpecializationParameters(nodeData); - + private void verifyNode(NodeData nodeData, List elements) { // verify order is not ambiguous verifySpecializationOrder(nodeData); - verifyMissingAbstractMethods(nodeData); + verifyMissingAbstractMethods(nodeData, elements); assignShortCircuitsToSpecializations(nodeData); verifyConstructors(nodeData); -// if (!verifyNamingConvention(specializations, "do")) { -// return null; -// } -// -// if (!verifyNamesUnique(specializations)) { -// return null; -// } - verifyNamingConvention(nodeData.getShortCircuits(), "needs"); 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); + private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List elements, List lookupTypes) { NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString()); - AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); + AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class); if (typeSystemMirror == null) { - nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), nodeType.getQualifiedName().toString()); + nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType)); return nodeData; } 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)); + nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType)); return nodeData; } - nodeData.setNodeType(nodeType.asType()); - nodeData.setTypeSystem(typeSystem); + boolean splitByMethodName = false; + AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class); + if (nodeClass != null) { + splitByMethodName = Utils.getAnnotationValue(Boolean.class, nodeClass, "splitByMethodName"); + } - List executableTypes = filterExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)); - nodeData.setExecutableTypes(executableTypes); + nodeData.setNodeType(nodeType); + nodeData.setSplitByMethodName(splitByMethodName); + nodeData.setTypeSystem(typeSystem); + nodeData.setFields(parseFields(elements)); + nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements))); parsedNodes.put(Utils.getQualifiedName(templateType), nodeData); - nodeData.setFields(parseFields(elements, typeHierarchy)); + // parseChildren invokes cyclic parsing. + nodeData.setChildren(parseChildren(templateType, elements, lookupTypes)); return nodeData; } - private static void verifySpecializationParameters(NodeData nodeData) { + private static boolean verifySpecializationParameters(NodeData nodeData) { boolean valid = true; int args = -1; for (SpecializationData specializationData : nodeData.getSpecializations()) { @@ -585,16 +596,17 @@ specialization.addError("All specializations must have the same number of arguments."); } } + return valid; } - private void verifyMissingAbstractMethods(NodeData nodeData) { + private static void verifyMissingAbstractMethods(NodeData nodeData, List originalElements) { if (!nodeData.needsFactory()) { // missing abstract methods only needs to be implemented // if we need go generate factory for it. return; } - List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(nodeData.getTemplateType())); + List elements = new ArrayList<>(originalElements); Set unusedElements = new HashSet<>(elements); for (TemplateMethod method : nodeData.getAllTemplateMethods()) { @@ -604,6 +616,12 @@ unusedElements.removeAll(nodeData.getExtensionElements()); } + for (NodeChildData child : nodeData.getChildren()) { + if (child.getAccessElement() != null) { + unusedElements.remove(child.getAccessElement()); + } + } + for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) { if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) { nodeData.addError("The type %s must implement the inherited abstract method %s.", Utils.getSimpleName(nodeData.getTemplateType()), Utils.getReadableSignature(unusedMethod)); @@ -618,8 +636,17 @@ } TypeElement type = Utils.fromTypeMirror(nodeData.getNodeType()); + List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); - List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); + boolean parametersFound = false; + for (ExecutableElement constructor : constructors) { + if (!constructor.getParameters().isEmpty()) { + parametersFound = true; + } + } + if (!parametersFound) { + return; + } for (ExecutableElement e : constructors) { if (e.getParameters().size() == 1) { TypeMirror firstArg = e.getParameters().get(0).asType(); @@ -638,38 +665,23 @@ nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); } - private static List filterExecutableTypes(List executableTypes) { - List filteredExecutableTypes = new ArrayList<>(); - for (ExecutableTypeData t1 : executableTypes) { - boolean add = true; - for (ExecutableTypeData t2 : executableTypes) { - if (t1 == t2) { - continue; - } - if (Utils.typeEquals(t1.getType().getPrimitiveType(), t2.getType().getPrimitiveType())) { - if (t1.isFinal() && !t2.isFinal()) { - add = false; - } - } + private static Map> groupExecutableTypes(List executableTypes) { + Map> groupedTypes = new HashMap<>(); + for (ExecutableTypeData type : executableTypes) { + int evaluatedCount = type.getEvaluatedCount(); + + List types = groupedTypes.get(evaluatedCount); + if (types == null) { + types = new ArrayList<>(); + groupedTypes.put(evaluatedCount, types); } - if (add) { - filteredExecutableTypes.add(t1); - } + types.add(type); } - Collections.sort(filteredExecutableTypes, new Comparator() { - - @Override - public int compare(ExecutableTypeData o1, ExecutableTypeData o2) { - int index1 = o1.getTypeSystem().findType(o1.getType()); - int index2 = o2.getTypeSystem().findType(o2.getType()); - if (index1 == -1 || index2 == -1) { - return 0; - } - return index1 - index2; - } - }); - return filteredExecutableTypes; + for (List types : groupedTypes.values()) { + Collections.sort(types); + } + return groupedTypes; } private AnnotationMirror findFirstAnnotation(List elements, Class annotation) { @@ -682,16 +694,20 @@ return null; } - private List parseFields(List elements, final List typeHierarchy) { - AnnotationMirror executionOrderMirror = findFirstAnnotation(typeHierarchy, ExecuteChildren.class); - List executionDefinition = null; - if (executionOrderMirror != null) { - executionDefinition = new ArrayList<>(); - for (String object : Utils.getAnnotationValueList(String.class, executionOrderMirror, "value")) { - executionDefinition.add(object); + private static List parseFields(List elements) { + List fields = new ArrayList<>(); + for (VariableElement field : ElementFilter.fieldsIn(elements)) { + if (field.getModifiers().contains(Modifier.STATIC)) { + continue; + } + if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) { + fields.add(new NodeFieldData(field)); } } + return fields; + } + private List parseChildren(TypeElement templateType, List elements, final List typeHierarchy) { Set shortCircuits = new HashSet<>(); for (ExecutableElement method : ElementFilter.methodsIn(elements)) { AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class); @@ -700,136 +716,113 @@ } } - List fields = new ArrayList<>(); - for (VariableElement var : ElementFilter.fieldsIn(elements)) { - if (var.getModifiers().contains(Modifier.STATIC)) { - continue; + List parsedChildren = new ArrayList<>(); + List typeHierarchyReversed = new ArrayList<>(typeHierarchy); + Collections.reverse(typeHierarchyReversed); + for (TypeElement type : typeHierarchyReversed) { + AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class); + AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class); + + TypeMirror nodeClassType = type.getSuperclass(); + if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) { + nodeClassType = null; } - if (executionDefinition != null) { - if (!executionDefinition.contains(var.getSimpleName().toString())) { - continue; - } + if (nodeClassMirror != null) { + nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType); } - NodeFieldData field = parseField(var, shortCircuits); - if (field != null) { - fields.add(field); - } - } - sortByExecutionOrder(fields, executionDefinition == null ? Collections. emptyList() : executionDefinition, typeHierarchy); - return fields; - } + List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class); + for (AnnotationMirror childMirror : children) { + String name = Utils.getAnnotationValue(String.class, childMirror, "value"); + + Cardinality cardinality = Cardinality.ONE; - private NodeFieldData parseField(VariableElement var, Set foundShortCircuits) { - AnnotationMirror childMirror = Utils.findAnnotationMirror(processingEnv, var, Child.class); - AnnotationMirror childrenMirror = Utils.findAnnotationMirror(processingEnv, var, Children.class); - - FieldKind kind; + TypeMirror childType = inheritType(childMirror, "type", nodeClassType); + if (childType.getKind() == TypeKind.ARRAY) { + cardinality = Cardinality.MANY; + } - ExecutionKind execution; - if (foundShortCircuits.contains(var.getSimpleName().toString())) { - execution = ExecutionKind.SHORT_CIRCUIT; - } else { - execution = ExecutionKind.DEFAULT; - } - - AnnotationMirror mirror; - TypeMirror type; + Element getter = findGetter(elements, name, childType); - if (childMirror != null) { - mirror = childMirror; - type = var.asType(); - kind = FieldKind.CHILD; - } else if (childrenMirror != null) { - mirror = childrenMirror; - type = getComponentType(var.asType()); - kind = FieldKind.CHILDREN; - } else { - execution = ExecutionKind.IGNORE; - type = var.asType(); - mirror = null; - kind = FieldKind.FIELD; - } + ExecutionKind kind = ExecutionKind.DEFAULT; + if (shortCircuits.contains(name)) { + kind = ExecutionKind.SHORT_CIRCUIT; + } + + NodeChildData nodeChild = new NodeChildData(templateType, childMirror, name, childType, getter, cardinality, kind); + + parsedChildren.add(nodeChild); - NodeFieldData fieldData = new NodeFieldData(var, findAccessElement(var), mirror, kind, execution); - if (type != null && mirror != null) { - TypeElement typeElement = Utils.fromTypeMirror(type); - if (typeElement == null) { - return null; - } - NodeData fieldNodeData = resolveNode(typeElement); - fieldData.setNode(fieldNodeData); + verifyNodeChild(nodeChild); + if (nodeChild.hasErrors()) { + continue; + } - if (fieldNodeData == null) { - fieldData.addError("Node type '%s' is invalid.", Utils.getQualifiedName(type)); - } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { - fieldData.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(type)); + NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType)); + nodeChild.setNode(fieldNodeData); + if (fieldNodeData == null) { + nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType)); + } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { + nodeChild.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(type)); + } } } - if (fieldData.getAccessElement().getModifiers().contains(Modifier.PRIVATE)) { - return null; + List filteredChildren = new ArrayList<>(); + Set encounteredNames = new HashSet<>(); + for (int i = parsedChildren.size() - 1; i >= 0; i--) { + NodeChildData child = parsedChildren.get(i); + if (!encounteredNames.contains(child.getName())) { + filteredChildren.add(0, child); + encounteredNames.add(child.getName()); + } } - - return fieldData; + return filteredChildren; } - private Element findAccessElement(VariableElement variableElement) { - Element enclosed = variableElement.getEnclosingElement(); - if (!enclosed.getKind().isClass()) { - throw new IllegalArgumentException("Field must be enclosed in a class."); - } - - String methodName; - if (Utils.typeEquals(variableElement.asType(), context.getType(boolean.class))) { - methodName = "is" + Utils.firstLetterUpperCase(variableElement.getSimpleName().toString()); - } else { - methodName = "get" + Utils.firstLetterUpperCase(variableElement.getSimpleName().toString()); + private static void verifyNodeChild(NodeChildData nodeChild) { + if (nodeChild.getNodeType() == null) { + nodeChild.addError("No valid node type could be resoleved."); } + // FIXME verify node child + // FIXME verify node type set + } - ExecutableElement getter = null; - for (ExecutableElement method : ElementFilter.methodsIn(enclosed.getEnclosedElements())) { - if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && !Utils.typeEquals(method.getReturnType(), context.getType(void.class))) { - getter = method; - break; - } - } - if (getter != null && !getter.getModifiers().contains(Modifier.PRIVATE)) { - return getter; + private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) { + TypeMirror inhertNodeType = context.getType(InheritNode.class); + TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName); + if (Utils.typeEquals(inhertNodeType, value)) { + return parentType; } else { - return variableElement; + return value; } } - private static void sortByExecutionOrder(List fields, final List executionOrder, final List typeHierarchy) { - Collections.sort(fields, new Comparator() { + private Element findGetter(List elements, String variableName, TypeMirror type) { + if (type == null) { + return null; + } + String methodName; + if (Utils.typeEquals(type, context.getType(boolean.class))) { + methodName = "is" + Utils.firstLetterUpperCase(variableName); + } else { + methodName = "get" + Utils.firstLetterUpperCase(variableName); + } - @Override - public int compare(NodeFieldData o1, NodeFieldData o2) { - // sort by execution order - int index1 = executionOrder.indexOf(o1.getName()); - int index2 = executionOrder.indexOf(o2.getName()); - if (index1 == -1 || index2 == -1) { - // sort by type hierarchy - index1 = typeHierarchy.indexOf(o1.getFieldElement().getEnclosingElement()); - index2 = typeHierarchy.indexOf(o2.getFieldElement().getEnclosingElement()); - - // finally sort by name (will emit warning) - if (index1 == -1 || index2 == -1) { - return o1.getName().compareTo(o2.getName()); - } - } - return index1 - index2; + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.typeEquals(method.getReturnType(), type)) { + return method; } - }); + } + return null; } private void assignShortCircuitsToSpecializations(NodeData node) { Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits()); boolean valid = true; - for (NodeFieldData field : node.filterFields(null, ExecutionKind.SHORT_CIRCUIT)) { + for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) { String valueName = field.getName(); List availableCircuits = groupedShortCircuits.get(valueName); @@ -880,7 +873,7 @@ return; } - NodeFieldData[] fields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT); + NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); for (SpecializationData specialization : node.getSpecializations()) { List assignedShortCuts = new ArrayList<>(fields.length); @@ -917,14 +910,14 @@ private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { for (ActualParameter parameter : method.getParameters()) { - NodeFieldData field = node.findField(parameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + NodeChildData field = node.findChild(parameter.getSpecification().getName()); + if (field == null) { continue; } ExecutableTypeData found = null; List executableElements = field.getNodeData().findGenericExecutableTypes(context); for (ExecutableTypeData executable : executableElements) { - if (executable.getType().equalsType(parameter.getActualTypeData(node.getTypeSystem()))) { + if (executable.getType().equalsType(parameter.getTypeSystemType())) { found = executable; break; } @@ -949,13 +942,6 @@ return group; } - private TypeMirror getComponentType(TypeMirror type) { - if (type instanceof ArrayType) { - return getComponentType(((ArrayType) type).getComponentType()); - } - return type; - } - private static List findSuperClasses(List collection, TypeElement element) { if (element.getSuperclass() != null) { TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass()); diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitData.java Tue Apr 23 08:44:07 2013 +0200 @@ -62,7 +62,7 @@ for (ActualParameter param : getParameters()) { ActualParameter specializationParam = specialization.findParameter(param.getLocalName()); - if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) { + if (!Utils.typeEquals(param.getType(), specializationParam.getType())) { return false; } } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ShortCircuitParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -29,7 +29,7 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; +import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; import com.oracle.truffle.codegen.processor.template.*; public class ShortCircuitParser extends NodeMethodParser { @@ -40,8 +40,8 @@ super(context, node); shortCircuitValues = new HashSet<>(); - NodeFieldData[] shortCircuitFields = node.filterFields(null, ExecutionKind.SHORT_CIRCUIT); - for (NodeFieldData field : shortCircuitFields) { + NodeChildData[] shortCircuitFields = node.filterFields(ExecutionKind.SHORT_CIRCUIT); + for (NodeChildData field : shortCircuitFields) { shortCircuitValues.add(field.getName()); } } @@ -49,7 +49,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value"); - return createDefaultMethodSpec(method, mirror, shortCircuitValue); + return createDefaultMethodSpec(method, mirror, true, shortCircuitValue); } @Override diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Tue Apr 23 08:44:07 2013 +0200 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.node.NodeFieldData.*; import com.oracle.truffle.codegen.processor.template.*; import com.oracle.truffle.codegen.processor.typesystem.*; @@ -83,11 +82,11 @@ return true; } for (ActualParameter parameter : getParameters()) { - NodeFieldData field = getNode().findField(parameter.getSpecification().getName()); - if (field == null || field.getKind() == FieldKind.FIELD) { + NodeChildData field = getNode().findChild(parameter.getSpecification().getName()); + if (field == null) { continue; } - ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getActualTypeData(field.getNodeData().getTypeSystem())); + ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getTypeSystemType()); if (type.hasUnexpectedValue(context)) { return true; } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationListenerParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -38,7 +38,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, null); + return createDefaultMethodSpec(method, mirror, true, null); } @Override diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -40,7 +40,7 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - return createDefaultMethodSpec(method, mirror, null); + return createDefaultMethodSpec(method, mirror, true, null); } @Override diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Tue Apr 23 08:44:07 2013 +0200 @@ -29,15 +29,17 @@ public class ActualParameter { private final ParameterSpec specification; - private final TypeMirror actualType; + private TypeData typeSystemType; private TemplateMethod method; private final String localName; private final int index; private final boolean implicit; + private final TypeMirror type; public ActualParameter(ParameterSpec specification, TypeMirror actualType, int index, boolean implicit) { this.specification = specification; - this.actualType = actualType; + this.type = actualType; + this.typeSystemType = null; this.index = index; this.implicit = implicit; @@ -49,7 +51,12 @@ this.localName = valueName; } - public ActualParameter(ActualParameter parameter, TypeMirror otherType) { + public ActualParameter(ParameterSpec specification, TypeData actualType, int index, boolean implicit) { + this(specification, actualType.getPrimitiveType(), index, implicit); + this.typeSystemType = actualType; + } + + public ActualParameter(ActualParameter parameter, TypeData otherType) { this(parameter.specification, otherType, parameter.index, parameter.implicit); } @@ -77,12 +84,12 @@ return method; } - public TypeMirror getActualType() { - return actualType; + public TypeMirror getType() { + return type; } - public TypeData getActualTypeData(TypeSystemData typeSystem) { - return typeSystem.findTypeData(actualType); + public TypeData getTypeSystemType() { + return typeSystemType; } public ActualParameter getPreviousParameter() { diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Tue Apr 23 08:44:07 2013 +0200 @@ -75,7 +75,7 @@ builder.string("this."); builder.string(fieldName); builder.string(" = "); - if (isAssignable(field.asType(), getContext().getTruffleTypes().getNode())) { + if (isAssignable(getContext(), field.asType(), getContext().getTruffleTypes().getNode())) { builder.string("adoptChild(").string(fieldName).string(")"); } else { builder.string(fieldName); @@ -99,7 +99,6 @@ if (element.getModifiers().contains(Modifier.PRIVATE)) { return null; } - CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element); executable.setReturnType(null); executable.setSimpleName(CodeNames.of(type.getSimpleName().toString())); diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Tue Apr 23 08:44:07 2013 +0200 @@ -27,7 +27,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; public class MethodSpec { @@ -60,8 +60,9 @@ optional.add(spec); } - public void addRequired(ParameterSpec spec) { + public ParameterSpec addRequired(ParameterSpec spec) { required.add(spec); + return spec; } public List getImplicitRequiredTypes() { @@ -80,10 +81,6 @@ return optional; } - public void makeTypeDefinitions() { - - } - public List getAll() { List specs = new ArrayList<>(); specs.add(getReturnType()); @@ -154,11 +151,11 @@ for (ParameterSpec requiredSpec : getRequired()) { b.append(sep); - if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) { + if (requiredSpec.getCardinality() == Cardinality.MANY) { b.append("{"); } b.append(createTypeSignature(requiredSpec, false)); - if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) { + if (requiredSpec.getCardinality() == Cardinality.MANY) { b.append("}"); } sep = ", "; diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Tue Apr 23 08:44:07 2013 +0200 @@ -27,14 +27,11 @@ import javax.lang.model.type.*; import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; import com.oracle.truffle.codegen.processor.template.MethodSpec.TypeDef; public class ParameterSpec { - public enum Cardinality { - ONE, MULTIPLE; - } - private final String name; private final List allowedTypes; diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Tue Apr 23 08:44:07 2013 +0200 @@ -144,14 +144,16 @@ public List getReturnTypeAndParameters() { List allParameters = new ArrayList<>(getParameters().size() + 1); - allParameters.add(getReturnType()); + if (getReturnType() != null) { + allParameters.add(getReturnType()); + } allParameters.addAll(getParameters()); return Collections.unmodifiableList(allParameters); } - public boolean canBeAccessedByInstanceOf(TypeMirror type) { + public boolean canBeAccessedByInstanceOf(ProcessorContext context, TypeMirror type) { TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType(); - return Utils.isAssignable(type, methodType) || Utils.isAssignable(methodType, type); + return Utils.isAssignable(context, type, methodType) || Utils.isAssignable(context, methodType, type); } public ExecutableElement getMethod() { @@ -186,13 +188,17 @@ return prev; } - public List getSignature(TypeSystemData typeSystem) { + public TypeData getReturnSignature() { + return getReturnType().getTypeSystemType(); + } + + public List getSignature() { List types = new ArrayList<>(); - for (ActualParameter parameter : getReturnTypeAndParameters()) { + for (ActualParameter parameter : getParameters()) { if (!parameter.getSpecification().isSignature()) { continue; } - TypeData typeData = parameter.getActualTypeData(typeSystem); + TypeData typeData = parameter.getTypeSystemType(); if (typeData != null) { types.add(typeData); } @@ -220,14 +226,27 @@ return compare; } + public List getParametersAfter(ActualParameter genericParameter) { + boolean found = false; + List foundParameters = new ArrayList<>(); + for (ActualParameter param : getParameters()) { + if (param.getLocalName().equals(genericParameter.getLocalName())) { + found = true; + } else if (found) { + foundParameters.add(param); + } + } + return foundParameters; + } + public int compareBySignature(TemplateMethod compareMethod) { TypeSystemData typeSystem = getTemplate().getTypeSystem(); if (typeSystem != compareMethod.getTemplate().getTypeSystem()) { throw new IllegalStateException("Cannot compare two methods with different type systems."); } - List signature1 = getSignature(typeSystem); - List signature2 = compareMethod.getSignature(typeSystem); + List signature1 = getSignature(); + List signature2 = compareMethod.getSignature(); if (signature1.size() != signature2.size()) { return signature2.size() - signature1.size(); } @@ -242,6 +261,12 @@ return 0; } } + if (result == 0) { + TypeData returnSignature1 = getReturnSignature(); + TypeData returnSignature2 = compareMethod.getReturnSignature(); + + result = compareActualParameter(typeSystem, returnSignature1, returnSignature2); + } return result; } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -33,7 +33,8 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; -import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; +import com.oracle.truffle.codegen.processor.typesystem.*; public abstract class TemplateMethodParser { @@ -69,6 +70,10 @@ return context; } + public TypeSystemData getTypeSystem() { + return template.getTypeSystem(); + } + public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); public abstract E create(TemplateMethod method); @@ -221,7 +226,7 @@ ConsumableListIterator required = new ConsumableListIterator<>(spec.getRequired()); while (required.get() != null || types.get() != null) { if (required.get() == null || types.get() == null) { - if (required.get() != null && required.get().getCardinality() == Cardinality.MULTIPLE) { + if (required.get() != null && required.get().getCardinality() == Cardinality.MANY) { required.consume(); specificationParameterIndex = 0; continue; @@ -231,7 +236,7 @@ boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size(); ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit); if (resolvedParameter == null) { - if (required.get().getCardinality() == Cardinality.MULTIPLE) { + if (required.get().getCardinality() == Cardinality.MANY) { required.consume(); continue; } @@ -243,7 +248,7 @@ if (required.get().getCardinality() == Cardinality.ONE) { required.consume(); specificationParameterIndex = 0; - } else if (required.get().getCardinality() == Cardinality.MULTIPLE) { + } else if (required.get().getCardinality() == Cardinality.MANY) { specificationParameterIndex++; } } @@ -263,16 +268,22 @@ return parsedParams; } - private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) { + private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int index, boolean implicit) { TypeMirror resolvedType = mirror; if (hasError(resolvedType)) { - resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem); + resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate); } if (!specification.matches(resolvedType)) { return null; } - return new ActualParameter(specification, resolvedType, index, implicit); + + TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType); + if (resolvedTypeData != null) { + return new ActualParameter(specification, resolvedTypeData, index, implicit); + } else { + return new ActualParameter(specification, resolvedType, index, implicit); + } } /* Helper class for parsing. */ diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -46,12 +46,12 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { - MethodSpec spec = createDefaultMethodSpec(method, mirror, null); + MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null); spec.setVariableRequiredArguments(true); spec.getRequired().clear(); for (ActualParameter parameter : specialization.getRequiredParameters()) { - ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getActualType(), getNode().getTypeSystem().getGenericType()); + ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getType(), getNode().getTypeSystem().getGenericType()); paramSpec.setSignature(true); spec.addRequired(paramSpec); } @@ -82,7 +82,7 @@ if (specializationParameter == null) { newParameters.add(parameter); } else { - newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getActualType(), specializationParameter.getIndex(), parameter.isImplicit())); + newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getIndex(), parameter.isImplicit())); } } guard.setParameters(newParameters); diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -51,7 +51,7 @@ public TypeCastData create(TemplateMethod method) { TypeData targetType = findTypeByMethodName(method, "as"); ActualParameter parameter = method.findParameter("valueValue"); - return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType); + return new TypeCastData(method, parameter.getTypeSystemType(), targetType); } @Override diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -53,7 +53,7 @@ assert checkedType != null; ActualParameter parameter = method.findParameter("valueValue"); assert parameter != null; - return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem())); + return new TypeCheckData(method, checkedType, parameter.getTypeSystemType()); } @Override diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Tue Apr 23 08:44:07 2013 +0200 @@ -110,4 +110,19 @@ return Utils.typeEquals(boxedType, actualTypeData.boxedType); } + public boolean needsCastTo(TypeData targetType) { + if (this.equals(targetType)) { + return false; + } else if (targetType.isGeneric()) { + return false; + } else if (targetType.isVoid()) { + return false; + } + return true; + } + + public boolean isPrimitive() { + return Utils.isPrimitive(getPrimitiveType()); + } + } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Tue Apr 23 08:44:07 2013 +0200 @@ -34,10 +34,6 @@ super(context, typeSystem); } - public TypeSystemData getTypeSystem() { - return template; - } - @Override public final boolean isParsable(ExecutableElement method) { return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null; diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Tue Apr 23 08:44:07 2013 +0200 @@ -74,7 +74,7 @@ if (expressions.size() >= 1) { StatementNode[] nodes = new StatementNode[expressions.size() + 1]; for (int i = 0; i < expressions.size(); i++) { - nodes[i] = PrintNodeFactory.create(expressions.get(i), printOutput); + nodes[i] = PrintNodeFactory.create(printOutput, expressions.get(i)); } nodes[expressions.size()] = new PrintLineNode(printOutput); return new BlockNode(nodes); diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -29,24 +29,8 @@ public abstract class ArithmeticNode extends BinaryNode { - public ArithmeticNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected ArithmeticNode(ArithmeticNode node) { - super(node); - } - public abstract static class AddNode extends ArithmeticNode { - public AddNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected AddNode(AddNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int doInt(int left, int right) { return ExactMath.addExact(left, right); @@ -70,14 +54,6 @@ public abstract static class SubNode extends ArithmeticNode { - public SubNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected SubNode(SubNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int sub(int left, int right) { return ExactMath.subtractExact(left, right); @@ -92,14 +68,6 @@ public abstract static class DivNode extends ArithmeticNode { - public DivNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected DivNode(DivNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int div(int left, int right) { return left / right; @@ -113,14 +81,6 @@ public abstract static class MulNode extends ArithmeticNode { - public MulNode(TypedNode left, TypedNode right) { - super(left, right); - } - - protected MulNode(MulNode node) { - super(node); - } - @Specialization(rewriteOn = ArithmeticException.class) int mul(int left, int right) { return ExactMath.multiplyExact(left, right); diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BinaryNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -24,20 +24,7 @@ import com.oracle.truffle.api.codegen.*; -@ExecuteChildren({"leftNode", "rightNode"}) +@NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")}) public abstract class BinaryNode extends TypedNode { - @Child protected TypedNode leftNode; - - @Child protected TypedNode rightNode; - - public BinaryNode(TypedNode left, TypedNode right) { - this.leftNode = adoptChild(left); - this.rightNode = adoptChild(right); - } - - public BinaryNode(BinaryNode node) { - this(node.leftNode, node.rightNode); - } - } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -28,4 +28,9 @@ public abstract boolean executeCondition(VirtualFrame frame); + @Override + public void executeVoid(VirtualFrame frame) { + executeCondition(frame); + } + } diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -25,23 +25,19 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.frame.*; -@ExecuteChildren("conditionNode") +@NodeChild(value = "conditionNode", type = ConditionNode.class) public abstract class IfNode extends StatementNode { - @Child protected ConditionNode conditionNode; - @Child private StatementNode thenPartNode; - @Child private StatementNode elsePartNode; - public IfNode(ConditionNode condition, StatementNode thenPart, StatementNode elsePart) { - this.conditionNode = adoptChild(condition); + public IfNode(StatementNode thenPart, StatementNode elsePart) { this.thenPartNode = adoptChild(thenPart); this.elsePartNode = adoptChild(elsePart); } protected IfNode(IfNode node) { - this(node.conditionNode, node.thenPartNode, node.elsePartNode); + this(node.thenPartNode, node.elsePartNode); } @Specialization diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LessThanNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -28,14 +28,6 @@ public abstract class LessThanNode extends BinaryNode { - public LessThanNode(TypedNode left, TypedNode right) { - super(left, right); - } - - public LessThanNode(LessThanNode node) { - this(node.leftNode, node.rightNode); - } - @Specialization public boolean doInteger(int left, int right) { return left < right; diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/LogicalAndNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -27,14 +27,6 @@ @SuppressWarnings("unused") public abstract class LogicalAndNode extends BinaryNode { - public LogicalAndNode(TypedNode leftNode, TypedNode rightNode) { - super(leftNode, rightNode); - } - - public LogicalAndNode(LogicalAndNode node) { - this(node.leftNode, node.rightNode); - } - @ShortCircuit("rightNode") public boolean needsRightNode(boolean left) { return left; diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -26,19 +26,17 @@ import com.oracle.truffle.api.codegen.*; +@NodeChild(value = "expression", type = TypedNode.class) public abstract class PrintNode extends StatementNode { - @Child protected TypedNode expression; - private final PrintStream output; - public PrintNode(TypedNode expression, PrintStream output) { - this.expression = adoptChild(expression); + public PrintNode(PrintStream output) { this.output = output; } public PrintNode(PrintNode node) { - this(node.expression, node.output); + this(node.output); } @Specialization diff -r 8f01fe16e473 -r 6aea59f0965c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -27,25 +27,9 @@ import com.oracle.truffle.api.codegen.*; @SuppressWarnings("unused") -@ExecuteChildren({"conditionNode", "ifPartNode", "elsePartNode"}) +@NodeChildren({@NodeChild(value = "conditionNode", type = ConditionNode.class), @NodeChild("ifPartNode"), @NodeChild("elsePartNode")}) public abstract class TernaryNode extends TypedNode { - @Child protected ConditionNode conditionNode; - - @Child protected TypedNode ifPartNode; - - @Child protected TypedNode elsePartNode; - - public TernaryNode(ConditionNode condition, TypedNode ifPart, TypedNode elsePart) { - this.conditionNode = adoptChild(condition); - this.ifPartNode = adoptChild(ifPart); - this.elsePartNode = adoptChild(elsePart); - } - - public TernaryNode(TernaryNode condition) { - this(condition.conditionNode, condition.ifPartNode, condition.elsePartNode); - } - @ShortCircuit("ifPartNode") public boolean needsIfPart(boolean condition) { return condition; diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.*; public abstract class TypedNode extends ConditionNode { @@ -38,18 +39,46 @@ } } - public abstract boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException; + public abstract Object executeGeneric(VirtualFrame frame); - public abstract int executeInteger(VirtualFrame frame) throws UnexpectedResultException; + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectBoolean(executeGeneric(frame)); + } + + public int executeInteger(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectInteger(executeGeneric(frame)); + } - public abstract BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException; + public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectBigInteger(executeGeneric(frame)); + } - public abstract String executeString(VirtualFrame frame) throws UnexpectedResultException; + public String executeString(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectString(executeGeneric(frame)); + } - public abstract Object executeGeneric(VirtualFrame frame); + @Override + public void executeVoid(VirtualFrame frame) { + executeGeneric(frame); + } public boolean isString(Object a, Object b) { return a instanceof String || b instanceof String; } + @SuppressWarnings("unused") + public Object executeEvaluated(VirtualFrame frame, Object val1) { + return executeGeneric(frame); + } + + @SuppressWarnings("unused") + public Object executeEvaluated(VirtualFrame frame, Object val1, Object val2) { + return executeEvaluated(frame, val1); + } + + @SuppressWarnings("unused") + public Object executeEvaluated(VirtualFrame frame, Object val1, Object val2, Object val3) { + return executeEvaluated(frame, val1, val2); + } + } diff -r 8f01fe16e473 -r 6aea59f0965c 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 Mon Apr 22 17:49:13 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Tue Apr 23 08:44:07 2013 +0200 @@ -27,17 +27,15 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.frame.*; +@NodeChild(value = "rightNode", type = TypedNode.class) public abstract class WriteLocalNode extends FrameSlotNode { - @Child protected TypedNode rightNode; - - public WriteLocalNode(FrameSlot slot, TypedNode right) { + public WriteLocalNode(FrameSlot slot) { super(slot); - this.rightNode = adoptChild(right); } public WriteLocalNode(WriteLocalNode node) { - this(node.slot, node.rightNode); + this(node.slot); } @Specialization diff -r 8f01fe16e473 -r 6aea59f0965c src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Apr 22 17:49:13 2013 +0200 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Apr 23 08:44:07 2013 +0200 @@ -972,6 +972,18 @@ break; } + case stub_printf_id: { + __ enter(); + oop_maps = new OopMapSet(); + OopMap* oop_map = save_live_registers(sasm, 4); + int call_offset = __ call_RT(noreg, noreg, (address)stub_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); + oop_maps->add_gc_map(call_offset, oop_map); + restore_live_registers(sasm); + __ leave(); + __ ret(0); + break; + } + case log_primitive_id: { __ enter(); oop_maps = new OopMapSet(); diff -r 8f01fe16e473 -r 6aea59f0965c src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Apr 22 17:49:13 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Apr 23 08:44:07 2013 +0200 @@ -773,6 +773,7 @@ set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id)); set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id)); set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id)); + set_stub("stubPrintfStub", GraalRuntime::entry_for(GraalRuntime::stub_printf_id)); set_stub("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); set_stub("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); set_stub("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); diff -r 8f01fe16e473 -r 6aea59f0965c src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon Apr 22 17:49:13 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Apr 23 08:44:07 2013 +0200 @@ -565,6 +565,12 @@ tty->print(buf, v1, v2, v3); JRT_END +JRT_LEAF(void, GraalRuntime::stub_printf(JavaThread* thread, jlong format, jlong v1, jlong v2, jlong v3)) + ResourceMark rm; + char *buf = (char*) (address) format; + tty->print(buf, v1, v2, v3); +JRT_END + JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) union { jlong l; diff -r 8f01fe16e473 -r 6aea59f0965c src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Mon Apr 22 17:49:13 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Apr 23 08:44:07 2013 +0200 @@ -98,6 +98,7 @@ stub(create_out_of_bounds_exception) \ stub(log_object) \ stub(log_printf) \ + stub(stub_printf) \ stub(log_primitive) \ stub(identity_hash_code) \ stub(thread_is_interrupted) \ @@ -146,6 +147,7 @@ static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); static void vm_error(JavaThread* thread, oop where, oop format, jlong value); static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); + static void stub_printf(JavaThread* thread, jlong format, jlong v1, jlong v2, jlong v3); static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); static void wb_pre_call(JavaThread* thread, oopDesc* obj); static void wb_post_call(JavaThread* thread, oopDesc* obj, void* card);