# HG changeset patch # User Thomas Wuerthinger # Date 1357560244 -3600 # Node ID 570d8e4c6dfbcb9805364f0f3866099ec8f21b12 # Parent 46f9450231898d44d987ba3be84a32f0c391a692# Parent f9f40467383e6630ab4f6b898ac26a82e67a4524 Merge. diff -r 46f945023189 -r 570d8e4c6dfb .hgignore --- a/.hgignore Fri Dec 21 15:54:59 2012 +0100 +++ b/.hgignore Mon Jan 07 13:04:04 2013 +0100 @@ -12,6 +12,8 @@ ^work/ \.checkstyle$ \.classpath +\.factorypath +\.externalToolBuilders \.project \.settings/ \.metadata/ @@ -43,6 +45,7 @@ ^test-output/ scratch/ bin/ +src_gen/ ^local/ ^src/share/tools/hsdis/build/ ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/ @@ -59,3 +62,7 @@ syntax: glob *.bgv core.* +*.jar +eclipse-build.xml +rebuild-launch.out + diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Mon Jan 07 13:04:04 2013 +0100 @@ -50,12 +50,12 @@ * Gets the calling convention describing how arguments are passed. * * @param type the type of calling convention being requested - * @param returnKind the return kind - * @param parameters the kinds of the arguments of the call + * @param returnType the return type (can be null for methods returning {@code void}) + * @param parameterTypes the types of the arguments of the call * @param target the target platform * @param stackOnly ignore registers */ - CallingConvention getCallingConvention(Type type, Kind returnKind, Kind[] parameters, TargetDescription target, boolean stackOnly); + CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly); /** * Gets the ordered set of registers that are can be used to pass parameters diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Mon Jan 07 13:04:04 2013 +0100 @@ -24,8 +24,6 @@ import java.util.*; -import com.oracle.graal.api.meta.*; - /** * The name, signature and calling convention of a call from compiled code to the runtime. * The target of such a call may be a leaf stub or a call into the runtime code proper. @@ -38,14 +36,14 @@ public static class Descriptor { private final String name; private final boolean hasSideEffect; - private final Kind resultKind; - private final Kind[] argumentKinds; + private final Class resultType; + private final Class[] argumentTypes; - public Descriptor(String name, boolean hasSideEffect, Kind resultKind, Kind... args) { + public Descriptor(String name, boolean hasSideEffect, Class resultType, Class... argumentTypes) { this.name = name; this.hasSideEffect = hasSideEffect; - this.resultKind = resultKind; - this.argumentKinds = args; + this.resultType = resultType; + this.argumentTypes = argumentTypes; } /** @@ -67,15 +65,15 @@ /** * Gets the return kind of this runtime call. */ - public Kind getResultKind() { - return resultKind; + public Class getResultType() { + return resultType; } /** * Gets the argument kinds of this runtime call. */ - public Kind[] getArgumentKinds() { - return argumentKinds.clone(); + public Class[] getArgumentTypes() { + return argumentTypes.clone(); } @Override @@ -87,7 +85,7 @@ public boolean equals(Object obj) { if (obj instanceof Descriptor) { Descriptor nas = (Descriptor) obj; - return nas.name.equals(name) && nas.resultKind.equals(resultKind) && Arrays.equals(nas.argumentKinds, argumentKinds); + return nas.name.equals(name) && nas.resultType.equals(resultType) && Arrays.equals(nas.argumentTypes, argumentTypes); } return false; } @@ -96,11 +94,11 @@ public String toString() { StringBuilder sb = new StringBuilder(name).append('('); String sep = ""; - for (Kind arg : argumentKinds) { - sb.append(sep).append(arg); + for (Class arg : argumentTypes) { + sb.append(sep).append(arg.getSimpleName()); sep = ","; } - return sb.append(')').append(resultKind).toString(); + return sb.append(')').append(resultType.getSimpleName()).toString(); } } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.api.code; +import java.math.*; + //JaCoCo Exclude /** @@ -87,5 +89,37 @@ public static boolean belowOrEqual(long a, long b) { return (a <= b) ^ ((a < 0) != (b < 0)); } + + /** + * Unsigned division for two numbers. + */ + public static int divide(int a, int b) { + return (int) ((a & MASK) / (b & MASK)); + } + + /** + * Unsigned remainder for two numbers. + */ + public static int remainder(int a, int b) { + return (int) ((a & MASK) % (b & MASK)); + } + + /** + * Unsigned division for two numbers. + */ + public static long divide(long a, long b) { + return bi(a).divide(bi(b)).longValue(); + } + + /** + * Unsigned remainder for two numbers. + */ + public static long remainder(long a, long b) { + return bi(a).remainder(bi(b)).longValue(); + } + + private static BigInteger bi(long unsigned) { + return unsigned >= 0 ? BigInteger.valueOf(unsigned) : BigInteger.valueOf(unsigned & 0x7fffffffffffffffL).setBit(63); + } } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Mon Jan 07 13:04:04 2013 +0100 @@ -431,4 +431,32 @@ throw new RuntimeException("cannot create Constant for boxed " + kind + " value"); } } + + /** + * Returns a constant with the default value for the given kind. + */ + public static Constant defaultForKind(Kind kind) { + switch(kind) { + case Boolean: + return FALSE; + case Byte: + return forByte((byte) 0); + case Char: + return forChar((char) 0); + case Short: + return forShort((short) 0); + case Int: + return INT_0; + case Double: + return DOUBLE_0; + case Float: + return FLOAT_0; + case Long: + return LONG_0; + case Object: + return NULL_OBJECT; + default: + throw new IllegalArgumentException(kind.toString()); + } + } } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Jan 07 13:04:04 2013 +0100 @@ -46,6 +46,17 @@ } /** + * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes. + */ + public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) { + ResolvedJavaType[] result = new ResolvedJavaType[classes.length]; + for (int i = 0; i < result.length; i++) { + result[i] = metaAccess.lookupJavaType(classes[i]); + } + return result; + } + + /** * Gets the {@link Class} mirror for a given resolved type. * * @param type the type for which the Java mirror is requested @@ -460,29 +471,46 @@ return sb.append(" [bci: ").append(bci).append(']'); } - public static Kind[] signatureToKinds(ResolvedJavaMethod method) { - Kind receiver = isStatic(method.getModifiers()) ? null : method.getDeclaringClass().getKind(); - return signatureToKinds(method.getSignature(), receiver); + public static JavaType[] signatureToTypes(ResolvedJavaMethod method) { + JavaType receiver = isStatic(method.getModifiers()) ? null : method.getDeclaringClass(); + return signatureToTypes(method.getSignature(), receiver); } - public static Kind[] signatureToKinds(Signature signature, Kind receiverKind) { + public static JavaType[] signatureToTypes(Signature signature, JavaType receiverType) { int args = signature.getParameterCount(false); - Kind[] result; + JavaType[] result; int i = 0; - if (receiverKind != null) { - result = new Kind[args + 1]; - result[0] = receiverKind; + if (receiverType != null) { + result = new JavaType[args + 1]; + result[0] = receiverType; i = 1; } else { - result = new Kind[args]; + result = new JavaType[args]; } for (int j = 0; j < args; j++) { - result[i + j] = signature.getParameterKind(j); + result[i + j] = signature.getParameterType(j, null); } return result; } /** + * Converts a {@link Signature} to internal representation, i.e., the signature + *
(int, String, double)void
is converted to
(ILjava/lang/String;D)V
. + * + * @param sig the {@link Signature} to be converted. + * + * @return the signature's internal representation as a string. + */ + public static String signatureToInternal(Signature sig) { + StringBuilder sb = new StringBuilder("("); + for (int i = 0; i < sig.getParameterCount(false); ++i) { + sb.append(sig.getParameterType(i, null).getName()); + } + sb.append(')').append(sig.getReturnType(null).getName()); + return sb.toString(); + } + + /** * Formats some profiling information associated as a string. * * @param info the profiling info to format diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Mon Jan 07 13:04:04 2013 +0100 @@ -36,8 +36,8 @@ public class AMD64DeoptimizationStub extends AMD64Code { - public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, Kind.Void); - public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, Kind.Void, Kind.Object); + public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class); + public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, void.class, Object.class); public final Label label = new Label(); public final LIRFrameState info; diff -r 46f945023189 -r 570d8e4c6dfb 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 Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Jan 07 13:04:04 2013 +0100 @@ -79,8 +79,8 @@ */ public abstract class AMD64LIRGenerator extends LIRGenerator { - public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, Kind.Float, Kind.Float, Kind.Float); - public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, Kind.Double, Kind.Double, Kind.Double); + public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class); + public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class); private static final RegisterValue RAX_I = AMD64.rax.asValue(Kind.Int); private static final RegisterValue RAX_L = AMD64.rax.asValue(Kind.Long); @@ -529,6 +529,11 @@ case MOV_L2D: append(new Op1Reg(MOV_L2D, result, input)); break; case MOV_F2I: append(new Op1Reg(MOV_F2I, result, input)); break; case MOV_D2L: append(new Op1Reg(MOV_D2L, result, input)); break; + case UNSIGNED_I2L: + // Instructions that move or generate 32-bit register values also set the upper 32 bits of the register to zero. + // Consequently, there is no need for a special zero-extension move. + emitMove(input, result); + break; default: throw GraalInternalError.shouldNotReachHere(); } return result; @@ -711,12 +716,12 @@ @Override public void visitBreakpointNode(BreakpointNode node) { - Kind[] sig = new Kind[node.arguments.size()]; + JavaType[] sig = new JavaType[node.arguments.size()]; for (int i = 0; i < sig.length; i++) { - sig[i] = node.arguments.get(i).kind(); + sig[i] = node.arguments.get(i).stamp().javaType(runtime); } - CallingConvention cc = frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, Kind.Void, sig, target(), false); + CallingConvention cc = frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false); Value[] parameters = visitInvokeArguments(cc, node.arguments); append(new AMD64BreakpointOp(parameters)); } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Jan 07 13:04:04 2013 +0100 @@ -459,7 +459,7 @@ } protected CallingConvention createCallingConvention() { - return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnKind(), MetaUtil.signatureToKinds(method), target, false); + return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), MetaUtil.signatureToTypes(method), target, false); } protected void emitPrologue() { @@ -711,8 +711,7 @@ @Override public void emitInvoke(Invoke x) { AbstractCallTargetNode callTarget = (AbstractCallTargetNode) x.callTarget(); - Kind[] signature = callTarget.signature(); - CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().kind(), signature, target(), false); + CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().stamp().javaType(runtime), callTarget.signature(), target(), false); frameMap.callsMethod(cc); Value[] parameters = visitInvokeArguments(cc, callTarget.arguments()); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java Mon Jan 07 13:04:04 2013 +0100 @@ -25,9 +25,7 @@ import java.util.*; import java.util.concurrent.*; -import sun.misc.*; - -public abstract class FieldIntrospection { +public abstract class FieldIntrospection extends UnsafeAccess { /** * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in bytes) of a field. @@ -43,28 +41,6 @@ } } - /** - * An instance of {@link Unsafe} for use within Graal. - */ - public static final Unsafe unsafe = getUnsafe(); - - private static Unsafe getUnsafe() { - try { - // this will fail if Graal is not part of the boot class path - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - // nothing to do - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - // currently we rely on being able to use Unsafe... - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - protected static final ConcurrentHashMap, FieldIntrospection> allClasses = new ConcurrentHashMap<>(); protected final Class clazz; diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,52 @@ +/* + * 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.graal.graph; + +import java.lang.reflect.*; + +import sun.misc.*; + +public class UnsafeAccess { + + /** + * An instance of {@link Unsafe} for use within Graal. + */ + public static final Unsafe unsafe = getUnsafe(); + + private static Unsafe getUnsafe() { + try { + // this will fail if Graal is not part of the boot class path + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + // nothing to do + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + // currently we rely on being able to use Unsafe... + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Jan 07 13:04:04 2013 +0100 @@ -90,7 +90,7 @@ if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) { return super.createCallingConvention(); } else { - return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnKind(), new Kind[]{Kind.Long}, target, false); + return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), new JavaType[]{runtime.lookupJavaType(long.class)}, target, false); } } @@ -262,7 +262,7 @@ if (!isStatic) { tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY); - CallingConvention cc = regConfig.getCallingConvention(JavaCallee, Kind.Void, new Kind[] {Kind.Object}, target, false); + CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[] {runtime().lookupJavaType(Object.class)}, target, false); Register inlineCacheKlass = rax; // see definition of IC_Klass in c1_LIRAssembler_x86.cpp Register receiver = asRegister(cc.getArgument(0)); Address src = new Address(target.wordKind, receiver.asValue(), config.hubOffset); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Mon Jan 07 13:04:04 2013 +0100 @@ -105,11 +105,11 @@ } @Override - public CallingConvention getCallingConvention(Type type, Kind returnKind, Kind[] parameters, TargetDescription target, boolean stackOnly) { + public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { if (type == Type.NativeCall) { throw new UnsupportedOperationException(); } - return callingConvention(returnKind, parameters, type, target, stackOnly); + return callingConvention(returnType, parameterTypes, type, target, stackOnly); } public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) { @@ -119,15 +119,15 @@ return generalParameterRegisters; } - private CallingConvention callingConvention(Kind returnKind, Kind[] kinds, Type type, TargetDescription target, boolean stackOnly) { - Value[] locations = new Value[kinds.length]; + private CallingConvention callingConvention(JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { + Value[] locations = new Value[parameterTypes.length]; int currentGeneral = 0; int currentXMM = 0; int currentStackOffset = 0; - for (int i = 0; i < kinds.length; i++) { - final Kind kind = kinds[i]; + for (int i = 0; i < parameterTypes.length; i++) { + final Kind kind = parameterTypes[i].getKind(); switch (kind) { case Byte: @@ -159,6 +159,7 @@ } } + Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); Value returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind); return new CallingConvention(currentStackOffset, returnLocation, locations); } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon Jan 07 13:04:04 2013 +0100 @@ -46,6 +46,11 @@ String fieldName = null; String valueString = null; + if (option.equals("+PrintFlags")) { + printFlags(); + return true; + } + char first = option.charAt(0); if (first == '+' || first == '-') { fieldName = option.substring(1); @@ -115,10 +120,6 @@ return false; } - if (option.equals("+PrintFlags")) { - printFlags(); - } - return true; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Mon Jan 07 13:04:04 2013 +0100 @@ -70,14 +70,14 @@ } private boolean checkArgs(Object... args) { - Kind[] sig = MetaUtil.signatureToKinds(method); + JavaType[] sig = MetaUtil.signatureToTypes(method); assert args.length == sig.length : MetaUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length; for (int i = 0; i < sig.length; i++) { Object arg = args[i]; if (arg == null) { - assert sig[i] == Kind.Object : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i]; - } else if (sig[i] != Kind.Object) { - assert sig[i].toBoxedJavaClass() == arg.getClass() : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass(); + assert sig[i].getKind() == Kind.Object : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i]; + } else if (sig[i].getKind() != Kind.Object) { + assert sig[i].getKind().toBoxedJavaClass() == arg.getClass() : MetaUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass(); } } return true; diff -r 46f945023189 -r 570d8e4c6dfb 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 Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jan 07 13:04:04 2013 +0100 @@ -66,6 +66,7 @@ import com.oracle.graal.phases.*; import com.oracle.graal.printer.*; import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * HotSpot implementation of {@link GraalCodeCacheProvider}. @@ -264,20 +265,27 @@ for (int i = 0; i < temps.length; i++) { temps[i] = tempRegs[i].asValue(); } - Kind retKind = ret.getKind(); - if (retKind == Kind.Illegal) { - retKind = Kind.Void; - } - assert retKind.equals(descriptor.getResultKind()) : descriptor + " incompatible with result location " + ret; - Kind[] argKinds = descriptor.getArgumentKinds(); - assert argKinds.length == args.length : descriptor + " incompatible with number of argument locations: " + args.length; - for (int i = 0; i < argKinds.length; i++) { - assert argKinds[i].equals(args[i].getKind()) : descriptor + " incompatible with argument location " + i + ": " + args[i]; + assert checkAssignable(descriptor.getResultType(), ret) : descriptor + " incompatible with result location " + ret; + Class[] argTypes = descriptor.getArgumentTypes(); + assert argTypes.length == args.length : descriptor + " incompatible with number of argument locations: " + args.length; + for (int i = 0; i < argTypes.length; i++) { + assert checkAssignable(argTypes[i], args[i]) : descriptor + " incompatible with argument location " + i + ": " + args[i]; } HotSpotRuntimeCallTarget runtimeCall = new HotSpotRuntimeCallTarget(descriptor, address, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM()); runtimeCalls.put(descriptor, runtimeCall); } + private boolean checkAssignable(Class spec, Value value) { + Kind kind = value.getKind(); + if (kind == Kind.Illegal) { + kind = Kind.Void; + } + if (WordBase.class.isAssignableFrom(spec)) { + return kind == graalRuntime.getTarget().wordKind; + } + return kind == Kind.fromJavaClass(spec); + } + /** * Binds a snippet-base {@link Stub} to a runtime call descriptor. * @@ -502,7 +510,7 @@ if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) { invoke.node().dependencies().add(tool.createNullCheckGuard(receiver, invoke.leafGraphId())); } - Kind[] signature = MetaUtil.signatureToKinds(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass().getKind()); + JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); AbstractCallTargetNode loweredCallTarget = null; if (callTarget.invokeKind() == InvokeKind.Virtual && diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Intrinsic for opening a scope binding a stack-based lock with an object. diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -27,7 +27,7 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}. diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Intrinsic for allocating an on-stack array of integers to hold the dimensions diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * A special purpose store node that differs from {@link CompareAndSwapNode} in that diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectReadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectReadNode.java Fri Dec 21 15:54:59 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * 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 com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * A special purpose store node that differs from {@link UnsafeStoreNode} in that - * it is not a {@link StateSplit} and takes a computed address instead of an object. - */ -public class DirectReadNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode address; - private final Kind readKind; - - public DirectReadNode(ValueNode address, Kind readKind) { - super(StampFactory.forKind(readKind)); - this.address = address; - this.readKind = readKind; - } - - @Override - public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitLoad(new Address(readKind, gen.operand(address)), false)); - } - - @NodeIntrinsic - public static native T read(long address, @ConstantNodeParameter Kind kind); -} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectStoreNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectStoreNode.java Fri Dec 21 15:54:59 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * 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 com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * A special purpose store node that differs from {@link UnsafeStoreNode} in that - * it is not a {@link StateSplit} and takes a computed address instead of an object. - */ -public class DirectStoreNode extends FixedWithNextNode implements LIRLowerable { - @Input private ValueNode address; - @Input private ValueNode value; - - public DirectStoreNode(ValueNode address, ValueNode value) { - super(StampFactory.forVoid()); - this.address = address; - this.value = value; - } - - @NodeIntrinsic - public static native void store(long address, boolean value); - - @NodeIntrinsic - public static native void store(long address, byte value); - - @NodeIntrinsic - public static native void store(long address, short value); - - @NodeIntrinsic - public static native void store(long address, char value); - - @NodeIntrinsic - public static native void store(long address, int value); - - @NodeIntrinsic - public static native void store(long address, long value); - - @NodeIntrinsic - public static native void store(long address, float value); - - @NodeIntrinsic - public static native void store(long address, double value); - - @Override - public void generate(LIRGeneratorTool gen) { - Value v = gen.operand(value); - gen.emitStore(new Address(v.getKind(), gen.operand(address)), v, false); - } -} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotCurrentRawThreadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotCurrentRawThreadNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotCurrentRawThreadNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -27,7 +27,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; public class HotSpotCurrentRawThreadNode extends FloatingNode implements LIRLowerable { diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -34,7 +34,7 @@ private final InvokeKind invokeKind; - public HotSpotDirectCallTargetNode(List arguments, Stamp returnStamp, Kind[] signature, Object target, Type callType, InvokeKind invokeKind) { + public HotSpotDirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType, InvokeKind invokeKind) { super(arguments, returnStamp, signature, target, callType); this.invokeKind = invokeKind; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -33,7 +33,7 @@ @Input private ValueNode metaspaceMethod; - public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List arguments, Stamp returnStamp, Kind[] signature, Object target, Type callType) { + public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType) { super(computedAddress, arguments, returnStamp, signature, target, callType); this.metaspaceMethod = metaspaceMethod; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -36,7 +36,7 @@ */ public class IdentityHashCodeStubCall extends FixedWithNextNode implements LIRGenLowerable { @Input private final ValueNode object; - public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, Kind.Int, Kind.Object); + public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, int.class, Object.class); public IdentityHashCodeStubCall(ValueNode object) { super(StampFactory.forKind(Kind.Int)); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Node that is used to maintain a stack based counter of how many locks diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,16 +22,13 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - 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.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Node implementing a call to HotSpot's {@code graal_monitorenter} stub. @@ -40,7 +37,7 @@ @Input private final ValueNode object; @Input private final ValueNode lock; - public static final Descriptor MONITORENTER = new Descriptor("monitorenter", true, Kind.Void, Kind.Object, wordKind()); + public static final Descriptor MONITORENTER = new Descriptor("monitorenter", true, void.class, Object.class, Word.class); public MonitorEnterStubCall(ValueNode object, ValueNode lock) { super(StampFactory.forVoid()); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,15 +22,13 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - 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.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; /** * Node implementing a call to HotSpot's {@code graal_monitorexit} stub. @@ -38,7 +36,7 @@ public class MonitorExitStubCall extends FixedWithNextNode implements LIRGenLowerable { @Input private final ValueNode object; - public static final Descriptor MONITOREXIT = new Descriptor("monitorexit", true, Kind.Void, Kind.Object, wordKind()); + public static final Descriptor MONITOREXIT = new Descriptor("monitorexit", true, void.class, Object.class, Word.class); public MonitorExitStubCall(ValueNode object) { super(StampFactory.forVoid()); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,18 +22,15 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - 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.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Node implementing a call to the {@code new_array} stub. @@ -45,7 +42,7 @@ @Input private final ValueNode hub; @Input private final ValueNode length; - public static final Descriptor NEW_ARRAY_SLOW = new Descriptor("new_array_slow", false, Kind.Object, wordKind(), Kind.Int); + public static final Descriptor NEW_ARRAY_SLOW = new Descriptor("new_array_slow", false, Object.class, Word.class, int.class); public NewArraySlowStubCall(ValueNode hub, ValueNode length) { super(defaultStamp); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,11 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - 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.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; @@ -34,7 +31,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * A call to the {@link NewArrayStub}. @@ -46,7 +43,7 @@ @Input private final ValueNode hub; @Input private final ValueNode length; - public static final Descriptor NEW_ARRAY = new Descriptor("new_array", false, Kind.Object, wordKind(), Kind.Int); + public static final Descriptor NEW_ARRAY = new Descriptor("new_array", false, Object.class, Word.class, int.class); public NewArrayStubCall(ValueNode hub, ValueNode length) { super(defaultStamp); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,18 +22,15 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - 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.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Node implementing a call to HotSpot's {@code new_instance} stub. @@ -44,7 +41,7 @@ @Input private final ValueNode hub; - public static final Descriptor NEW_INSTANCE_SLOW = new Descriptor("new_instance_slow", false, Kind.Object, wordKind()); + public static final Descriptor NEW_INSTANCE_SLOW = new Descriptor("new_instance_slow", false, Object.class, Word.class); public NewInstanceSlowStubCall(ValueNode hub) { super(defaultStamp); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,11 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - 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.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; @@ -34,7 +31,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * A call to the {@link NewInstanceStub}. @@ -45,7 +42,7 @@ @Input private final ValueNode hub; - public static final Descriptor NEW_INSTANCE = new Descriptor("new_instance", false, Kind.Object, wordKind()); + public static final Descriptor NEW_INSTANCE = new Descriptor("new_instance", false, Object.class, Word.class); public NewInstanceStubCall(ValueNode hub) { super(defaultStamp); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; @@ -33,7 +31,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Node implementing a call to HotSpot's {@code new_multi_array} stub. @@ -46,7 +44,7 @@ @Input private final ValueNode dims; private final int rank; - public static final Descriptor NEW_MULTI_ARRAY = new Descriptor("new_multi_array", false, Kind.Object, wordKind(), Kind.Int, wordKind()); + public static final Descriptor NEW_MULTI_ARRAY = new Descriptor("new_multi_array", false, Object.class, Word.class, int.class, Word.class); public NewMultiArrayStubCall(ValueNode hub, int rank, ValueNode dims) { super(defaultStamp); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -25,7 +25,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Allocates some uninitialized area. This is used for TLAB allocation diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -60,8 +60,8 @@ ResolvedJavaMethod method = frameState.method(); boolean isStatic = Modifier.isStatic(method.getModifiers()); - Kind[] signature = MetaUtil.signatureToKinds(method.getSignature(), isStatic ? null : method.getDeclaringClass().getKind()); - CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, Kind.Void, signature, gen.target(), false); + JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass()); + CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.target(), false); gen.frameMap().callsMethod(cc); // TODO (aw): I think this is unnecessary for a tail call. List parameters = new ArrayList<>(); for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) { diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -37,7 +37,7 @@ public class ThreadIsInterruptedStubCall extends FixedWithNextNode implements LIRGenLowerable { @Input private final ValueNode thread; @Input private final ValueNode clearIsInterrupted; - public static final Descriptor THREAD_IS_INTERRUPTED = new Descriptor("thread_is_interrupted", false, Kind.Int, Kind.Object, Kind.Boolean); + public static final Descriptor THREAD_IS_INTERRUPTED = new Descriptor("thread_is_interrupted", false, int.class, Object.class, boolean.class); public ThreadIsInterruptedStubCall(ValueNode thread, ValueNode clearIsInterrupted) { super(StampFactory.forInteger(Kind.Int, 0, 1)); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -41,7 +41,7 @@ @Input private ValueNode format; @Input private ValueNode value; - public static final Descriptor VM_ERROR = new Descriptor("vm_error", false, Kind.Void, Kind.Object, Kind.Object, Kind.Long); + public static final Descriptor VM_ERROR = new Descriptor("vm_error", false, void.class, Object.class, Object.class, long.class); public VMErrorNode(ValueNode format, ValueNode value) { super(StampFactory.forVoid()); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Mon Jan 07 13:04:04 2013 +0100 @@ -24,7 +24,6 @@ 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.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; @@ -36,7 +35,7 @@ public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable { @Input private final ValueNode object; - public static final Descriptor VERIFY_OOP = new Descriptor("verify_oop", false, Kind.Void, Kind.Object); + public static final Descriptor VERIFY_OOP = new Descriptor("verify_oop", false, void.class, Object.class); public VerifyOopStubCall(ValueNode object) { super(StampFactory.objectNonNull()); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Jan 07 13:04:04 2013 +0100 @@ -41,7 +41,7 @@ public class OnStackReplacementPhase extends Phase { - public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, Kind.Void, Kind.Long); + public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, void.class, long.class); @Override protected void run(StructuredGraph graph) { diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -46,6 +46,7 @@ import com.oracle.graal.snippets.SnippetTemplate.Arguments; import com.oracle.graal.snippets.SnippetTemplate.Key; import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.word.*; /** * Snippets used for implementing the type test of a checkcast instruction. @@ -177,7 +178,7 @@ int length = secondarySupers.readInt(metaspaceArrayLengthOffset()); for (int i = 0; i < length; i++) { if (t == loadWordElement(secondarySupers, i)) { - DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t); + s.writeWord(secondarySuperCacheOffset(), t); secondariesHit.inc(); return true; } @@ -218,7 +219,7 @@ int length = secondarySupers.readInt(metaspaceArrayLengthOffset()); for (int i = 0; i < length; i++) { if (t == loadWordElement(secondarySupers, i)) { - DirectObjectStoreNode.storeWord(s, secondarySuperCacheOffset(), 0, t); + s.writeWord(secondarySuperCacheOffset(), t); secondariesHit.inc(); return true; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.snippets.*; import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; /** * Snippets for {@link java.lang.Class} methods. diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Jan 07 13:04:04 2013 +0100 @@ -31,7 +31,7 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.snippets.Snippet.Fold; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; //JaCoCo Exclude diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -43,6 +43,7 @@ import com.oracle.graal.snippets.SnippetTemplate.Arguments; import com.oracle.graal.snippets.SnippetTemplate.Key; import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.word.*; /** * Snippets used for implementing the type test of an instanceof instruction. @@ -150,7 +151,7 @@ int length = secondarySupers.readInt(metaspaceArrayLengthOffset()); for (int i = 0; i < length; i++) { if (t == loadWordElement(secondarySupers, i)) { - DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t); + s.writeWord(secondarySuperCacheOffset(), t); secondariesHit.inc(); return true; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -28,7 +28,6 @@ import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; import static com.oracle.graal.snippets.SnippetTemplate.*; -import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*; import java.util.*; @@ -50,7 +49,7 @@ import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates; import com.oracle.graal.snippets.SnippetTemplate.Arguments; import com.oracle.graal.snippets.SnippetTemplate.Key; -import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.word.*; /** * Snippets used for implementing the monitorenter and monitorexit instructions. @@ -86,9 +85,9 @@ final Word lock = beginLockScope(false); - trace(trace, " object: 0x%016lx\n", Word.fromObject(object).toLong()); - trace(trace, " lock: 0x%016lx\n", lock.toLong()); - trace(trace, " mark: 0x%016lx\n", mark.toLong()); + trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); + trace(trace, " lock: 0x%016lx\n", lock); + trace(trace, " mark: 0x%016lx\n", mark); incCounter(); @@ -100,7 +99,7 @@ final Word biasableLockBits = mark.and(biasedLockMaskInPlace()); // First check to see whether biasing is enabled for this object - if (biasableLockBits.toLong() != biasedLockPattern()) { + if (biasableLockBits != Word.unsigned(biasedLockPattern())) { // Biasing not enabled -> fall through to lightweight locking } else { // The bias pattern is present in the object's mark word. Need to check @@ -109,12 +108,12 @@ final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); final Word thread = thread(); final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace()); - trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord.toLong()); - trace(trace, " thread: 0x%016lx\n", thread.toLong()); - trace(trace, " tmp: 0x%016lx\n", tmp.toLong()); + trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); + trace(trace, " thread: 0x%016lx\n", thread); + trace(trace, " tmp: 0x%016lx\n", tmp); if (tmp == Word.zero()) { // Object is already biased to current thread -> done - trace(trace, "+lock{bias:existing}", object); + traceObject(trace, "+lock{bias:existing}", object); return; } @@ -146,17 +145,17 @@ // don't accidentally blow away another thread's valid bias. Word unbiasedMark = mark.and(biasedLockMaskInPlace() | ageMaskInPlace() | epochMaskInPlace()); Word biasedMark = unbiasedMark.or(thread); - trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark.toLong()); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark.toLong()); + trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark) == unbiasedMark) { // Object is now biased to current thread -> done - trace(trace, "+lock{bias:acquired}", object); + traceObject(trace, "+lock{bias:acquired}", object); return; } // If the biasing toward our thread failed, this means that another thread // owns the bias and we need to revoke that bias. The revocation will occur // in the interpreter runtime. - trace(trace, "+lock{stub:revoke}", object); + traceObject(trace, "+lock{stub:revoke}", object); MonitorEnterStubCall.call(object, lock); return; } else { @@ -167,16 +166,16 @@ // bias in the current epoch. In other words, we allow transfer of // the bias from one thread to another directly in this situation. Word biasedMark = prototypeMarkWord.or(thread); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark.toLong()); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); if (compareAndSwap(object, markOffset(), mark, biasedMark) == mark) { // Object is now biased to current thread -> done - trace(trace, "+lock{bias:transfer}", object); + traceObject(trace, "+lock{bias:transfer}", object); return; } // If the biasing toward our thread failed, then another thread // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. - trace(trace, "+lock{stub:epoch-expired}", object); + traceObject(trace, "+lock{stub:epoch-expired}", object); MonitorEnterStubCall.call(object, lock); return; } @@ -204,16 +203,16 @@ // Create the unlocked mark word pattern Word unlockedMark = mark.or(unlockedMask()); - trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark.toLong()); + trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); // Copy this unlocked mark word into the lock slot on the stack - storeWord(lock, lockDisplacedMarkOffset(), 0, unlockedMark); + lock.writeWord(lockDisplacedMarkOffset(), unlockedMark); // Test if the object's mark word is unlocked, and if so, store the // (address of) the lock slot into the object's mark word. Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock); if (currentMark != unlockedMark) { - trace(trace, " currentMark: 0x%016lx\n", currentMark.toLong()); + trace(trace, " currentMark: 0x%016lx\n", currentMark); // The mark word in the object header was not the same. // Either the object is locked by another thread or is already locked // by the current thread. The latter is true if the mark word @@ -229,20 +228,20 @@ // // assuming both the stack pointer and page_size have their least // significant 2 bits cleared and page_size is a power of 2 - final Word alignedMask = Word.fromInt(wordSize() - 1); + final Word alignedMask = Word.unsigned(wordSize() - 1); final Word stackPointer = stackPointer(); - if (currentMark.minus(stackPointer).and(alignedMask.minus(pageSize())) != Word.zero()) { + if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())) != Word.zero()) { // Most likely not a recursive lock, go into a slow runtime call - trace(trace, "+lock{stub:failed-cas}", object); + traceObject(trace, "+lock{stub:failed-cas}", object); MonitorEnterStubCall.call(object, lock); return; } else { // Recursively locked => write 0 to the lock slot - storeWord(lock, lockDisplacedMarkOffset(), 0, Word.zero()); - trace(trace, "+lock{recursive}", object); + lock.writeWord(lockDisplacedMarkOffset(), Word.zero()); + traceObject(trace, "+lock{recursive}", object); } } else { - trace(trace, "+lock{cas}", object); + traceObject(trace, "+lock{cas}", object); } } @@ -265,13 +264,13 @@ // BeginLockScope nodes do not read from object so a use of object // cannot float about the null check above final Word lock = beginLockScope(false); - trace(trace, "+lock{stub}", object); + traceObject(trace, "+lock{stub}", object); MonitorEnterStubCall.call(object, lock); } @Snippet public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { - trace(trace, " object: 0x%016lx\n", Word.fromObject(object).toLong()); + trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); if (useBiasedLocking()) { // Check for biased locking unlock case, which is a no-op // Note: we do not have to check the thread ID for two reasons. @@ -280,11 +279,11 @@ // lock, the object could not be rebiased toward another thread, so // the bias bit would be clear. final Word mark = loadWordFromObject(object, markOffset()); - trace(trace, " mark: 0x%016lx\n", mark.toLong()); - if (mark.and(biasedLockMaskInPlace()).toLong() == biasedLockPattern()) { + trace(trace, " mark: 0x%016lx\n", mark); + if (mark.and(biasedLockMaskInPlace()) == Word.unsigned(biasedLockPattern())) { endLockScope(); decCounter(); - trace(trace, "-lock{bias}", object); + traceObject(trace, "-lock{bias}", object); return; } } @@ -293,11 +292,11 @@ // Load displaced mark final Word displacedMark = lock.readWord(lockDisplacedMarkOffset()); - trace(trace, " displacedMark: 0x%016lx\n", displacedMark.toLong()); + trace(trace, " displacedMark: 0x%016lx\n", displacedMark); if (displacedMark == Word.zero()) { // Recursive locking => done - trace(trace, "-lock{recursive}", object); + traceObject(trace, "-lock{recursive}", object); } else { verifyOop(object); // Test if object's mark word is pointing to the displaced mark word, and if so, restore @@ -306,10 +305,10 @@ if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark) != lock) { // The object's mark word was not pointing to the displaced header, // we do unlocking via runtime call. - trace(trace, "-lock{stub}", object); + traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); } else { - trace(trace, "-lock{cas}", object); + traceObject(trace, "-lock{cas}", object); } } endLockScope(); @@ -322,7 +321,7 @@ @Snippet public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { verifyOop(object); - trace(trace, "-lock{stub}", object); + traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); endLockScope(); decCounter(); @@ -334,7 +333,7 @@ decCounter(); } - private static void trace(boolean enabled, String action, Object object) { + private static void traceObject(boolean enabled, String action, Object object) { if (enabled) { Log.print(action); Log.print(' '); @@ -342,9 +341,9 @@ } } - private static void trace(boolean enabled, String format, long value) { + private static void trace(boolean enabled, String format, WordBase value) { if (enabled) { - Log.printf(format, value); + Log.printf(format, value.rawValue()); } } @@ -360,7 +359,7 @@ if (CHECK_BALANCED_MONITORS) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0); - DirectObjectStoreNode.storeInt(counter, 0, 0, count + 1); + counter.writeInt(0, count + 1); } } @@ -368,14 +367,14 @@ if (CHECK_BALANCED_MONITORS) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0); - DirectObjectStoreNode.storeInt(counter, 0, 0, count - 1); + counter.writeInt(0, count - 1); } } @Snippet private static void initCounter() { final Word counter = MonitorCounterNode.counter(); - DirectObjectStoreNode.storeInt(counter, 0, 0, 0); + counter.writeInt(0, 0); } @Snippet diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -29,7 +29,6 @@ import static com.oracle.graal.snippets.Snippet.Varargs.*; import static com.oracle.graal.snippets.SnippetTemplate.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; -import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*; import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*; import com.oracle.graal.api.code.*; @@ -50,6 +49,7 @@ import com.oracle.graal.snippets.SnippetTemplate.Arguments; import com.oracle.graal.snippets.SnippetTemplate.Key; import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.word.*; /** * Snippets used for implementing NEW, ANEWARRAY and NEWARRAY. @@ -61,10 +61,10 @@ Word thread = thread(); Word top = thread.readWord(threadTlabTopOffset()); Word end = thread.readWord(threadTlabEndOffset()); - Word newTop = top.plus(size); + Word newTop = top.add(size); // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code) if (newTop.belowOrEqual(end)) { - storeObject(thread, 0, threadTlabTopOffset(), newTop); + thread.writeWord(threadTlabTopOffset(), newTop); return top; } return Word.zero(); @@ -171,7 +171,7 @@ Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { - DirectObjectStoreNode.storeInt(dims, 0, i * 4, dimensions[i]); + dims.writeInt(i * 4, dimensions[i]); } return NewMultiArrayStubCall.call(hub, rank, dims); } @@ -188,19 +188,19 @@ */ private static void formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) { Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset()) : compileTimePrototypeMarkWord; - storeWord(memory, 0, markOffset(), prototypeMarkWord); - storeWord(memory, 0, hubOffset(), hub); + memory.writeWord(markOffset(), prototypeMarkWord); + memory.writeWord(hubOffset(), hub); if (fillContents) { if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) { new_seqInit.inc(); explodeLoop(); for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - storeWord(memory, 0, offset, Word.zero()); + memory.writeWord(offset, Word.zero()); } } else { new_loopInit.inc(); for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - storeWord(memory, 0, offset, Word.zero()); + memory.writeWord(offset, Word.zero()); } } } @@ -210,13 +210,13 @@ * Formats some allocated memory with an object header zeroes out the rest. */ public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { - storeWord(memory, 0, markOffset(), prototypeMarkWord); - storeInt(memory, 0, arrayLengthOffset(), length); + memory.writeWord(markOffset(), prototypeMarkWord); + memory.writeInt(arrayLengthOffset(), length); // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null - storeWord(memory, 0, hubOffset(), hub); + memory.writeWord(hubOffset(), hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { - storeWord(memory, 0, offset, Word.zero()); + memory.writeWord(offset, Word.zero()); } } } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.snippets.*; import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; /** * Snippets for {@link java.lang.Object} methods. @@ -37,7 +38,7 @@ @MethodSubstitution(isStatic = false) public static Class getClass(final Object thisObj) { Word hub = loadHub(thisObj); - return unsafeCast(hub.readFinalObject(classMirrorOffset()), Class.class, true, true); + return unsafeCast(hub.readFinalObject(Word.signed(classMirrorOffset())), Class.class, true, true); } @MethodSubstitution(isStatic = false) @@ -46,8 +47,8 @@ // this code is independent from biased locking (although it does not look that way) final Word biasedLock = mark.and(biasedLockMaskInPlace()); - if (biasedLock.toLong() == unlockedMask()) { - int hash = (int) (mark.toLong() >>> identityHashCodeShift()); + if (biasedLock == Word.unsigned(unlockedMask())) { + int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); if (hash != uninitializedIdentityHashCodeValue()) { return hash; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -22,15 +22,15 @@ */ package com.oracle.graal.hotspot.snippets; -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; -import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * Snippets for {@link java.lang.System} methods. @@ -38,8 +38,8 @@ @ClassSubstitution(java.lang.System.class) public class SystemSnippets implements SnippetsInterface { - public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, Kind.Long); - public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, Kind.Long); + public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, long.class); + public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, long.class); public static long currentTimeMillis() { return callLong(JAVA_TIME_MILLIS); @@ -58,8 +58,8 @@ // this code is independent from biased locking (although it does not look that way) final Word biasedLock = mark.and(biasedLockMaskInPlace()); - if (biasedLock.toLong() == unlockedMask()) { - int hash = (int) (mark.toLong() >>> identityHashCodeShift()); + if (biasedLock == Word.unsigned(unlockedMask())) { + int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); if (hash != uninitializedIdentityHashCodeValue()) { return hash; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.snippets.*; import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; /** * Snippets for {@link java.lang.Thread} methods. diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsafeSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsafeSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,383 +0,0 @@ -/* - * Copyright (c) 2011, 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.snippets; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.ClassSubstitution.*; - -/** - * Snippets for {@link sun.misc.Unsafe} methods. - */ -@ClassSubstitution(sun.misc.Unsafe.class) -public class UnsafeSnippets implements SnippetsInterface { - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); - } - - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); - } - - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); - } - - @MethodSubstitution(isStatic = false) - public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - return UnsafeLoadNode.load(o, 0, offset, Kind.Object); - } - - @MethodSubstitution(isStatic = false) - public static Object getObjectVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - Object result = getObject(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Object); - } - - @MethodSubstitution(isStatic = false) - public static void putObjectVolatile(final Object thisObj, Object o, long offset, Object x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putObject(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedObject(final Object thisObj, Object o, long offset, Object x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putObject(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - Integer value = UnsafeLoadNode.load(o, 0, offset, Kind.Int); - return value; - } - - @MethodSubstitution(isStatic = false) - public static int getIntVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - int result = getInt(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Int); - } - - @MethodSubstitution(isStatic = false) - public static void putIntVolatile(final Object thisObj, Object o, long offset, int x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putInt(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedInt(final Object thisObj, Object o, long offset, int x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putInt(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Boolean result = UnsafeLoadNode.load(o, 0, offset, Kind.Boolean); - return result; - } - - @MethodSubstitution(isStatic = false) - public static boolean getBooleanVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - boolean result = getBoolean(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Boolean); - } - - @MethodSubstitution(isStatic = false) - public static void putBooleanVolatile(final Object thisObj, Object o, long offset, boolean x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putBoolean(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Byte result = UnsafeLoadNode.load(o, 0, offset, Kind.Byte); - return result; - } - - @MethodSubstitution(isStatic = false) - public static byte getByteVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - byte result = getByte(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Byte); - } - - @MethodSubstitution(isStatic = false) - public static void putByteVolatile(final Object thisObj, Object o, long offset, byte x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putByte(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Short result = UnsafeLoadNode.load(o, 0, offset, Kind.Short); - return result; - } - - @MethodSubstitution(isStatic = false) - public static short getShortVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - short result = getShort(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Short); - } - - @MethodSubstitution(isStatic = false) - public static void putShortVolatile(final Object thisObj, Object o, long offset, short x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putShort(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Character result = UnsafeLoadNode.load(o, 0, offset, Kind.Char); - return result; - } - - @MethodSubstitution(isStatic = false) - public static char getCharVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - char result = getChar(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Char); - } - - @MethodSubstitution(isStatic = false) - public static void putCharVolatile(final Object thisObj, Object o, long offset, char x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putChar(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Long result = UnsafeLoadNode.load(o, 0, offset, Kind.Long); - return result; - } - - @MethodSubstitution(isStatic = false) - public static long getLongVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - long result = getLong(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Long); - } - - @MethodSubstitution(isStatic = false) - public static void putLongVolatile(final Object thisObj, Object o, long offset, long x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putLong(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedLong(final Object thisObj, Object o, long offset, long x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putLong(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Float result = UnsafeLoadNode.load(o, 0, offset, Kind.Float); - return result; - } - - @MethodSubstitution(isStatic = false) - public static float getFloatVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - float result = getFloat(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Float); - } - - @MethodSubstitution(isStatic = false) - public static void putFloatVolatile(final Object thisObj, Object o, long offset, float x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putFloat(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Double result = UnsafeLoadNode.load(o, 0, offset, Kind.Double); - return result; - } - - @MethodSubstitution(isStatic = false) - public static double getDoubleVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - double result = getDouble(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Double); - } - - @MethodSubstitution(isStatic = false) - public static void putDoubleVolatile(final Object thisObj, Object o, long offset, double x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putDouble(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putByte(@SuppressWarnings("unused") final Object thisObj, long address, byte value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putShort(@SuppressWarnings("unused") final Object thisObj, long address, short value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putChar(@SuppressWarnings("unused") final Object thisObj, long address, char value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putInt(@SuppressWarnings("unused") final Object thisObj, long address, int value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putLong(@SuppressWarnings("unused") final Object thisObj, long address, long value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putFloat(@SuppressWarnings("unused") final Object thisObj, long address, float value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putDouble(@SuppressWarnings("unused") final Object thisObj, long address, double value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static byte getByte(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Byte); - } - - @MethodSubstitution(isStatic = false) - public static short getShort(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Short); - } - - @MethodSubstitution(isStatic = false) - public static char getChar(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Char); - } - - @MethodSubstitution(isStatic = false) - public static int getInt(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Int); - } - - @MethodSubstitution(isStatic = false) - public static long getLong(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Long); - } - - @MethodSubstitution(isStatic = false) - public static float getFloat(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Float); - } - - @MethodSubstitution(isStatic = false) - public static double getDouble(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Double); - } -} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Jan 07 13:04:04 2013 +0100 @@ -35,6 +35,7 @@ import com.oracle.graal.snippets.Snippet.ConstantParameter; import com.oracle.graal.snippets.Snippet.Parameter; import com.oracle.graal.snippets.SnippetTemplate.Key; +import com.oracle.graal.word.*; /** * Stub implementing the fast path for TLAB refill during instance class allocation. @@ -78,14 +79,14 @@ log(log, "newArray: element kind %d\n", elementKind); log(log, "newArray: array length %d\n", length); log(log, "newArray: array size %d\n", sizeInBytes); - log(log, "newArray: hub=%p\n", hub.toLong()); + log(log, "newArray: hub=%p\n", hub); // check that array length is small enough for fast path. if (length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { Word memory = refillAllocate(intArrayHub, sizeInBytes, log); if (memory != Word.zero()) { - log(log, "newArray: allocated new array at %p\n", memory.toLong()); - formatArray(hub, sizeInBytes, length, headerSize, memory, Word.fromLong(arrayPrototypeMarkWord()), true); + log(log, "newArray: allocated new array at %p\n", memory); + formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true); return verifyOop(memory.toObject()); } } diff -r 46f945023189 -r 570d8e4c6dfb 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 Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Jan 07 13:04:04 2013 +0100 @@ -26,7 +26,6 @@ import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; import static com.oracle.graal.hotspot.snippets.NewObjectSnippets.*; -import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -34,8 +33,11 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.snippets.*; import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.Snippet.*; +import com.oracle.graal.snippets.Snippet.ConstantParameter; +import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.snippets.Snippet.Parameter; import com.oracle.graal.snippets.SnippetTemplate.Key; +import com.oracle.graal.word.*; /** * Stub implementing the fast path for TLAB refill during instance class allocation. @@ -74,10 +76,10 @@ Word memory = refillAllocate(intArrayHub, sizeInBytes, log); if (memory != Word.zero()) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); - storeWord(memory, 0, markOffset(), prototypeMarkWord); - storeWord(memory, 0, hubOffset(), hub); + memory.writeWord(markOffset(), prototypeMarkWord); + memory.writeWord(hubOffset(), hub); for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) { - storeWord(memory, 0, offset, Word.zero()); + memory.writeWord(offset, Word.zero()); } return verifyOop(memory.toObject()); } @@ -96,7 +98,7 @@ */ static Word refillAllocate(Word intArrayHub, int sizeInBytes, boolean log) { - Word intArrayMarkWord = Word.fromLong(tlabIntArrayMarkWord()); + Word intArrayMarkWord = Word.unsigned(tlabIntArrayMarkWord()); int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords() * wordSize(); Word thread = thread(); @@ -104,15 +106,14 @@ Word end = thread.readWord(threadTlabEndOffset()); // calculate amount of free space - Word tlabFreeSpaceInBytes = end.minus(top); + Word tlabFreeSpaceInBytes = end.subtract(top); - log(log, "refillTLAB: thread=%p\n", thread.toLong()); - log(log, "refillTLAB: top=%p\n", top.toLong()); - log(log, "refillTLAB: end=%p\n", end.toLong()); - log(log, "refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes.toLong()); + log(log, "refillTLAB: thread=%p\n", thread); + log(log, "refillTLAB: top=%p\n", top); + log(log, "refillTLAB: end=%p\n", end); + log(log, "refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes); - // a DIV or SHR operations on Words would be handy here... - Word tlabFreeSpaceInWords = Word.fromLong(tlabFreeSpaceInBytes.toLong() >>> log2WordSize()); + Word tlabFreeSpaceInWords = tlabFreeSpaceInBytes.unsignedShiftRight(log2WordSize()); // Retain TLAB and allocate object in shared space if // the amount free in the TLAB is too large to discard. @@ -120,12 +121,12 @@ if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) { if (tlabStats()) { // increment number of refills - storeInt(thread, 0, tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1); - log(log, "thread: %p -- number_of_refills %d\n", thread.toLong(), thread.readInt(tlabNumberOfRefillsOffset())); + thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1); + log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset())); // accumulate wastage - Word wastage = thread.readWord(tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords); - log(log, "thread: %p -- accumulated wastage %d\n", thread.toLong(), wastage.toLong()); - storeWord(thread, 0, tlabFastRefillWasteOffset(), wastage); + Word wastage = thread.readWord(tlabFastRefillWasteOffset()).add(tlabFreeSpaceInWords); + log(log, "thread: %p -- accumulated wastage %d\n", thread, wastage); + thread.writeWord(tlabFastRefillWasteOffset(), wastage); } // if TLAB is currently allocated (top or end != null) then @@ -133,26 +134,26 @@ if (top != Word.zero()) { int headerSize = arrayBaseOffset(Kind.Int); // just like the HotSpot assembler stubs, assumes that tlabFreeSpaceInInts fits in an int - int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes.toLong() >>> 2; + int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes.rawValue() >>> 2; int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false); Word allocated = thread.readWord(threadAllocatedBytesOffset()); - allocated = allocated.plus(top.minus(thread.readWord(threadTlabStartOffset()))); - storeWord(thread, 0, threadAllocatedBytesOffset(), allocated); + allocated = allocated.add(top.subtract(thread.readWord(threadTlabStartOffset()))); + thread.writeWord(threadAllocatedBytesOffset(), allocated); } // refill the TLAB with an eden allocation Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset()); - Word tlabRefillSizeInBytes = Word.fromLong(tlabRefillSizeInWords.toLong() * wordSize()); + Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize()); // allocate new TLAB, address returned in top top = edenAllocate(tlabRefillSizeInBytes, log); if (top != Word.zero()) { - storeWord(thread, 0, threadTlabStartOffset(), top); - storeWord(thread, 0, threadTlabTopOffset(), top); + thread.writeWord(threadTlabStartOffset(), top); + thread.writeWord(threadTlabTopOffset(), top); - end = top.plus(tlabRefillSizeInBytes.minus(alignmentReserveInBytes)); - storeWord(thread, 0, threadTlabEndOffset(), end); + end = top.add(tlabRefillSizeInBytes.subtract(alignmentReserveInBytes)); + thread.writeWord(threadTlabEndOffset(), end); return allocate(sizeInBytes); } else { @@ -160,15 +161,15 @@ } } else { // Retain TLAB - Word newRefillWasteLimit = refillWasteLimit.plus(tlabRefillWasteIncrement()); - storeWord(thread, 0, tlabRefillWasteLimitOffset(), newRefillWasteLimit); - log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.toLong()); + Word newRefillWasteLimit = refillWasteLimit.add(tlabRefillWasteIncrement()); + thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit); + log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit); if (tlabStats()) { - storeInt(thread, 0, tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1); + thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1); } - return edenAllocate(Word.fromInt(sizeInBytes), log); + return edenAllocate(Word.unsigned(sizeInBytes), log); } } @@ -180,18 +181,18 @@ * @return the allocated chunk or {@link Word#zero()} if allocation fails */ static Word edenAllocate(Word sizeInBytes, boolean log) { - Word heapTopAddress = Word.fromLong(heapTopAddress()); - Word heapEndAddress = Word.fromLong(heapEndAddress()); + Word heapTopAddress = Word.unsigned(heapTopAddress()); + Word heapEndAddress = Word.unsigned(heapEndAddress()); while (true) { Word heapTop = heapTopAddress.readWord(0); - Word newHeapTop = heapTop.plus(sizeInBytes); + Word newHeapTop = heapTop.add(sizeInBytes); if (newHeapTop.belowOrEqual(heapTop)) { return Word.zero(); } Word heapEnd = heapEndAddress.readWord(0); - if (newHeapTop.above(heapEnd)) { + if (newHeapTop.aboveThan(heapEnd)) { return Word.zero(); } @@ -211,11 +212,26 @@ 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 46f945023189 -r 570d8e4c6dfb 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 Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jan 07 13:04:04 2013 +0100 @@ -54,8 +54,8 @@ */ public final class GraphBuilderPhase extends Phase { - public static final Descriptor CREATE_NULL_POINTER_EXCEPTION = new Descriptor("createNullPointerException", true, Kind.Object); - public static final Descriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new Descriptor("createOutOfBoundsException", true, Kind.Object, Kind.Int); + public static final Descriptor CREATE_NULL_POINTER_EXCEPTION = new Descriptor("createNullPointerException", true, Object.class); + public static final Descriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new Descriptor("createOutOfBoundsException", true, Object.class, int.class); /** diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -54,11 +54,11 @@ if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); - Kind[] parameterKinds = signatureToKinds(runtime.lookupJavaMethod(m)); - assert parameterKinds.length == args.length; + JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m)); + assert parameterTypes.length == args.length; for (int i = 0; i < argsToBind.length; i++) { LocalNode local = graph.getLocal(i); - Constant c = Constant.forBoxed(parameterKinds[i], argsToBind[i]); + Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]); ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph); local.replaceAtUsages(replacement); } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Jan 07 13:04:04 2013 +0100 @@ -35,7 +35,7 @@ public class AMD64Call { - public static final Descriptor DEBUG = new Descriptor("debug", false, Kind.Void); + public static final Descriptor DEBUG = new Descriptor("debug", false, void.class); @Opcode("CALL_DIRECT") public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -31,11 +31,11 @@ public abstract class AbstractCallTargetNode extends CallTargetNode { private final Stamp returnStamp; - private final Kind[] signature; + private final JavaType[] signature; private final Object target; private final CallingConvention.Type callType; - public AbstractCallTargetNode(List arguments, Stamp returnStamp, Kind[] signature, Object target, CallingConvention.Type callType) { + public AbstractCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) { super(arguments); this.returnStamp = returnStamp; this.signature = signature; @@ -48,7 +48,7 @@ return returnStamp; } - public Kind[] signature() { + public JavaType[] signature() { return signature; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -30,7 +30,7 @@ public class DirectCallTargetNode extends AbstractCallTargetNode { - public DirectCallTargetNode(List arguments, Stamp returnStamp, Kind[] signature, Object target, CallingConvention.Type callType) { + public DirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) { super(arguments, returnStamp, signature, target, callType); } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -32,7 +32,7 @@ @Input protected ValueNode computedAddress; - public IndirectCallTargetNode(ValueNode computedAddress, List arguments, Stamp returnStamp, Kind[] signature, Object target, CallingConvention.Type callType) { + public IndirectCallTargetNode(ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) { super(arguments, returnStamp, signature, target, callType); this.computedAddress = computedAddress; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -34,7 +34,7 @@ */ public final class UnwindNode extends FixedNode implements LIRLowerable, Node.IterableNodeType { - public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, Kind.Void, Kind.Object); + public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class); @Input private ValueNode exception; diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -50,6 +50,7 @@ L2D(Long, Double), F2L(Float, Long), D2L(Double, Long), + UNSIGNED_I2L(Int, Long), MOV_I2F(Int, Float), MOV_L2D(Long, Double), MOV_F2I(Float, Int), @@ -104,6 +105,7 @@ case L2D: return ConstantNode.forDouble(c.asLong(), graph()); case F2L: return ConstantNode.forLong((long) c.asFloat(), graph()); case D2L: return ConstantNode.forLong((long) c.asDouble(), graph()); + case UNSIGNED_I2L: return ConstantNode.forLong(c.asInt() & 0xffffffffL, graph()); case MOV_I2F: return ConstantNode.forFloat(java.lang.Float.intBitsToFloat(c.asInt()), graph()); case MOV_L2D: return ConstantNode.forDouble(java.lang.Double.longBitsToDouble(c.asLong()), graph()); case MOV_F2I: return ConstantNode.forInt(java.lang.Float.floatToRawIntBits(c.asFloat()), graph()); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011, 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.calc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo(shortName = "|/|") +public final class UnsignedDivNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable { + + public UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) { + super(kind, x, y); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x().isConstant() && y().isConstant()) { + long yConst = y().asConstant().asLong(); + if (yConst == 0) { + return this; // this will trap, cannot canonicalize + } + if (kind() == Kind.Int) { + return ConstantNode.forInt(UnsignedMath.divide(x().asConstant().asInt(), (int) yConst), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(UnsignedMath.divide(x().asConstant().asLong(), yConst), graph()); + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 1) { + return x(); + } + if (CodeUtil.isPowerOf2(c)) { + return graph().unique(new UnsignedRightShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph()))); + } + } + return this; + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y()))); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, 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.calc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo(shortName = "|%|") +public final class UnsignedRemNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable { + + public UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) { + super(kind, x, y); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x().isConstant() && y().isConstant()) { + long yConst = y().asConstant().asLong(); + if (yConst == 0) { + return this; // this will trap, cannot canonicalize + } + if (kind() == Kind.Int) { + return ConstantNode.forInt(UnsignedMath.remainder(x().asConstant().asInt(), (int) yConst), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(UnsignedMath.remainder(x().asConstant().asLong(), yConst), graph()); + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 1) { + return ConstantNode.forIntegerKind(kind(), 0, graph()); + } else if (CodeUtil.isPowerOf2(c)) { + return graph().unique(new AndNode(kind(), x(), ConstantNode.forIntegerKind(kind(), c - 1, graph()))); + } + } + return this; + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()))); + } +} diff -r 46f945023189 -r 570d8e4c6dfb 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 Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -34,7 +34,7 @@ */ public final class ReadNode extends AccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable { - public ReadNode(ValueNode object, LocationNode location, Stamp stamp) { + public ReadNode(ValueNode object, ValueNode location, Stamp stamp) { super(object, location, stamp); } @@ -42,6 +42,12 @@ super(object, object.graph().add(new LocationNode(locationIdentity, kind, displacement)), StampFactory.forKind(kind)); } + public ReadNode(ValueNode object, ValueNode location) { + // Used by node intrinsics. Since the initial value for location is a parameter, i.e., a LocalNode, the + // constructor cannot use the declared type LocationNode + this(object, location, StampFactory.forNodeIntrinsic()); + } + @Override public void generate(LIRGeneratorTool gen) { gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck())); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -34,7 +35,7 @@ private final Descriptor descriptor; public RuntimeCallNode(Descriptor descriptor, ValueNode... arguments) { - super(StampFactory.forKind(descriptor.getResultKind()), arguments); + super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())), arguments); this.descriptor = descriptor; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -68,7 +68,7 @@ if (my.nonNull() && !other.nonNull()) { return this; } - if (my.type() != other.type() && other.type().isAssignableFrom(my.type())) { + if (!my.type().isAssignableFrom(other.type())) { return this; } } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -23,8 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.*; -import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -34,7 +33,7 @@ */ public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable { - public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, Kind.Void, Kind.Object); + public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, void.class, Object.class); @Input private ValueNode object; diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Mon Jan 07 13:04:04 2013 +0100 @@ -44,6 +44,11 @@ this.nonNaN = nonNaN; } + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(kind().toJavaClass()); + } + /** * The (inclusive) lower bound on the value described by this stamp. */ diff -r 46f945023189 -r 570d8e4c6dfb 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 Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Mon Jan 07 13:04:04 2013 +0100 @@ -42,6 +42,11 @@ } @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(kind().toJavaClass()); + } + + @Override public String toString() { return type.toString(); } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Jan 07 13:04:04 2013 +0100 @@ -52,6 +52,11 @@ this.mask = mask; } + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(kind().toJavaClass()); + } + /** * The (inclusive) lower bound on the value described by this stamp. */ diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Mon Jan 07 13:04:04 2013 +0100 @@ -43,6 +43,14 @@ } @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + if (type != null) { + return type; + } + return metaAccess.lookupJavaType(Object.class); + } + + @Override public boolean nonNull() { return nonNull; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java Mon Jan 07 13:04:04 2013 +0100 @@ -40,6 +40,12 @@ return kind; } + /** + * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the lookup of class meta + * data, therefore the {@link MetaAccessProvider} is mandatory. + */ + public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess); + public boolean nonNull() { return false; } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Jan 07 13:04:04 2013 +0100 @@ -135,17 +135,19 @@ if (shift.lowerBound() == shift.upperBound()) { long shiftMask = kind == Kind.Int ? 0x1FL : 0x3FL; long shiftCount = shift.lowerBound() & shiftMask; - long lowerBound; - long upperBound; - if (value.lowerBound() < 0) { - lowerBound = 0; - upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount; - } else { - lowerBound = value.lowerBound() >>> shiftCount; - upperBound = value.upperBound() >>> shiftCount; + if (shiftCount != 0) { + long lowerBound; + long upperBound; + if (value.lowerBound() < 0) { + lowerBound = 0; + upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount; + } else { + lowerBound = value.lowerBound() >>> shiftCount; + upperBound = value.upperBound() >>> shiftCount; + } + long mask = value.mask() >>> shiftCount; + return StampFactory.forInteger(kind, lowerBound, upperBound, mask); } - long mask = value.mask() >>> shiftCount; - return StampFactory.forInteger(kind, lowerBound, upperBound, mask); } long mask = IntegerStamp.maskFor(kind, value.lowerBound(), value.upperBound()); return stampForMask(kind, mask); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java --- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -32,9 +32,8 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.snippets.Snippet.DefaultSnippetInliningPolicy; import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy; +import com.oracle.graal.word.*; /** * Tests for the {@link Word} type. @@ -57,37 +56,41 @@ } @Test - public void test_arithmetic() { - long[] words = new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; + public void construction() { + long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, + Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; for (long word : words) { - for (int addend = -1000; addend < 1000; addend++) { - test("plus_int", word, addend); - test("plus_int", word, -addend); - test("minus_int", word, addend); - test("minus_int", word, -addend); - test("plus_long", word, (long) addend); - test("plus_long", word, (long) -addend); - test("minus_long", word, (long) addend); - test("minus_long", word, (long) -addend); + test("unsigned_long", word); + test("unsigned_int", (int) word); + test("signed_long", word); + test("signed_int", (int) word); + } + } - test("and_int", word, addend); - test("and_int", word, -addend); - test("or_int", word, addend); - test("or_int", word, -addend); - test("and_long", word, (long) addend); - test("and_long", word, (long) -addend); - test("or_long", word, (long) addend); - test("or_long", word, (long) -addend); - } + @Test + public void test_arithmetic() { + long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, + Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; + for (long word : words) { + test("unsigned_not", word); + test("signed_not", word); for (long addend : words) { - test("plus_int", word, (int) addend); - test("minus_int", word, (int) addend); - test("plus_int", word, -((int) addend)); - test("minus_int", word, -((int) addend)); - test("plus_long", word, addend); - test("minus_long", word, addend); - test("plus_long", word, -addend); - test("minus_long", word, -addend); + test("unsigned_plus_int", word, (int) addend); + test("unsigned_minus_int", word, (int) addend); + test("unsigned_plus_int", word, -((int) addend)); + test("unsigned_minus_int", word, -((int) addend)); + test("unsigned_plus_long", word, addend); + test("unsigned_minus_long", word, addend); + test("unsigned_plus_long", word, -addend); + test("unsigned_minus_long", word, -addend); + test("signed_plus_int", word, (int) addend); + test("signed_minus_int", word, (int) addend); + test("signed_plus_int", word, -((int) addend)); + test("signed_minus_int", word, -((int) addend)); + test("signed_plus_long", word, addend); + test("signed_minus_long", word, addend); + test("signed_plus_long", word, -addend); + test("signed_minus_long", word, -addend); test("and_int", word, (int) addend); test("or_int", word, (int) addend); @@ -114,84 +117,113 @@ } } - @Test - public void test_fromObject() { - inliningPolicy.set(new DefaultSnippetInliningPolicy(runtime(), new BoxingMethodPool(runtime())) { - @Override - public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - return super.shouldInline(method, caller) && !method.getName().equals("hashCode"); - } - }); - test("fromToObject", "object1", "object2"); - test("fromToObject", "object1", "object1"); - test("fromToObject", "object", null); - test("fromToObject", null, "object"); - test("fromToObject", null, null); - inliningPolicy.set(null); + @Snippet + public static long unsigned_long(long word) { + return Word.unsigned(word).rawValue(); + } + + @Snippet + public static long unsigned_int(int word) { + return Word.unsigned(word).rawValue(); + } + + @Snippet + public static long signed_long(long word) { + return Word.signed(word).rawValue(); + } + + @Snippet + public static long signed_int(int word) { + return Word.signed(word).rawValue(); + } + + @Snippet + public static long unsigned_plus_int(long word, int addend) { + return Word.unsigned(word).add(addend).rawValue(); + } + + @Snippet + public static long unsigned_minus_int(long word, int addend) { + return Word.unsigned(word).subtract(addend).rawValue(); } @Snippet - public static long plus_int(long word, int addend) { - return Word.fromLong(word).plus(addend).toLong(); + public static long unsigned_plus_long(long word, long addend) { + return Word.unsigned(word).add(Word.unsigned(addend)).rawValue(); + } + + @Snippet + public static long unsigned_minus_long(long word, long addend) { + return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue(); + } + + @Snippet + public static long signed_plus_int(long word, int addend) { + return Word.signed(word).add(addend).rawValue(); } @Snippet - public static long minus_int(long word, int addend) { - return Word.fromLong(word).minus(addend).toLong(); + public static long signed_minus_int(long word, int addend) { + return Word.signed(word).subtract(addend).rawValue(); + } + + @Snippet + public static long signed_plus_long(long word, long addend) { + return Word.signed(word).add(Word.signed(addend)).rawValue(); } @Snippet - public static long plus_long(long word, long addend) { - return Word.fromLong(word).plus(addend).toLong(); + public static long signed_minus_long(long word, long addend) { + return Word.signed(word).subtract(Word.signed(addend)).rawValue(); } @Snippet - public static long minus_long(long word, long addend) { - return Word.fromLong(word).minus(addend).toLong(); + public static long signed_not(long word) { + return Word.signed(word).not().rawValue(); + } + + @Snippet + public static long unsigned_not(long word) { + return Word.unsigned(word).not().rawValue(); } @Snippet public static boolean aboveOrEqual(long word1, long word2) { - return Word.fromLong(word1).aboveOrEqual(Word.fromLong(word2)); + return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2)); } @Snippet public static boolean above(long word1, long word2) { - return Word.fromLong(word1).above(Word.fromLong(word2)); + return Word.unsigned(word1).aboveThan(Word.unsigned(word2)); } @Snippet public static boolean belowOrEqual(long word1, long word2) { - return Word.fromLong(word1).belowOrEqual(Word.fromLong(word2)); + return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2)); } @Snippet public static boolean below(long word1, long word2) { - return Word.fromLong(word1).below(Word.fromLong(word2)); - } - - @Snippet - public static int fromToObject(Object o1, Object o2) { - return Word.fromObject(o1).toObject().hashCode() + Word.fromObject(o2).toObject().hashCode(); + return Word.unsigned(word1).belowThan(Word.unsigned(word2)); } @Snippet public static long and_int(long word, int addend) { - return Word.fromLong(word).and(addend).toLong(); + return Word.unsigned(word).and(addend).rawValue(); } @Snippet public static long or_int(long word, int addend) { - return Word.fromLong(word).or(addend).toLong(); + return Word.unsigned(word).or(addend).rawValue(); } @Snippet public static long and_long(long word, long addend) { - return Word.fromLong(word).and(addend).toLong(); + return Word.unsigned(word).and(Word.unsigned(addend)).rawValue(); } @Snippet public static long or_long(long word, long addend) { - return Word.fromLong(word).or(addend).toLong(); + return Word.unsigned(word).or(Word.unsigned(addend)).rawValue(); } } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java Mon Jan 07 13:04:04 2013 +0100 @@ -37,9 +37,9 @@ */ public final class Log { - public static final Descriptor LOG_PRIMITIVE = new Descriptor("logPrimitive", false, Kind.Void, Kind.Int, Kind.Long, Kind.Boolean); - public static final Descriptor LOG_OBJECT = new Descriptor("logObject", false, Kind.Void, Kind.Object, Kind.Int); - public static final Descriptor LOG_PRINTF = new Descriptor("logPrintf", false, Kind.Void, Kind.Object, Kind.Long, Kind.Long, Kind.Long); + public static final Descriptor LOG_PRIMITIVE = new Descriptor("logPrimitive", false, void.class, int.class, long.class, boolean.class); + public static final Descriptor LOG_OBJECT = new Descriptor("logObject", false, void.class, Object.class, int.class); + public static final Descriptor LOG_PRINTF = new Descriptor("logPrintf", false, void.class, Object.class, long.class, long.class, long.class); // Note: Must be kept in sync with constants in c1_Runtime1.hpp private static final int LOG_OBJECT_NEWLINE = 0x01; diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java Mon Jan 07 13:04:04 2013 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.snippets; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.extended.*; @@ -84,9 +83,9 @@ } } - public static final Descriptor ARITHMETIC_SIN = new Descriptor("arithmeticSin", false, Kind.Double, Kind.Double); - public static final Descriptor ARITHMETIC_COS = new Descriptor("arithmeticCos", false, Kind.Double, Kind.Double); - public static final Descriptor ARITHMETIC_TAN = new Descriptor("arithmeticTan", false, Kind.Double, Kind.Double); + public static final Descriptor ARITHMETIC_SIN = new Descriptor("arithmeticSin", false, double.class, double.class); + public static final Descriptor ARITHMETIC_COS = new Descriptor("arithmeticCos", false, double.class, double.class); + public static final Descriptor ARITHMETIC_TAN = new Descriptor("arithmeticTan", false, double.class, double.class); @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true) public static native double callDouble(@ConstantNodeParameter Descriptor descriptor, double value); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Mon Jan 07 13:04:04 2013 +0100 @@ -29,8 +29,8 @@ import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.Word.Operation; import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.word.*; /** * A snippet is a Graal graph expressed as a Java source method. Graal snippets can be used for: @@ -95,7 +95,7 @@ return false; } } - if (method.getAnnotation(Operation.class) != null) { + if (method.getAnnotation(Word.Operation.class) != null) { return false; } if (pool.isSpecialMethod(method)) { diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Jan 07 13:04:04 2013 +0100 @@ -35,11 +35,13 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; import com.oracle.graal.snippets.Snippet.DefaultSnippetInliningPolicy; import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy; +import com.oracle.graal.word.phases.*; /** * Utility for snippet {@linkplain #install(Class) installation}. @@ -122,13 +124,13 @@ } Method originalMethod = originalClazz.getDeclaredMethod(originalName, originalParameters); if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) { - throw new RuntimeException("Snippet has incompatible return type"); + throw new RuntimeException("Snippet has incompatible return type: " + method); } int modifiers = method.getModifiers(); if (!Modifier.isStatic(modifiers)) { - throw new RuntimeException("Snippets must be static methods"); + throw new RuntimeException("Snippets must be static methods: " + method); } else if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native"); + throw new RuntimeException("Snippet must not be abstract or native: " + method); } ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet), true); @@ -191,6 +193,7 @@ } private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method; final StructuredGraph graph = new StructuredGraph(method); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); @@ -198,19 +201,19 @@ Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName()); - new SnippetVerificationPhase(runtime).apply(graph); + new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.methodCallTarget(); ResolvedJavaMethod callee = callTarget.targetMethod(); - if (policy.shouldInline(callee, method)) { + if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) { StructuredGraph targetGraph = parseGraph(callee, policy); InliningUtil.inline(invoke, targetGraph, true); Debug.dump(graph, "after inlining %s", callee); if (GraalOptions.OptCanonicalizer) { - new WordTypeRewriterPhase(target.wordKind).apply(graph); + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } } @@ -218,7 +221,7 @@ new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); - new WordTypeRewriterPhase(target.wordKind).apply(graph); + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Jan 07 13:04:04 2013 +0100 @@ -44,6 +44,8 @@ import com.oracle.graal.snippets.Snippet.Varargs; import com.oracle.graal.snippets.Snippet.VarargsParameter; import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.phases.*; /** * A snippet template is a graph created by parsing a snippet method and then @@ -239,7 +241,7 @@ replacements.put(snippetGraph.start(), snippetCopy.start()); int parameterCount = signature.getParameterCount(false); - assert checkTemplate(key, parameterCount, method, signature); + assert checkTemplate(runtime, key, parameterCount, method, signature); Parameter[] parameterAnnotations = new Parameter[parameterCount]; VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount]; @@ -278,7 +280,7 @@ if (!replacements.isEmpty()) { // Do deferred intrinsification of node intrinsics new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); - new WordTypeRewriterPhase(target.wordKind).apply(snippetCopy); + new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); new CanonicalizerPhase(null, runtime, assumptions, 0, null).apply(snippetCopy); } @@ -406,9 +408,9 @@ return true; } - private static boolean checkConstantArgument(final ResolvedJavaMethod method, Signature signature, int i, String name, Object arg, Kind kind) { + private static boolean checkConstantArgument(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Object arg, Kind kind) { ResolvedJavaType type = signature.getParameterType(i, method.getDeclaringClass()).resolve(method.getDeclaringClass()); - if (WordTypeRewriterPhase.isWord(type)) { + if (runtime.lookupJavaType(WordBase.class).isAssignableFrom(type)) { assert arg instanceof Constant : method + ": word constant parameters must be passed boxed in a Constant value: " + arg; return true; } @@ -487,14 +489,22 @@ } } else if (parameter instanceof LocalNode[]) { LocalNode[] locals = (LocalNode[]) parameter; - Object array = argument; - assert array != null && array.getClass().isArray(); int length = locals.length; - assert Array.getLength(array) == length : length + " != " + Array.getLength(array); + List list = null; + Object array = null; + if (argument instanceof List) { + list = (List) argument; + assert list.size() == length : length + " != " + list.size(); + } else { + array = argument; + assert array != null && array.getClass().isArray(); + assert Array.getLength(array) == length : length + " != " + Array.getLength(array); + } + for (int j = 0; j < length; j++) { LocalNode local = locals[j]; assert local != null; - Object value = Array.get(array, j); + Object value = list != null ? list.get(j) : Array.get(array, j); if (value instanceof ValueNode) { replacements.put(local, (ValueNode) value); } else { @@ -696,7 +706,7 @@ return buf.append(')').toString(); } - private static boolean checkTemplate(SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) { + private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) { Set expected = new HashSet<>(); for (int i = 0; i < parameterCount; i++) { ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); @@ -708,7 +718,7 @@ expected.add(name); Kind kind = signature.getParameterKind(i); assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert checkConstantArgument(method, signature, i, c.value(), key.get(name), kind); + assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind); } else if (vp != null) { assert p == null; String name = vp.value(); diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Fri Dec 21 15:54:59 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2011, 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.snippets; - -import static com.oracle.graal.snippets.WordTypeRewriterPhase.*; - -import java.lang.reflect.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.snippets.Word.*; - -/** - * Verifies invariants that must hold for snippet code above and beyond normal - * bytecode verification. - */ -public class SnippetVerificationPhase extends Phase { - - private final MetaAccessProvider metaAccess; - - public SnippetVerificationPhase(MetaAccessProvider metaAccess) { - this.metaAccess = metaAccess; - } - - @Override - protected void run(StructuredGraph graph) { - ResolvedJavaType wordType = metaAccess.lookupJavaType(Word.class); - - for (ValueNode node : graph.getNodes().filter(ValueNode.class)) { - for (Node usage : node.usages()) { - if (usage instanceof AccessMonitorNode) { - verify(!isWord(node), node, usage, "word value has no monitor"); - } else if (usage instanceof LoadFieldNode) { - verify(!isWord(node) || ((LoadFieldNode) usage).object() != node, node, usage, "cannot load from word value"); - } else if (usage instanceof StoreFieldNode) { - verify(!isWord(node) || ((StoreFieldNode) usage).object() != node, node, usage, "cannot store to word value"); - } else if (usage instanceof CheckCastNode) { - verify(!isWord(node), node, usage, "word value cannot be cast"); - verify(!isWord(((CheckCastNode) usage).type()), node, usage, "cannot cast to word value"); - } else if (usage instanceof LoadIndexedNode) { - verify(!isWord(node) || ((LoadIndexedNode) usage).array() != node, node, usage, "cannot load from word value"); - verify(!isWord(node) || ((LoadIndexedNode) usage).index() != node, node, usage, "cannot use word value as index"); - } else if (usage instanceof StoreIndexedNode) { - verify(!isWord(node) || ((StoreIndexedNode) usage).array() != node, node, usage, "cannot store to word value"); - verify(!isWord(node) || ((StoreIndexedNode) usage).index() != node, node, usage, "cannot use word value as index"); - verify(!isWord(node) || ((StoreIndexedNode) usage).value() != node, node, usage, "cannot store word value to array"); - } else if (usage instanceof MethodCallTargetNode) { - MethodCallTargetNode callTarget = (MethodCallTargetNode) usage; - ResolvedJavaMethod method = callTarget.targetMethod(); - if (method.getAnnotation(NodeIntrinsic.class) == null) { - Invoke invoke = (Invoke) callTarget.usages().first(); - NodeInputList arguments = callTarget.arguments(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); - int argc = 0; - if (!isStatic) { - ValueNode receiver = arguments.get(argc); - if (receiver == node && isWord(node)) { - Operation operation = method.getAnnotation(Word.Operation.class); - verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + method); - } - argc++; - } - Signature signature = method.getSignature(); - for (int i = 0; i < signature.getParameterCount(false); i++) { - ValueNode argument = arguments.get(argc); - if (argument == node) { - ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); - verify(type.equals(wordType) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); - } - argc++; - } - } - } else if (usage instanceof ObjectEqualsNode) { - ObjectEqualsNode compare = (ObjectEqualsNode) usage; - if (compare.x() == node || compare.y() == node) { - verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and non-word type in use of '==' or '!='"); - } - } else if (usage instanceof ArrayLengthNode) { - verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value"); - } else if (usage instanceof PhiNode) { - if (!(node instanceof MergeNode)) { - PhiNode phi = (PhiNode) usage; - for (ValueNode input : phi.values()) { - verify(isWord(node) == isWord(input), node, input, "cannot merge word and non-word values"); - } - } - } - } - } - } - - private static void verify(boolean condition, Node node, Node usage, String message) { - if (!condition) { - error(node, usage, message); - } - } - - private static void error(Node node, Node usage, String message) { - throw new GraalInternalError(String.format("Snippet verification error: %s" + - "%n node: %s (%s)" + - "%n usage: %s (%s)", message, node, sourceLocation(node), usage, sourceLocation(usage))); - } - - private static String sourceLocation(Node n) { - if (n instanceof PhiNode) { - StringBuilder buf = new StringBuilder(); - for (Node usage : n.usages()) { - String loc = sourceLocation(usage); - if (!loc.equals("")) { - if (buf.length() != 0) { - buf.append(", "); - } - buf.append(loc); - } - } - return buf.toString(); - } else { - String loc = GraphUtil.approxSourceLocation(n); - return loc == null ? "" : loc; - } - } -} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2011, 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.snippets; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.snippets.nodes.*; + +/** + * Snippets for {@link sun.misc.Unsafe} methods. + */ +@ClassSubstitution(sun.misc.Unsafe.class) +public class UnsafeSnippets implements SnippetsInterface { + @MethodSubstitution(isStatic = false) + public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) { + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); + } + + @MethodSubstitution(isStatic = false) + public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) { + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); + } + + @MethodSubstitution(isStatic = false) + public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) { + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); + } + + @MethodSubstitution(isStatic = false) + public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + return UnsafeLoadNode.load(o, 0, offset, Kind.Object); + } + + @MethodSubstitution(isStatic = false) + public static Object getObjectVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + Object result = getObject(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Object); + } + + @MethodSubstitution(isStatic = false) + public static void putObjectVolatile(final Object thisObj, Object o, long offset, Object x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putObject(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putOrderedObject(final Object thisObj, Object o, long offset, Object x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putObject(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + Integer value = UnsafeLoadNode.load(o, 0, offset, Kind.Int); + return value; + } + + @MethodSubstitution(isStatic = false) + public static int getIntVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + int result = getInt(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Int); + } + + @MethodSubstitution(isStatic = false) + public static void putIntVolatile(final Object thisObj, Object o, long offset, int x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putInt(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putOrderedInt(final Object thisObj, Object o, long offset, int x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putInt(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Boolean result = UnsafeLoadNode.load(o, 0, offset, Kind.Boolean); + return result; + } + + @MethodSubstitution(isStatic = false) + public static boolean getBooleanVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + boolean result = getBoolean(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Boolean); + } + + @MethodSubstitution(isStatic = false) + public static void putBooleanVolatile(final Object thisObj, Object o, long offset, boolean x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putBoolean(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Byte result = UnsafeLoadNode.load(o, 0, offset, Kind.Byte); + return result; + } + + @MethodSubstitution(isStatic = false) + public static byte getByteVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + byte result = getByte(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Byte); + } + + @MethodSubstitution(isStatic = false) + public static void putByteVolatile(final Object thisObj, Object o, long offset, byte x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putByte(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Short result = UnsafeLoadNode.load(o, 0, offset, Kind.Short); + return result; + } + + @MethodSubstitution(isStatic = false) + public static short getShortVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + short result = getShort(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Short); + } + + @MethodSubstitution(isStatic = false) + public static void putShortVolatile(final Object thisObj, Object o, long offset, short x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putShort(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Character result = UnsafeLoadNode.load(o, 0, offset, Kind.Char); + return result; + } + + @MethodSubstitution(isStatic = false) + public static char getCharVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + char result = getChar(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Char); + } + + @MethodSubstitution(isStatic = false) + public static void putCharVolatile(final Object thisObj, Object o, long offset, char x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putChar(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Long result = UnsafeLoadNode.load(o, 0, offset, Kind.Long); + return result; + } + + @MethodSubstitution(isStatic = false) + public static long getLongVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + long result = getLong(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Long); + } + + @MethodSubstitution(isStatic = false) + public static void putLongVolatile(final Object thisObj, Object o, long offset, long x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putLong(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putOrderedLong(final Object thisObj, Object o, long offset, long x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putLong(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Float result = UnsafeLoadNode.load(o, 0, offset, Kind.Float); + return result; + } + + @MethodSubstitution(isStatic = false) + public static float getFloatVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + float result = getFloat(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Float); + } + + @MethodSubstitution(isStatic = false) + public static void putFloatVolatile(final Object thisObj, Object o, long offset, float x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putFloat(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Double result = UnsafeLoadNode.load(o, 0, offset, Kind.Double); + return result; + } + + @MethodSubstitution(isStatic = false) + public static double getDoubleVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + double result = getDouble(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Double); + } + + @MethodSubstitution(isStatic = false) + public static void putDoubleVolatile(final Object thisObj, Object o, long offset, double x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putDouble(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putByte(@SuppressWarnings("unused") final Object thisObj, long address, byte value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putShort(@SuppressWarnings("unused") final Object thisObj, long address, short value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putChar(@SuppressWarnings("unused") final Object thisObj, long address, char value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putInt(@SuppressWarnings("unused") final Object thisObj, long address, int value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putLong(@SuppressWarnings("unused") final Object thisObj, long address, long value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putFloat(@SuppressWarnings("unused") final Object thisObj, long address, float value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putDouble(@SuppressWarnings("unused") final Object thisObj, long address, double value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static byte getByte(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Byte); + } + + @MethodSubstitution(isStatic = false) + public static short getShort(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Short); + } + + @MethodSubstitution(isStatic = false) + public static char getChar(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Char); + } + + @MethodSubstitution(isStatic = false) + public static int getInt(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Int); + } + + @MethodSubstitution(isStatic = false) + public static long getLong(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Long); + } + + @MethodSubstitution(isStatic = false) + public static float getFloat(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Float); + } + + @MethodSubstitution(isStatic = false) + public static double getDouble(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Double); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java Mon Jan 07 13:04:04 2013 +0100 @@ -26,6 +26,8 @@ import static com.oracle.graal.nodes.calc.Condition.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.calc.*; /** * Snippets for {@link UnsignedMath}. @@ -82,4 +84,44 @@ public static boolean belowOrEqual(long a, long b) { return !materialize(BT, b, a); } + + /** + * Unsigned division for two numbers. + */ + public static int divide(int a, int b) { + return unsignedDivide(Kind.Int, a, b); + } + + /** + * Unsigned remainder for two numbers. + */ + public static int remainder(int a, int b) { + return unsignedRemainder(Kind.Int, a, b); + } + + /** + * Unsigned division for two numbers. + */ + public static long divide(long a, long b) { + return unsignedDivide(Kind.Long, a, b); + } + + /** + * Unsigned remainder for two numbers. + */ + public static long remainder(long a, long b) { + return unsignedRemainder(Kind.Long, a, b); + } + + @NodeIntrinsic(UnsignedDivNode.class) + private static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b); + + @NodeIntrinsic(UnsignedDivNode.class) + private static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b); + + @NodeIntrinsic(UnsignedRemNode.class) + private static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b); + + @NodeIntrinsic(UnsignedRemNode.class) + private static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b); } diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java Fri Dec 21 15:54:59 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,260 +0,0 @@ -/* - * 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.snippets; - -import static com.oracle.graal.snippets.Word.Opcode.*; - -import java.lang.annotation.*; - -//JaCoCo Exclude - -/** - * Special type for use in snippets to represent machine word sized data. - */ -public final class Word { - - /** - * Links a method to a canonical operation represented by an {@link Opcode} value. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) - public @interface Operation { - Opcode value(); - } - - /** - * The canonical {@link Operation} represented by a method in the {@link Word} class. - */ - public enum Opcode { - ZERO, - W2A, - A2W, - L2W, - I2W, - W2L, - W2I, - PLUS, - MINUS, - OR, - AND, - XOR, - READ_INT, - READ_WORD, - READ_OBJECT, - READ_FINAL_OBJECT, - BELOW, - BELOW_EQUAL, - ABOVE, - ABOVE_EQUAL; - } - - private Word(long value, Object object) { - assert object == null || value == 0L; - this.value = value; - this.object = object; - } - - private final long value; - private final Object object; - - @Operation(ZERO) - public static Word zero() { - return new Word(0L, null); - } - - @Operation(W2A) - public Object toObject() { - assert value == 0L; - return object; - } - - @Operation(A2W) - public static Word fromObject(Object value) { - return new Word(0L, value); - } - - @Operation(L2W) - public static Word fromLong(long value) { - return new Word(value, null); - } - - @Operation(I2W) - public static Word fromInt(int value) { - return new Word(value, null); - } - - @Operation(W2I) - public int toInt() { - assert object == null; - return (int) value; - } - - @Operation(W2L) - public long toLong() { - assert object == null; - return value; - } - - @Operation(ABOVE) - public boolean above(Word other) { - assert object == null; - assert other.object == null; - long a = value; - long b = other.value; - return (a > b) ^ ((a < 0) != (b < 0)); - } - - @Operation(ABOVE_EQUAL) - public boolean aboveOrEqual(Word other) { - assert object == null; - assert other.object == null; - long a = value; - long b = other.value; - return (a >= b) ^ ((a < 0) != (b < 0)); - } - - @Operation(BELOW) - public boolean below(Word other) { - assert object == null; - assert other.object == null; - long a = value; - long b = other.value; - return (a < b) ^ ((a < 0) != (b < 0)); - } - - @Operation(BELOW_EQUAL) - public boolean belowOrEqual(Word other) { - assert object == null; - assert other.object == null; - long a = value; - long b = other.value; - return (a <= b) ^ ((a < 0) != (b < 0)); - } - - @Operation(PLUS) - public Word plus(int addend) { - assert object == null; - return new Word(value + addend, null); - } - - @Operation(PLUS) - public Word plus(long addend) { - assert object == null; - return new Word(value + addend, null); - } - - @Operation(PLUS) - public Word plus(Word addend) { - assert object == null; - return new Word(value + addend.value, null); - } - - @Operation(MINUS) - public Word minus(int addend) { - assert object == null; - return new Word(value - addend, null); - } - - @Operation(MINUS) - public Word minus(long addend) { - assert object == null; - return new Word(value - addend, null); - } - - @Operation(MINUS) - public Word minus(Word addend) { - assert object == null; - return new Word(value - addend.value, null); - } - - @Operation(OR) - public Word or(int other) { - assert object == null; - return new Word(value | other, null); - } - - @Operation(OR) - public Word or(long other) { - assert object == null; - return new Word(value | other, null); - } - - @Operation(OR) - public Word or(Word other) { - assert object == null; - return new Word(value | other.value, null); - } - - @Operation(AND) - public Word and(int other) { - assert object == null; - return new Word(value & other, null); - } - - @Operation(AND) - public Word and(long other) { - assert object == null; - return new Word(value & other, null); - } - - @Operation(AND) - public Word and(Word other) { - assert object == null; - return new Word(value & other.value, null); - } - - @Operation(XOR) - public Word xor(int other) { - assert object == null; - return new Word(value | other, null); - } - - @Operation(XOR) - public Word xor(long other) { - assert object == null; - return new Word(value | other, null); - } - - @Operation(XOR) - public Word xor(Word other) { - assert object == null; - return new Word(value | other.value, null); - } - - @Operation(READ_INT) - public native int readInt(int offset); - - @Operation(READ_WORD) - public native Word readWord(int offset); - - @Operation(READ_OBJECT) - public native Object readObject(int offset); - - /** - * Reads an object value from a location that is guaranteed not be to modified after this read. - * - * @param offset the offset from this base address of the location to be read - */ - @Operation(READ_FINAL_OBJECT) - public native Object readFinalObject(int offset); -} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Fri Dec 21 15:54:59 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ -/* - * 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.snippets; - -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.calc.ConvertNode.Op; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.util.*; -import com.oracle.graal.snippets.Word.Opcode; -import com.oracle.graal.snippets.Word.Operation; - -/** - * Transforms all uses of the {@link Word} class into unsigned - * operations on {@code int} or {@code long} values, depending - * on the word kind of the underlying platform. - */ -public class WordTypeRewriterPhase extends Phase { - - public static final String WordClassName = MetaUtil.toInternalName(Word.class.getName()); - - private final Kind wordKind; - - public WordTypeRewriterPhase(Kind wordKind) { - this.wordKind = wordKind; - } - - @Override - protected void run(StructuredGraph graph) { - for (Node n : GraphOrder.forwardGraph(graph)) { - if (n instanceof ValueNode) { - ValueNode valueNode = (ValueNode) n; - if (isWord(valueNode)) { - changeToWord(valueNode); - } - } - } - - // Remove unnecessary/redundant unsafe casts - for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) { - if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) { - graph.replaceFloating(unsafeCastNode, unsafeCastNode.object()); - } - } - - // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words - for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { - ValueNode x = objectEqualsNode.x(); - ValueNode y = objectEqualsNode.y(); - if (x.kind() == wordKind || y.kind() == wordKind) { - assert x.kind() == wordKind; - assert y.kind() == wordKind; - graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y))); - } - } - - // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words - for (LoadIndexedNode load : graph.getNodes().filter(LoadIndexedNode.class).snapshot()) { - if (isWord(load)) { - load.setStamp(StampFactory.forKind(wordKind)); - } - } - - for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { - ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); - Operation operation = targetMethod.getAnnotation(Word.Operation.class); - if (operation != null) { - NodeInputList arguments = callTargetNode.arguments(); - Invoke invoke = (Invoke) callTargetNode.usages().first(); - assert invoke != null : callTargetNode.targetMethod(); - - Opcode opcode = operation.value(); - switch (opcode) { - case ZERO: { - assert arguments.size() == 0; - replace(invoke, wordKind == Kind.Long ? ConstantNode.forLong(0L, graph) : ConstantNode.forInt(0, graph)); - break; - } - - case ABOVE: { - assert arguments.size() == 2; - replace(invoke, compare(Condition.AT, graph, arguments.first(), arguments.last())); - break; - } - - case ABOVE_EQUAL: { - assert arguments.size() == 2; - replace(invoke, compare(Condition.AE, graph, arguments.first(), arguments.last())); - break; - } - - case BELOW: { - assert arguments.size() == 2; - replace(invoke, compare(Condition.BT, graph, arguments.first(), arguments.last())); - break; - } - - case BELOW_EQUAL: { - assert arguments.size() == 2; - replace(invoke, compare(Condition.BE, graph, arguments.first(), arguments.last())); - break; - } - - case PLUS: { - ValueNode addend = asWordKind(graph, arguments.last()); - IntegerAddNode op = graph.unique(new IntegerAddNode(wordKind, arguments.first(), addend)); - replace(invoke, op); - break; - } - - case MINUS: { - ValueNode addend = asWordKind(graph, arguments.last()); - IntegerSubNode op = graph.unique(new IntegerSubNode(wordKind, arguments.first(), addend)); - replace(invoke, op); - break; - } - - case AND: { - ValueNode operand = asWordKind(graph, arguments.last()); - AndNode op = graph.unique(new AndNode(wordKind, arguments.first(), operand)); - replace(invoke, op); - break; - } - - case OR: { - ValueNode operand = asWordKind(graph, arguments.last()); - OrNode op = graph.unique(new OrNode(wordKind, arguments.first(), operand)); - replace(invoke, op); - break; - } - - case XOR: { - ValueNode operand = asWordKind(graph, arguments.last()); - XorNode op = graph.unique(new XorNode(wordKind, arguments.first(), operand)); - replace(invoke, op); - break; - } - - case W2A: { - assert arguments.size() == 1; - ValueNode value = arguments.first(); - UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, ((ValueNode) invoke).stamp())); - replace(invoke, cast); - break; - } - - case W2I: { - assert arguments.size() == 1; - ValueNode value = arguments.first(); - ValueNode intValue = fromWordKindTo(graph, value, Kind.Int); - replace(invoke, intValue); - break; - } - - case W2L: { - assert arguments.size() == 1; - ValueNode value = arguments.first(); - ValueNode longValue = fromWordKindTo(graph, value, Kind.Long); - replace(invoke, longValue); - break; - } - - case A2W: { - assert arguments.size() == 1; - ValueNode value = arguments.first(); - assert value.kind() == Kind.Object : value + ", " + targetMethod; - UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, StampFactory.forKind(wordKind))); - replace(invoke, cast); - break; - } - - case L2W: { - assert arguments.size() == 1; - ValueNode value = arguments.first(); - assert value.kind() == Kind.Long; - ValueNode wordValue = asWordKind(graph, value); - replace(invoke, wordValue); - break; - } - - case I2W: { - assert arguments.size() == 1; - ValueNode value = arguments.first(); - assert value.kind() == Kind.Int; - replace(invoke, asWordKind(graph, value)); - break; - } - - case READ_INT: - case READ_OBJECT: - case READ_WORD: { - replaceRead(graph, arguments, invoke, LocationNode.ANY_LOCATION); - break; - } - - case READ_FINAL_OBJECT: { - replaceRead(graph, arguments, invoke, LocationNode.FINAL_LOCATION); - break; - } - - default: { - throw new GraalInternalError("Unknown opcode: %s", opcode); - } - } - } - } - } - - protected void replaceRead(StructuredGraph graph, NodeInputList arguments, Invoke invoke, Object locationIdentity) { - assert arguments.size() == 2; - ValueNode base = arguments.first(); - IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, arguments.last(), graph, false); - ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp())); - graph.addBeforeFixed(invoke.node(), read); - // The read must not float outside its block otherwise it may float above an explicit zero check on its base address - read.dependencies().add(BeginNode.prevBegin(invoke.node())); - replace(invoke, read); - } - - protected void replace(Invoke invoke, ValueNode value) { - FixedNode next = invoke.next(); - invoke.setNext(null); - invoke.node().replaceAtPredecessor(next); - invoke.node().replaceAtUsages(value); - GraphUtil.killCFG(invoke.node()); - } - - /** - * Creates comparison node for a given condition and two input values. - */ - private ValueNode compare(Condition condition, StructuredGraph graph, ValueNode left, ValueNode right) { - assert condition.isUnsigned() : condition; - assert left.kind() == wordKind; - assert right.kind() == wordKind; - - // mirroring gets the condition into canonical form - boolean mirror = condition.canonicalMirror(); - - ValueNode a = mirror ? right : left; - ValueNode b = mirror ? left : right; - - MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b))); - - ValueNode op; - if (condition.canonicalNegate()) { - op = (ValueNode) materialize.negate(); - } else { - op = materialize; - } - return op; - } - - /** - * Adds a node if necessary to convert a given value into the word kind. - * - * @return the node for {@code value} producing a value of word kind - */ - private ValueNode asWordKind(StructuredGraph graph, ValueNode value) { - if (value.kind() != wordKind) { - Op op; - if (wordKind == Kind.Long) { - assert value.kind().getStackKind() == Kind.Int; - op = Op.I2L; - } else { - assert wordKind.getStackKind() == Kind.Int; - assert value.kind() == Kind.Long; - op = Op.L2I; - } - return graph.unique(new ConvertNode(op, value)); - } - return value; - } - - private static ValueNode fromWordKindTo(StructuredGraph graph, ValueNode value, Kind to) { - Kind from = value.kind(); - if (from != to) { - Op op; - if (from == Kind.Long) { - op = Op.L2I; - } else { - assert from.getStackKind() == Kind.Int; - op = Op.I2L; - } - return graph.unique(new ConvertNode(op, value)); - } - return value; - } - - public static boolean isWord(ValueNode node) { - node.inferStamp(); - if (node.stamp() == StampFactory.forWord()) { - return true; - } - if (node instanceof LoadIndexedNode) { - return isWord(((LoadIndexedNode) node).array().objectStamp().type().getComponentType()); - } - if (node.kind() == Kind.Object) { - return isWord(node.objectStamp().type()); - } - return false; - } - - public static boolean isWord(ResolvedJavaType type) { - if (type != null && type.getName().equals(WordClassName)) { - return true; - } - return false; - } - - private void changeToWord(ValueNode valueNode) { - assert !(valueNode instanceof ConstantNode) : "boxed Word constants should not appear in a snippet graph: " + valueNode + ", stamp: " + valueNode.stamp(); - valueNode.setStamp(StampFactory.forKind(wordKind)); - } -} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java Fri Dec 21 15:54:59 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -26,7 +26,7 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; +import com.oracle.graal.word.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectReadNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectReadNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.snippets.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * A special purpose store node that differs from {@link UnsafeStoreNode} in that + * it is not a {@link StateSplit} and takes a computed address instead of an object. + */ +public class DirectReadNode extends FixedWithNextNode implements LIRLowerable { + @Input private ValueNode address; + private final Kind readKind; + + public DirectReadNode(ValueNode address, Kind readKind) { + super(StampFactory.forKind(readKind)); + this.address = address; + this.readKind = readKind; + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.setResult(this, gen.emitLoad(new Address(readKind, gen.operand(address)), false)); + } + + @NodeIntrinsic + public static native T read(long address, @ConstantNodeParameter Kind kind); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,75 @@ +/* + * 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.snippets.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * A special purpose store node that differs from {@link UnsafeStoreNode} in that + * it is not a {@link StateSplit} and takes a computed address instead of an object. + */ +public class DirectStoreNode extends FixedWithNextNode implements LIRLowerable { + @Input private ValueNode address; + @Input private ValueNode value; + + public DirectStoreNode(ValueNode address, ValueNode value) { + super(StampFactory.forVoid()); + this.address = address; + this.value = value; + } + + @NodeIntrinsic + public static native void store(long address, boolean value); + + @NodeIntrinsic + public static native void store(long address, byte value); + + @NodeIntrinsic + public static native void store(long address, short value); + + @NodeIntrinsic + public static native void store(long address, char value); + + @NodeIntrinsic + public static native void store(long address, int value); + + @NodeIntrinsic + public static native void store(long address, long value); + + @NodeIntrinsic + public static native void store(long address, float value); + + @NodeIntrinsic + public static native void store(long address, double value); + + @Override + public void generate(LIRGeneratorTool gen) { + Value v = gen.operand(value); + gen.emitStore(new Address(v.getKind(), gen.operand(address)), v, false); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,521 @@ +/* + * 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.graal.word; + +public interface Pointer extends Unsigned { + + /** + * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type checks are performed. + * The caller must ensure that the Pointer contains a valid Java object that can i.e., processed by the garbage + * collector. + * + * @return this Pointer cast to Object. + */ + Object toObject(); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + byte readByte(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + char readChar(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + short readShort(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + int readInt(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + long readLong(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + float readFloat(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + double readDouble(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + Word readWord(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + Object readObject(WordBase offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + byte readByte(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + char readChar(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + short readShort(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + int readInt(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + long readLong(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + float readFloat(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + double readDouble(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + Word readWord(int offset); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + Object readObject(int offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + byte readFinalByte(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + char readFinalChar(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + short readFinalShort(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + int readFinalInt(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + long readFinalLong(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + float readFinalFloat(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + double readFinalDouble(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + Word readFinalWord(WordBase offset); + + /** + * Reads the constant memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The caller guarantees that the memory content is final, i.e., never changing. The compiler can therefore + * eliminate memory accesses more aggressively.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + Object readFinalObject(WordBase offset); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeByte(WordBase offset, byte val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeChar(WordBase offset, char val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeShort(WordBase offset, Short val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeInt(WordBase offset, int val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeLong(WordBase offset, long val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeFloat(WordBase offset, float val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeDouble(WordBase offset, double val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeWord(WordBase offset, WordBase val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes.
+ * The offset is always treated as a {@link Signed} value. However, the static type is {@link WordBase} to avoid the + * frequent casts to of {@link Unsigned} values (where the caller knows that the highest-order bit of the unsigned + * value is never used). + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeObject(WordBase offset, Object val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeByte(int offset, byte val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeChar(int offset, char val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeShort(int offset, short val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeInt(int offset, int val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeLong(int offset, long val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeFloat(int offset, float val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeDouble(int offset, double val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeWord(int offset, WordBase val); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in bytes. + * + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + void writeObject(int offset, Object val); + + // Math functions that are defined in Unsigned, but known to preserve the pointer-characteristics. + // It is therefore safe that they return a static type of Pointer instead of Unsigned. + + @Override + Pointer add(Unsigned val); + + @Override + Pointer add(int val); + + @Override + Pointer subtract(Unsigned val); + + @Override + Pointer subtract(int val); + + @Override + Pointer and(Unsigned val); + + @Override + Pointer and(int val); + + @Override + Pointer or(Unsigned val); + + @Override + Pointer or(int val); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,266 @@ +/* + * 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.graal.word; + +public interface Signed extends WordBase { + + /** + * Returns a Signed whose value is {@code (this + val)}. + * + * @param val value to be added to this Signed. + * @return {@code this + val} + */ + Signed add(Signed val); + + /** + * Returns a Signed whose value is {@code (this - val)}. + * + * @param val value to be subtracted from this Signed. + * @return {@code this - val} + */ + Signed subtract(Signed val); + + /** + * Returns a Signed whose value is {@code (this * val)}. + * + * @param val value to be multiplied by this Signed. + * @return {@code this * val} + */ + Signed multiply(Signed val); + + /** + * Returns a Signed whose value is {@code (this / val)}. + * + * @param val value by which this Signed is to be divided. + * @return {@code this / val} + */ + Signed signedDivide(Signed val); + + /** + * Returns a Signed whose value is {@code (this % val)}. + * + * @param val value by which this Signed is to be divided, and the remainder computed. + * @return {@code this % val} + */ + Signed signedRemainder(Signed val); + + /** + * Returns a Signed whose value is {@code (this << n)}. + * + * @param n shift distance, in bits. + * @return {@code this << n} + */ + Signed shiftLeft(Unsigned n); + + /** + * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed. + * + * @param n shift distance, in bits. + * @return {@code this >> n} + */ + Signed signedShiftRight(Unsigned n); + + /** + * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed if and only if this + * and val are both negative.) + * + * @param val value to be AND'ed with this Signed. + * @return {@code this & val} + */ + Signed and(Signed val); + + /** + * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed if and only if + * either this or val is negative.) + * + * @param val value to be OR'ed with this Signed. + * @return {@code this | val} + */ + Signed or(Signed val); + + /** + * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed if and only if + * exactly one of this and val are negative.) + * + * @param val value to be XOR'ed with this Signed. + * @return {@code this ^ val} + */ + Signed xor(Signed val); + + /** + * Returns a Signed whose value is {@code (~this)}. (This method returns a negative value if and only if this Signed + * is non-negative.) + * + * @return {@code ~this} + */ + Signed not(); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this < val} + */ + boolean lessThan(Signed val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this <= val} + */ + boolean lessOrEqual(Signed val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this > val} + */ + boolean greaterThan(Signed val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this >= val} + */ + boolean greaterOrEqual(Signed val); + + + + /** + * Returns a Signed whose value is {@code (this + val)}. + * + * @param val value to be added to this Signed. + * @return {@code this + val} + */ + Signed add(int val); + + /** + * Returns a Signed whose value is {@code (this - val)}. + * + * @param val value to be subtracted from this Signed. + * @return {@code this - val} + */ + Signed subtract(int val); + + /** + * Returns a Signed whose value is {@code (this * val)}. + * + * @param val value to be multiplied by this Signed. + * @return {@code this * val} + */ + Signed multiply(int val); + + /** + * Returns a Signed whose value is {@code (this / val)}. + * + * @param val value by which this Signed is to be divided. + * @return {@code this / val} + */ + Signed signedDivide(int val); + + /** + * Returns a Signed whose value is {@code (this % val)}. + * + * @param val value by which this Signed is to be divided, and the remainder computed. + * @return {@code this % val} + */ + Signed signedRemainder(int val); + + /** + * Returns a Signed whose value is {@code (this << n)}. + * + * @param n shift distance, in bits. + * @return {@code this << n} + */ + Signed shiftLeft(int n); + + /** + * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed. + * + * @param n shift distance, in bits. + * @return {@code this >> n} + */ + Signed signedShiftRight(int n); + + /** + * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed if and only if this + * and val are both negative.) + * + * @param val value to be AND'ed with this Signed. + * @return {@code this & val} + */ + Signed and(int val); + + /** + * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed if and only if + * either this or val is negative.) + * + * @param val value to be OR'ed with this Signed. + * @return {@code this | val} + */ + Signed or(int val); + + /** + * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed if and only if + * exactly one of this and val are negative.) + * + * @param val value to be XOR'ed with this Signed. + * @return {@code this ^ val} + */ + Signed xor(int val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this < val} + */ + boolean lessThan(int val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this <= val} + */ + boolean lessOrEqual(int val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this > val} + */ + boolean greaterThan(int val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this >= val} + */ + boolean greaterOrEqual(int val); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,285 @@ +/* + * 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.graal.word; + +public interface Unsigned extends WordBase { + + /** + * Returns a Unsigned whose value is {@code (this + val)}. + * + * @param val value to be added to this Unsigned. + * @return {@code this + val} + */ + Unsigned add(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this - val)}. + * + * @param val value to be subtracted from this Unsigned. + * @return {@code this - val} + */ + Unsigned subtract(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this * val)}. + * + * @param val value to be multiplied by this Unsigned. + * @return {@code this * val} + */ + Unsigned multiply(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this / val)}. + * + * @param val value by which this Unsigned is to be divided. + * @return {@code this / val} + */ + Unsigned unsignedDivide(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this % val)}. + * + * @param val value by which this Unsigned is to be divided, and the remainder computed. + * @return {@code this % val} + */ + Unsigned unsignedRemainder(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this << n)}. + * + * @param n shift distance, in bits. + * @return {@code this << n} + */ + Unsigned shiftLeft(Unsigned n); + + /** + * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed. + * + * @param n shift distance, in bits. + * @return {@code this >> n} + */ + Unsigned unsignedShiftRight(Unsigned n); + + /** + * Returns a Unsigned whose value is {@code (this & val)}. + * + * @param val value to be AND'ed with this Unsigned. + * @return {@code this & val} + */ + Unsigned and(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this | val)}. + * + * @param val value to be OR'ed with this Unsigned. + * @return {@code this | val} + */ + Unsigned or(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this ^ val)}. + * + * @param val value to be XOR'ed with this Unsigned. + * @return {@code this ^ val} + */ + Unsigned xor(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (~this)}. + * + * @return {@code ~this} + */ + Unsigned not(); + + /** + * Compares this Unsigned with the specified value. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this < val} + */ + boolean belowThan(Unsigned val); + + /** + * Compares this Unsigned with the specified value. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this <= val} + */ + boolean belowOrEqual(Unsigned val); + + /** + * Compares this Unsigned with the specified value. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this > val} + */ + boolean aboveThan(Unsigned val); + + /** + * Compares this Unsigned with the specified value. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this >= val} + */ + boolean aboveOrEqual(Unsigned val); + + /** + * Returns a Unsigned whose value is {@code (this + val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to be added to this Unsigned. + * @return {@code this + val} + */ + Unsigned add(int val); + + /** + * Returns a Unsigned whose value is {@code (this - val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to be subtracted from this Unsigned. + * @return {@code this - val} + */ + Unsigned subtract(int val); + + /** + * Returns a Unsigned whose value is {@code (this * val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to be multiplied by this Unsigned. + * @return {@code this * val} + */ + Unsigned multiply(int val); + + /** + * Returns a Unsigned whose value is {@code (this / val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value by which this Unsigned is to be divided. + * @return {@code this / val} + */ + Unsigned unsignedDivide(int val); + + /** + * Returns a Unsigned whose value is {@code (this % val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value by which this Unsigned is to be divided, and the remainder computed. + * @return {@code this % val} + */ + Unsigned unsignedRemainder(int val); + + /** + * Returns a Unsigned whose value is {@code (this << n)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param n shift distance, in bits. + * @return {@code this << n} + */ + Unsigned shiftLeft(int n); + + /** + * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param n shift distance, in bits. + * @return {@code this >> n} + */ + Unsigned unsignedShiftRight(int n); + + /** + * Returns a Unsigned whose value is {@code (this & val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to be AND'ed with this Unsigned. + * @return {@code this & val} + */ + Unsigned and(int val); + + /** + * Returns a Unsigned whose value is {@code (this | val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to be OR'ed with this Unsigned. + * @return {@code this | val} + */ + Unsigned or(int val); + + /** + * Returns a Unsigned whose value is {@code (this ^ val)}.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to be XOR'ed with this Unsigned. + * @return {@code this ^ val} + */ + Unsigned xor(int val); + + /** + * Compares this Unsigned with the specified value.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this < val} + */ + boolean belowThan(int val); + + /** + * Compares this Unsigned with the specified value.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this <= val} + */ + boolean belowOrEqual(int val); + + /** + * Compares this Unsigned with the specified value.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this > val} + */ + boolean aboveThan(int val); + + /** + * Compares this Unsigned with the specified value.
+ * Note that the right operand is a signed value, while the operation is performed unsigned. Therefore, the result + * is only well-defined for positive right operands. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this >= val} + */ + boolean aboveOrEqual(int val); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,756 @@ +/* + * 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.graal.word; + +import static com.oracle.graal.graph.UnsafeAccess.*; + +import java.lang.annotation.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +public abstract class Word implements Signed, Unsigned, Pointer { + /** + * Links a method to a canonical operation represented by an {@link Opcode} val. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface Operation { + Class node() default ValueNode.class; + boolean rightOperandIsInt() default false; + Opcode opcode() default Opcode.NODE_CLASS; + Condition condition() default Condition.EQ; + } + + /** + * The canonical {@link Operation} represented by a method in the {@link Word} class. + */ + public enum Opcode { + NODE_CLASS, + COMPARISON, + NOT, + READ, + READ_FINAL, + WRITE, + ZERO, + FROM_UNSIGNED, + FROM_SIGNED, + FROM_OBJECT, + TO_OBJECT, + TO_RAW_VALUE, + } + + private static Word box(long val) { + return HostedWord.box(val); + } + + protected abstract long unbox(); + + private static Word intParam(int val) { + return box(val); + } + + + /** + * The constant 0, i.e., the word with no bits set. There is no difference between a signed and unsigned zero. + * @return the constant 0. + */ + @Operation(opcode = Opcode.ZERO) + public static Word zero() { + return box(0L); + } + + /** + * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned 64-bit value (in contrast to the semantics of a Java long). + * @param val a 64 bit unsigned value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_UNSIGNED) + public static Word unsigned(long val) { + return box(val); + } + + /** + * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned 32-bit value (in contrast to the semantics of a Java int). + * @param val a 32 bit unsigned value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_UNSIGNED) + public static Word unsigned(int val) { + return box(val & 0xffffffffL); + } + + /** + * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed 64-bit value (unchanged semantics of a Java long). + * @param val a 64 bit signed value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_SIGNED) + public static Word signed(long val) { + return box(val); + } + + /** + * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed 32-bit value (unchanged semantics of a Java int). + * @param val a 32 bit signed value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_SIGNED) + public static Word signed(int val) { + return box(val); + } + + @Override + @Operation(opcode = Opcode.TO_RAW_VALUE) + public long rawValue() { + return unbox(); + } + + @Operation(opcode = Opcode.FROM_OBJECT) + public static native Pointer fromObject(Object val); + + @Override + @Operation(opcode = Opcode.TO_OBJECT) + public native Object toObject(); + + + @Override + @Operation(node = IntegerAddNode.class) + public Word add(Signed val) { + return add((Word) val); + } + @Override + @Operation(node = IntegerAddNode.class) + public Word add(Unsigned val) { + return add((Word) val); + } + @Override + @Operation(node = IntegerAddNode.class) + public Word add(int val) { + return add(intParam(val)); + } + @Operation(node = IntegerAddNode.class) + public Word add(Word val) { + return box(unbox() + val.unbox()); + } + + @Override + @Operation(node = IntegerSubNode.class) + public Word subtract(Signed val) { + return subtract((Word) val); + } + @Override + @Operation(node = IntegerSubNode.class) + public Word subtract(Unsigned val) { + return subtract((Word) val); + } + @Override + @Operation(node = IntegerSubNode.class) + public Word subtract(int val) { + return subtract(intParam(val)); + } + @Operation(node = IntegerSubNode.class) + public Word subtract(Word val) { + return box(unbox() - val.unbox()); + } + + @Override + @Operation(node = IntegerMulNode.class) + public Word multiply(Signed val) { + return multiply((Word) val); + } + @Override + @Operation(node = IntegerMulNode.class) + public Word multiply(Unsigned val) { + return multiply((Word) val); + } + @Override + @Operation(node = IntegerMulNode.class) + public Word multiply(int val) { + return multiply(intParam(val)); + } + @Operation(node = IntegerMulNode.class) + public Word multiply(Word val) { + return box(unbox() * val.unbox()); + } + + @Override + @Operation(node = IntegerDivNode.class) + public Word signedDivide(Signed val) { + return signedDivide((Word) val); + } + @Override + @Operation(node = IntegerMulNode.class) + public Word signedDivide(int val) { + return signedDivide(intParam(val)); + } + @Operation(node = IntegerMulNode.class) + public Word signedDivide(Word val) { + return box(unbox() / val.unbox()); + } + + @Override + @Operation(node = UnsignedDivNode.class) + public Word unsignedDivide(Unsigned val) { + return unsignedDivide((Word) val); + } + @Override + @Operation(node = UnsignedDivNode.class) + public Word unsignedDivide(int val) { + return signedDivide(intParam(val)); + } + @Operation(node = UnsignedDivNode.class) + public Word unsignedDivide(Word val) { + return box(UnsignedMath.divide(unbox(), val.unbox())); + } + + @Override + @Operation(node = IntegerRemNode.class) + public Word signedRemainder(Signed val) { + return signedRemainder((Word) val); + } + @Override + @Operation(node = IntegerRemNode.class) + public Word signedRemainder(int val) { + return signedRemainder(intParam(val)); + } + @Operation(node = IntegerRemNode.class) + public Word signedRemainder(Word val) { + return box(unbox() % val.unbox()); + } + + @Override + @Operation(node = UnsignedRemNode.class) + public Word unsignedRemainder(Unsigned val) { + return unsignedRemainder((Word) val); + } + @Override + @Operation(node = UnsignedRemNode.class) + public Word unsignedRemainder(int val) { + return signedRemainder(intParam(val)); + } + @Operation(node = UnsignedRemNode.class) + public Word unsignedRemainder(Word val) { + return box(UnsignedMath.remainder(unbox(), val.unbox())); + } + + @Override + @Operation(node = LeftShiftNode.class, rightOperandIsInt = true) + public Word shiftLeft(Unsigned val) { + return shiftLeft((Word) val); + } + @Override + @Operation(node = LeftShiftNode.class, rightOperandIsInt = true) + public Word shiftLeft(int val) { + return shiftLeft(intParam(val)); + } + @Operation(node = LeftShiftNode.class, rightOperandIsInt = true) + public Word shiftLeft(Word val) { + return box(unbox() << val.unbox()); + } + + @Override + @Operation(node = RightShiftNode.class, rightOperandIsInt = true) + public Word signedShiftRight(Unsigned val) { + return signedShiftRight((Word) val); + } + @Override + @Operation(node = RightShiftNode.class, rightOperandIsInt = true) + public Word signedShiftRight(int val) { + return signedShiftRight(intParam(val)); + } + @Operation(node = RightShiftNode.class, rightOperandIsInt = true) + public Word signedShiftRight(Word val) { + return box(unbox() >> val.unbox()); + } + + @Override + @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true) + public Word unsignedShiftRight(Unsigned val) { + return unsignedShiftRight((Word) val); + } + @Override + @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true) + public Word unsignedShiftRight(int val) { + return unsignedShiftRight(intParam(val)); + } + @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true) + public Word unsignedShiftRight(Word val) { + return box(unbox() >>> val.unbox()); + } + + @Override + @Operation(node = AndNode.class) + public Word and(Signed val) { + return and((Word) val); + } + @Override + @Operation(node = AndNode.class) + public Word and(Unsigned val) { + return and((Word) val); + } + @Override + @Operation(node = AndNode.class) + public Word and(int val) { + return and(intParam(val)); + } + @Operation(node = AndNode.class) + public Word and(Word val) { + return box(unbox() & val.unbox()); + } + + @Override + @Operation(node = OrNode.class) + public Word or(Signed val) { + return or((Word) val); + } + @Override + @Operation(node = OrNode.class) + public Word or(Unsigned val) { + return or((Word) val); + } + @Override + @Operation(node = OrNode.class) + public Word or(int val) { + return or(intParam(val)); + } + @Operation(node = OrNode.class) + public Word or(Word val) { + return box(unbox() | val.unbox()); + } + + @Override + @Operation(node = XorNode.class) + public Word xor(Signed val) { + return xor((Word) val); + } + @Override + @Operation(node = XorNode.class) + public Word xor(Unsigned val) { + return xor((Word) val); + } + @Override + @Operation(node = XorNode.class) + public Word xor(int val) { + return xor(intParam(val)); + } + @Operation(node = XorNode.class) + public Word xor(Word val) { + return box(unbox() ^ val.unbox()); + } + + @Override + @Operation(opcode = Opcode.NOT) + public Word not() { + return box(~unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT) + public boolean lessThan(Signed val) { + return lessThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT) + public boolean lessThan(int val) { + return lessThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT) + public boolean lessThan(Word val) { + return unbox() < val.unbox(); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE) + public boolean lessOrEqual(Signed val) { + return lessOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE) + public boolean lessOrEqual(int val) { + return lessOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE) + public boolean lessOrEqual(Word val) { + return unbox() <= val.unbox(); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT) + public boolean greaterThan(Signed val) { + return greaterThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT) + public boolean greaterThan(int val) { + return greaterThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT) + public boolean greaterThan(Word val) { + return unbox() > val.unbox(); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE) + public boolean greaterOrEqual(Signed val) { + return greaterOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE) + public boolean greaterOrEqual(int val) { + return greaterOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE) + public boolean greaterOrEqual(Word val) { + return unbox() >= val.unbox(); + } + + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT) + public boolean belowThan(Unsigned val) { + return belowThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT) + public boolean belowThan(int val) { + return belowThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT) + public boolean belowThan(Word val) { + return UnsignedMath.belowThan(unbox(), val.unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE) + public boolean belowOrEqual(Unsigned val) { + return belowOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE) + public boolean belowOrEqual(int val) { + return belowOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE) + public boolean belowOrEqual(Word val) { + return UnsignedMath.belowOrEqual(unbox(), val.unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT) + public boolean aboveThan(Unsigned val) { + return aboveThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT) + public boolean aboveThan(int val) { + return aboveThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT) + public boolean aboveThan(Word val) { + return UnsignedMath.aboveThan(unbox(), val.unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE) + public boolean aboveOrEqual(Unsigned val) { + return aboveOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE) + public boolean aboveOrEqual(int val) { + return aboveOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE) + public boolean aboveOrEqual(Word val) { + return UnsignedMath.aboveOrEqual(unbox(), val.unbox()); + } + + + @Override + @Operation(opcode = Opcode.READ) + public byte readByte(WordBase offset) { + return unsafe.getByte(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public char readChar(WordBase offset) { + return unsafe.getChar(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public short readShort(WordBase offset) { + return unsafe.getShort(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public int readInt(WordBase offset) { + return unsafe.getInt(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public long readLong(WordBase offset) { + return unsafe.getLong(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public float readFloat(WordBase offset) { + return unsafe.getFloat(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public double readDouble(WordBase offset) { + return unsafe.getDouble(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public Word readWord(WordBase offset) { + return box(unsafe.getAddress(add((Word) offset).unbox())); + } + @Override + @Operation(opcode = Opcode.READ) + public native Object readObject(WordBase offset); + + @Override + @Operation(opcode = Opcode.READ) + public byte readByte(int offset) { + return readByte(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public char readChar(int offset) { + return readChar(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public short readShort(int offset) { + return readShort(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public int readInt(int offset) { + return readInt(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public long readLong(int offset) { + return readLong(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public float readFloat(int offset) { + return readFloat(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public double readDouble(int offset) { + return readDouble(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public Word readWord(int offset) { + return readWord(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public Object readObject(int offset) { + return readObject(signed(offset)); + } + + @Override + @Operation(opcode = Opcode.READ_FINAL) + public byte readFinalByte(WordBase offset) { + return readByte(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public char readFinalChar(WordBase offset) { + return readChar(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public short readFinalShort(WordBase offset) { + return readShort(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public int readFinalInt(WordBase offset) { + return readInt(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public long readFinalLong(WordBase offset) { + return readLong(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public float readFinalFloat(WordBase offset) { + return readFloat(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public double readFinalDouble(WordBase offset) { + return readDouble(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public Word readFinalWord(WordBase offset) { + return readWord(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public Object readFinalObject(WordBase offset) { + return readObject(offset); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeByte(WordBase offset, byte val) { + unsafe.putByte(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeChar(WordBase offset, char val) { + unsafe.putChar(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeShort(WordBase offset, Short val) { + unsafe.putShort(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeInt(WordBase offset, int val) { + unsafe.putInt(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeLong(WordBase offset, long val) { + unsafe.putLong(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeFloat(WordBase offset, float val) { + unsafe.putFloat(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeDouble(WordBase offset, double val) { + unsafe.putDouble(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeWord(WordBase offset, WordBase val) { + unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox()); + } + @Override + @Operation(opcode = Opcode.WRITE) + public native void writeObject(WordBase offset, Object val); + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeByte(int offset, byte val) { + writeByte(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeChar(int offset, char val) { + writeChar(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeShort(int offset, short val) { + writeShort(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeInt(int offset, int val) { + writeInt(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeLong(int offset, long val) { + writeLong(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeFloat(int offset, float val) { + writeFloat(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeDouble(int offset, double val) { + writeDouble(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeWord(int offset, WordBase val) { + writeWord(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeObject(int offset, Object val) { + writeObject(signed(offset), val); + } +} + +final class HostedWord extends Word { + private static final int SMALL_FROM = -1; + private static final int SMALL_TO = 100; + + private static final HostedWord[] smallCache = new HostedWord[SMALL_TO - SMALL_FROM + 1]; + private static final ConcurrentHashMap cache = new ConcurrentHashMap<>(); + + static { + for (int i = SMALL_FROM; i <= SMALL_TO; i++) { + smallCache[i - SMALL_FROM] = new HostedWord(i); + } + } + + private final long rawValue; + + private HostedWord(long rawValue) { + this.rawValue = rawValue; + } + + protected static Word box(long val) { + if (val >= SMALL_FROM && val <= SMALL_TO) { + return smallCache[(int) val - SMALL_FROM]; + } + Long key = val; + HostedWord result = cache.get(key); + if (result != null) { + return result; + } + HostedWord newValue = new HostedWord(val); + HostedWord oldValue = cache.putIfAbsent(key, newValue); + return oldValue == null ? newValue : oldValue; + } + + @Override + protected long unbox() { + return rawValue; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.word/src/com/oracle/graal/word/WordBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/WordBase.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,28 @@ +/* + * 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.graal.word; + +public interface WordBase { + + long rawValue(); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,317 @@ +/* + * 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.word.phases; + +import java.lang.reflect.*; + +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.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.Operation; + +/** + * Transforms all uses of the {@link Word} class into unsigned operations on {@code int} or {@code long} values, + * depending on the word kind of the underlying platform. + */ +public class WordTypeRewriterPhase extends Phase { + + private final ResolvedJavaType wordBaseType; + private final ResolvedJavaType wordImplType; + private final Kind wordKind; + + public WordTypeRewriterPhase(MetaAccessProvider metaAccess, Kind wordKind) { + this.wordKind = wordKind; + this.wordBaseType = metaAccess.lookupJavaType(WordBase.class); + this.wordImplType = metaAccess.lookupJavaType(Word.class); + } + + public ResolvedJavaType getWordBaseType() { + return wordBaseType; + } + + public ResolvedJavaType getWordImplType() { + return wordImplType; + } + + @Override + protected void run(StructuredGraph graph) { + for (Node n : GraphOrder.forwardGraph(graph)) { + if (n instanceof ValueNode) { + ValueNode valueNode = (ValueNode) n; + if (isWord(valueNode)) { + changeToWord(valueNode); + } + } + } + + // Remove casts between different word types (which are by now no longer have kind Object) + for (CheckCastNode checkCastNode : graph.getNodes().filter(CheckCastNode.class).snapshot()) { + if (!checkCastNode.isDeleted() && checkCastNode.kind() == wordKind) { + checkCastNode.replaceAtUsages(checkCastNode.object()); + graph.removeFixed(checkCastNode); + } + } + + // Remove unnecessary/redundant unsafe casts + for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) { + if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) { + graph.replaceFloating(unsafeCastNode, unsafeCastNode.object()); + } + } + + // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words + for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { + ValueNode x = objectEqualsNode.x(); + ValueNode y = objectEqualsNode.y(); + if (x.kind() == wordKind || y.kind() == wordKind) { + assert x.kind() == wordKind; + assert y.kind() == wordKind; + graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y))); + } + } + + // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words + for (LoadIndexedNode load : graph.getNodes().filter(LoadIndexedNode.class).snapshot()) { + if (isWord(load)) { + load.setStamp(StampFactory.forKind(wordKind)); + } + } + + for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { + ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); + if (!callTargetNode.isStatic() && (callTargetNode.receiver().kind() == wordKind || isWord(callTargetNode.receiver()))) { + targetMethod = getWordImplType().resolveMethod(targetMethod); + } + Operation operation = targetMethod.getAnnotation(Word.Operation.class); + if (operation != null) { + NodeInputList arguments = callTargetNode.arguments(); + Invoke invoke = (Invoke) callTargetNode.usages().first(); + assert invoke != null : callTargetNode.targetMethod(); + + switch (operation.opcode()) { + case NODE_CLASS: + assert arguments.size() == 2; + ValueNode left = arguments.get(0); + ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1)); + replace(invoke, nodeClassOp(graph, operation.node(), left, right)); + break; + + case COMPARISON: + assert arguments.size() == 2; + replace(invoke, comparisonOp(graph, operation.condition(), arguments.get(0), fromSigned(graph, arguments.get(1)))); + break; + + case NOT: + assert arguments.size() == 1; + replace(invoke, graph.unique(new XorNode(wordKind, arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); + break; + + case READ: + assert arguments.size() == 2; + replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.ANY_LOCATION)); + break; + + case READ_FINAL: + assert arguments.size() == 2; + replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.FINAL_LOCATION)); + break; + + case WRITE: + assert arguments.size() == 3; + replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, LocationNode.ANY_LOCATION)); + break; + + case ZERO: + assert arguments.size() == 0; + replace(invoke, ConstantNode.forIntegerKind(wordKind, 0L, graph)); + break; + + case FROM_UNSIGNED: + assert arguments.size() == 1; + replace(invoke, fromUnsigned(graph, arguments.get(0))); + break; + + case FROM_SIGNED: + assert arguments.size() == 1; + replace(invoke, fromSigned(graph, arguments.get(0))); + break; + + case TO_RAW_VALUE: + assert arguments.size() == 1; + replace(invoke, toUnsigned(graph, arguments.get(0), Kind.Long)); + break; + + case FROM_OBJECT: + assert arguments.size() == 1; + replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), StampFactory.forKind(wordKind)))); + break; + + case TO_OBJECT: + assert arguments.size() == 1; + replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.node().stamp()))); + break; + + default: + throw new GraalInternalError("Unknown opcode: %s", operation.opcode()); + } + } + } + } + + private ValueNode fromUnsigned(StructuredGraph graph, ValueNode value) { + return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); + } + + private ValueNode fromSigned(StructuredGraph graph, ValueNode value) { + return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.I2L); + } + + private static ValueNode toUnsigned(StructuredGraph graph, ValueNode value, Kind toKind) { + return convert(graph, value, toKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); + } + + private static ValueNode convert(StructuredGraph graph, ValueNode value, Kind toKind, ConvertNode.Op longToIntOp, ConvertNode.Op intToLongOp) { + assert longToIntOp.from == Kind.Long && longToIntOp.to == Kind.Int; + assert intToLongOp.from == Kind.Int && intToLongOp.to == Kind.Long; + if (value.kind() == toKind) { + return value; + } + + if (toKind == Kind.Int) { + assert value.kind() == Kind.Long; + return graph.unique(new ConvertNode(longToIntOp, value)); + } else { + assert toKind == Kind.Long; + assert value.kind().getStackKind() == Kind.Int; + return graph.unique(new ConvertNode(intToLongOp, value)); + } + } + + private ValueNode nodeClassOp(StructuredGraph graph, Class nodeClass, ValueNode left, ValueNode right) { + try { + Constructor< ? extends ValueNode> constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class); + return graph.add(constructor.newInstance(wordKind, left, right)); + } catch (Throwable ex) { + throw new GraalInternalError(ex).addContext(nodeClass.getName()); + } + } + + private ValueNode comparisonOp(StructuredGraph graph, Condition condition, ValueNode left, ValueNode right) { + assert left.kind() == wordKind && right.kind() == wordKind; + + // mirroring gets the condition into canonical form + boolean mirror = condition.canonicalMirror(); + + ValueNode a = mirror ? right : left; + ValueNode b = mirror ? left : right; + + + CompareNode comparison; + if (condition == Condition.EQ || condition == Condition.NE) { + comparison = new IntegerEqualsNode(a, b); + } else if (condition.isUnsigned()) { + comparison = new IntegerBelowThanNode(a, b); + } else { + comparison = new IntegerLessThanNode(a, b); + } + MaterializeNode materialize = MaterializeNode.create(graph.unique(comparison)); + + ValueNode op; + if (condition.canonicalNegate()) { + op = (ValueNode) materialize.negate(); + } else { + op = materialize; + } + return op; + } + + private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Object locationIdentity) { + IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, offset, graph, false); + ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp())); + graph.addBeforeFixed(invoke.node(), read); + // The read must not float outside its block otherwise it may float above an explicit zero check on its base address + read.dependencies().add(BeginNode.prevBegin(invoke.node())); + return read; + } + + private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Object locationIdentity) { + IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, value.kind(), 0, offset, graph, false); + WriteNode write = graph.add(new WriteNode(base, value, location)); + graph.addBeforeFixed(invoke.node(), write); + return write; + } + + private static void replace(Invoke invoke, ValueNode value) { + FixedNode next = invoke.next(); + invoke.setNext(null); + invoke.node().replaceAtPredecessor(next); + invoke.node().replaceAtUsages(value); + GraphUtil.killCFG(invoke.node()); + } + + public boolean isWord(ValueNode node) { + node.inferStamp(); + if (node.stamp() == StampFactory.forWord()) { + return true; + } + if (node instanceof LoadIndexedNode) { + ValueNode array = ((LoadIndexedNode) node).array(); + if (array.objectStamp().type() == null) { + // There are cases where the array does not have a known type yet. Assume it is not a word type. + // TODO disallow LoadIndexedNode for word arrays? + return false; + } + return isWord(array.objectStamp().type().getComponentType()); + } + if (node.kind() == Kind.Object) { + return isWord(node.objectStamp().type()); + } + return false; + } + + public boolean isWord(ResolvedJavaType type) { + if (type != null && wordBaseType.isAssignableFrom(type)) { + return true; + } + return false; + } + + private void changeToWord(ValueNode valueNode) { + if (valueNode.isConstant() && valueNode.asConstant().getKind() == Kind.Object) { + WordBase value = (WordBase) valueNode.asConstant().asObject(); + ConstantNode newConstant = ConstantNode.forIntegerKind(wordKind, value.rawValue(), valueNode.graph()); + ((StructuredGraph) valueNode.graph()).replaceFloating((ConstantNode) valueNode, newConstant); + } else { + assert !(valueNode instanceof ConstantNode) : "boxed Word constants should not appear in a snippet graph: " + valueNode + ", stamp: " + valueNode.stamp(); + valueNode.setStamp(StampFactory.forKind(wordKind)); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2011, 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.word.phases; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.Operation; + +/** + * Verifies invariants that must hold for snippet code above and beyond normal + * bytecode verification. + */ +public class WordTypeVerificationPhase extends Phase { + + private final WordTypeRewriterPhase wordAccess; + + public WordTypeVerificationPhase(MetaAccessProvider metaAccess, Kind wordKind) { + this.wordAccess = new WordTypeRewriterPhase(metaAccess, wordKind); + } + + @Override + protected void run(StructuredGraph graph) { + for (ValueNode node : graph.getNodes().filter(ValueNode.class)) { + for (Node usage : node.usages()) { + if (usage instanceof AccessMonitorNode) { + verify(!isWord(node), node, usage, "word value has no monitor"); + } else if (usage instanceof LoadFieldNode) { + verify(!isWord(node) || ((LoadFieldNode) usage).object() != node, node, usage, "cannot load from word value"); + } else if (usage instanceof StoreFieldNode) { + verify(!isWord(node) || ((StoreFieldNode) usage).object() != node, node, usage, "cannot store to word value"); + } else if (usage instanceof CheckCastNode) { + boolean expectWord = isWord(node); + verify(isWord(node) == expectWord, node, usage, "word cannot be cast to object, and vice versa"); + verify(isWord(((CheckCastNode) usage).type()) == expectWord, node, usage, "word cannot be cast to object, and vice versa"); + } else if (usage instanceof LoadIndexedNode) { + verify(!isWord(node) || ((LoadIndexedNode) usage).array() != node, node, usage, "cannot load from word value"); + verify(!isWord(node) || ((LoadIndexedNode) usage).index() != node, node, usage, "cannot use word value as index"); + } else if (usage instanceof StoreIndexedNode) { + verify(!isWord(node) || ((StoreIndexedNode) usage).array() != node, node, usage, "cannot store to word value"); + verify(!isWord(node) || ((StoreIndexedNode) usage).index() != node, node, usage, "cannot use word value as index"); + verify(!isWord(node) || ((StoreIndexedNode) usage).value() != node, node, usage, "cannot store word value to array"); + } else if (usage instanceof MethodCallTargetNode) { + MethodCallTargetNode callTarget = (MethodCallTargetNode) usage; + ResolvedJavaMethod method = callTarget.targetMethod(); + if (method.getAnnotation(NodeIntrinsic.class) == null) { + Invoke invoke = (Invoke) callTarget.usages().first(); + NodeInputList arguments = callTarget.arguments(); + boolean isStatic = Modifier.isStatic(method.getModifiers()); + int argc = 0; + if (!isStatic) { + ValueNode receiver = arguments.get(argc); + if (receiver == node && isWord(node)) { + ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveMethod(method); + verify(resolvedMethod != null, node, invoke.node(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); + Operation operation = resolvedMethod.getAnnotation(Word.Operation.class); + verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); + } + argc++; + } + Signature signature = method.getSignature(); + for (int i = 0; i < signature.getParameterCount(false); i++) { + ValueNode argument = arguments.get(argc); + if (argument == node) { + ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); + verify(isWord(type) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); + } + argc++; + } + } + } else if (usage instanceof ObjectEqualsNode) { + ObjectEqualsNode compare = (ObjectEqualsNode) usage; + if (compare.x() == node || compare.y() == node) { + verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and non-word type in use of '==' or '!='"); + } + } else if (usage instanceof ArrayLengthNode) { + verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value"); + } else if (usage instanceof PhiNode) { + if (!(node instanceof MergeNode)) { + PhiNode phi = (PhiNode) usage; + for (ValueNode input : phi.values()) { + verify(isWord(node) == isWord(input), node, input, "cannot merge word and non-word values"); + } + } + } + } + } + } + + private boolean isWord(ValueNode node) { + return wordAccess.isWord(node); + } + + private boolean isWord(ResolvedJavaType type) { + return wordAccess.isWord(type); + } + + private static void verify(boolean condition, Node node, Node usage, String message) { + if (!condition) { + error(node, usage, message); + } + } + + private static void error(Node node, Node usage, String message) { + throw new GraalInternalError(String.format("Snippet verification error: %s" + + "%n node: %s (%s)" + + "%n usage: %s (%s)", message, node, sourceLocation(node), usage, sourceLocation(usage))); + } + + private static String sourceLocation(Node n) { + if (n instanceof PhiNode) { + StringBuilder buf = new StringBuilder(); + for (Node usage : n.usages()) { + String loc = sourceLocation(usage); + if (!loc.equals("")) { + if (buf.length() != 0) { + buf.append(", "); + } + buf.append(loc); + } + } + return buf.toString(); + } else { + String loc = GraphUtil.approxSourceLocation(n); + return loc == null ? "" : loc; + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ExtensionAnnotation.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,34 @@ +/* + * 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.ANNOTATION_TYPE}) +public @interface ExtensionAnnotation { + + String processorClassName(); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GeneratedBy.java Mon Jan 07 13:04:04 2013 +0100 @@ -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.*; + +/** + * Marks a type to be generated by another class. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface GeneratedBy { + + Class< ? > value(); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +/** + * + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface Generic { +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/GuardCheck.java Mon Jan 07 13:04:04 2013 +0100 @@ -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.*; + +/** + * + * + * @see SpecializationGuard + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface GuardCheck { + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Operation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Operation.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; +import com.oracle.truffle.api.nodes.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface Operation { + + Class< ? > typeSystem(); + + Class baseClass() default Node.class; + + String[] values() default {}; + + String[] shortCircuitValues() default {}; + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ShortCircuit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/ShortCircuit.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface ShortCircuit { + + String value(); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface Specialization { + + int DEFAULT_ORDER = -1; + + int order() default DEFAULT_ORDER; + + SpecializationThrows[] exceptions() default {}; + + SpecializationGuard[] guards() default {}; + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationGuard.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +/** + * Specifies the use of a guard for a specialization. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface SpecializationGuard { + + /** + * Specifies the name of the guard method annotated by {@link GuardCheck} specified as method in the + * {@link TypeSystem} or {@link Operation} class. + */ + String methodName(); + + /** + * Determines if a guard check is invoked on specialization. Defaults to true. + */ + boolean onSpecialization() default true; + + /** + * Determines if a guard check is invoked on execution. Defaults to true. + */ + boolean onExecution() default true; + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationListener.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface SpecializationListener { +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/SpecializationThrows.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface SpecializationThrows { + + Class< ? extends Throwable> javaClass(); + + String transitionTo(); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCast.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + + +/** + * + * + * + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface TypeCast { + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCheck.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeCheck.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,79 @@ +/* + * 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.*; + +/** + *

+ * Provides a way to define a custom type check for a defined type. The name of the annotated method must fit to the + * pattern is${typeName} (eg. isInteger), where ${typeName} must be a valid type defined in the parent + * {@link TypeSystem}. The annotated method must have exactly one argument where the type of the argument is the generic + * type {@link Object} or a more specific one from the {@link TypeSystem}. You can define multiple overloaded + * {@link TypeCheck} methods for the same type. This can be used to reduce the boxing overhead in type conversions. + *

+ * + *

+ * By default the system generates type checks for all types in the parent {@link TypeSystem} which look like the + * follows: + * + *

+ * @TypeCheck
+ * boolean is${typeName}(Object value) {
+ *         return value instanceof ${typeName};
+ * }
+ * 
+ * + *

+ * + * Example: + *

+ * A type check for BigInteger with one overloaded optimized variant to reduce boxing. + *

+ * + *
+ *
+ *
+ * @TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
+ * public abstract class Types {
+ *
+ *     @TypeCheck
+ *     public boolean isBigInteger(Object value) {
+ *         return value instanceof Integer || value instanceof BigInteger;
+ *     }
+ *
+ *     @TypeCheck
+ *     public boolean isBigInteger(int value) {
+ *         return true;
+ *     }
+ *
+ * }
+ * 
+ * + * + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface TypeCheck { + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/TypeSystem.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.codegen; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.nodes.*; + +/** + *

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

+ * + * + * Example: + *

+ * Shows a @TypeSystem definition with three types. In this example BigIntegers can be also treated as + * integers if their bit width is less than 32. + *

+ * + *
+ *
+ * @TypeSystem(types = {int.class, BigInteger.class, String.class}, nodeBaseClass = TypedNode.class)
+ * public abstract class Types {
+ *
+ *     @TypeCheck
+ *     public boolean isInteger(Object value) {
+ *         return value instanceof Integer || (value instanceof BigInteger && ((BigInteger) value).bitLength() < Integer.SIZE);
+ *     }
+ *
+ *     @TypeCast
+ *     public int asInteger(Object value) {
+ *         if (value instanceof Integer) {
+ *             return (int) value;
+ *         } else {
+ *             return ((BigInteger) value).intValue();
+ *         }
+ *     }
+ * }
+ * 
+ * + * @see TypeCast + * @see TypeCheck + * @see GuardCheck + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.TYPE}) +public @interface TypeSystem { + + /** + * Sets the types contained by this type system. The order of types also determines the order of specialization. + */ + Class[] types(); + + /** + * Specifies whether the node base class has an executeVoid method or not. Operations derived from this type system + * will automatically implement executeVoid for all generated nodes. Defaults to false. + */ + boolean hasVoid() default false; + + /** + * Specifies the node base class used for generated code that uses this type system. The node base class must extend + * {@link Node} and provide a public non-final method ${type} execute${typeName}(VirtualFrame) for all + * types specified in the types attribute. + */ + Class< ? extends Node> nodeBaseClass(); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,1 @@ +com.oracle.truffle.codegen.processor.TruffleProcessor \ No newline at end of file diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AbstractParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,66 @@ +/* + * 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; + +import java.lang.annotation.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.template.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public abstract class AbstractParser { + + protected final ProcessorContext context; + protected final ProcessingEnvironment processingEnv; + protected RoundEnvironment roundEnv; + + protected final Log log; + + public AbstractParser(ProcessorContext c) { + this.context = c; + this.processingEnv = c.getEnvironment(); + this.log = c.getLog(); + } + + public final M parse(RoundEnvironment env, Element element) { + this.roundEnv = env; + try { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType()); + if (!context.getTruffleTypes().verify(context, element, mirror)) { + return null; + } + return parse(element, mirror); + } finally { + this.roundEnv = null; + } + } + + protected abstract M parse(Element element, AnnotationMirror mirror); + + public abstract Class< ? extends Annotation> getAnnotationType(); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/AnnotationProcessor.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,132 @@ +/* + * 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; + +import java.io.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.tools.*; + +import com.oracle.truffle.codegen.processor.ast.*; +import com.oracle.truffle.codegen.processor.codewriter.*; +import com.oracle.truffle.codegen.processor.compiler.*; +import com.oracle.truffle.codegen.processor.template.*; + +/** + * THIS IS NOT PUBLIC API. + */ +class AnnotationProcessor { + + private final AbstractParser parser; + private final CompilationUnitFactory factory; + private final ProcessorContext context; + + private final Set processedElements = new HashSet<>(); + + public AnnotationProcessor(ProcessorContext context, AbstractParser parser, CompilationUnitFactory factory) { + this.context = context; + this.parser = parser; + this.factory = factory; + } + + public AbstractParser getParser() { + return parser; + } + + public ProcessorContext getContext() { + return context; + } + + @SuppressWarnings({"unchecked"}) + public void process(RoundEnvironment env, Element element, boolean callback) { + + // since it is not guaranteed to be called only once by the compiler + // we check for already processed elements to avoid errors when writing files. + if (!callback && element instanceof TypeElement) { + String qualifiedName = Utils.getQualifiedName((TypeElement) element); + if (processedElements.contains(qualifiedName)) { + return; + } + processedElements.add(qualifiedName); + } + + TypeElement type = (TypeElement) element; + + M model = (M) context.getTemplate(type.asType(), false); + boolean firstRun = !context.containsTemplate(type); + + if (firstRun || !callback) { + context.registerTemplate(type, null); + model = parser.parse(env, element); + context.registerTemplate(type, model); + + if (model != null) { + CodeCompilationUnit unit = (CodeCompilationUnit) factory.process(model); + unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation()); + unit.setGeneratorElement(model.getTemplateType()); + + DeclaredType overrideType = (DeclaredType) context.getType(Override.class); + DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class); + unit.accept(new GenerateOverrideVisitor(overrideType), null); + unit.accept(new FixWarningsVisitor(context, unusedType, overrideType), null); + + if (!callback) { + unit.accept(new CodeWriter(context.getEnvironment(), element), null); + } + } + } + } + + private static class CodeWriter extends AbstractCodeWriter { + + private final Element orignalElement; + private final ProcessingEnvironment env; + + public CodeWriter(ProcessingEnvironment env, Element originalElement) { + this.env = env; + this.orignalElement = originalElement; + } + + @Override + protected Writer createWriter(CodeTypeElement clazz) throws IOException { + JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), orignalElement); + return jfo.openWriter(); + } + + @Override + protected void writeHeader() { + if (env == null) { + return; + } + String comment = CompilerFactory.getCompiler(orignalElement).getHeaderComment(env, orignalElement); + if (comment != null) { + writeLn(comment); + } + } + + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,79 @@ +/* + * 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; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic.Kind; + +import com.oracle.truffle.codegen.processor.ast.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public class Log { + + private final ProcessingEnvironment processingEnv; + + public Log(ProcessingEnvironment env) { + this.processingEnv = env; + } + + public void warning(Element element, String format, Object ... args) { + message(Kind.WARNING, element, null, null, format, args); + } + + public void warning(Element element, AnnotationMirror mirror, String format, Object ... args) { + message(Kind.WARNING, element, mirror, null, format, args); + } + + public void error(Element element, String format, Object... args) { + message(Kind.ERROR, element, null, null, format, args); + } + + public void error(Element element, AnnotationMirror mirror, String format, Object... args) { + message(Kind.ERROR, element, mirror, null, format, args); + } + + public void error(Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { + message(Kind.ERROR, element, mirror, value, format, args); + } + + public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) { + AnnotationMirror usedMirror = mirror; + Element usedElement = element; + AnnotationValue usedValue = value; + String message = String.format(format, args); + + if (element instanceof GeneratedElement) { + usedMirror = ((GeneratedElement) element).getGeneratorAnnotationMirror(); + usedElement = ((GeneratedElement) element).getGeneratorElement(); + usedValue = null; + if (usedElement != null) { + message = String.format("Element %s: %s", element, message); + } + } + processingEnv.getMessager().printMessage(kind, message, usedElement, usedMirror, usedValue); + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ProcessorContext.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,190 @@ +/* + * 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; + +import static com.oracle.truffle.codegen.processor.Utils.*; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.ArrayCodeTypeMirror; +import com.oracle.truffle.codegen.processor.template.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public class ProcessorContext { + + private final ProcessingEnvironment environment; + + private final Map models = new HashMap<>(); + private final Map> generatedClasses = new HashMap<>(); + + private final ProcessCallback callback; + private final Log log; + private TruffleTypes truffleTypes; + + public ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) { + this.environment = env; + this.callback = callback; + this.log = new Log(environment); + } + + public TruffleTypes getTruffleTypes() { + if (truffleTypes == null) { + truffleTypes = new TruffleTypes(this); + } + return truffleTypes; + } + + public Log getLog() { + return log; + } + + public ProcessingEnvironment getEnvironment() { + return environment; + } + + public boolean containsTemplate(TypeElement element) { + return models.containsKey(Utils.getQualifiedName(element)); + } + + public void registerTemplate(TypeElement element, Template model) { + models.put(Utils.getQualifiedName(element), model); + } + + public void registerType(TypeElement templateType, TypeMirror generatedTypeMirror) { + String templateQualifiedName = getQualifiedName(templateType); + Map simpleNameToType = generatedClasses.get(templateQualifiedName); + if (simpleNameToType == null) { + simpleNameToType = new HashMap<>(); + generatedClasses.put(templateQualifiedName, simpleNameToType); + } + String generatedSimpleName = getSimpleName(generatedTypeMirror); + simpleNameToType.put(generatedSimpleName, generatedTypeMirror); + } + + public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) { + String qualifiedName = Utils.getQualifiedName(templateTypeMirror); + Template model = models.get(qualifiedName); + if (model == null && invokeCallback) { + callback.callback(Utils.fromTypeMirror(templateTypeMirror)); + model = models.get(qualifiedName); + } + return model; + } + + public TypeMirror resolveNotYetCompiledType(TypeMirror mirror, Template templateHint) { + TypeMirror resolvedType = null; + if (mirror.getKind() == TypeKind.ARRAY) { + TypeMirror originalComponentType = ((ArrayType) mirror).getComponentType(); + TypeMirror resolvedComponent = resolveNotYetCompiledType(originalComponentType, templateHint); + if (resolvedComponent != originalComponentType) { + return new ArrayCodeTypeMirror(resolvedComponent); + } + } + + if (mirror.getKind() == TypeKind.ERROR) { + Element element = ((ErrorType) mirror).asElement(); + ElementKind kind = element.getKind(); + if (kind == ElementKind.CLASS || kind == ElementKind.PARAMETER || kind == ElementKind.ENUM) { + String simpleName = element.getSimpleName().toString(); + resolvedType = findGeneratedClassBySimpleName(simpleName, templateHint); + } + } else { + resolvedType = mirror; + } + + return resolvedType; + } + + public TypeMirror findGeneratedClassBySimpleName(String simpleName, Template templateHint) { + if (templateHint == null) { + // search all + for (String qualifiedTemplateName : generatedClasses.keySet()) { + Map mirrors = generatedClasses.get(qualifiedTemplateName); + if (mirrors.get(simpleName) != null) { + return mirrors.get(simpleName); + } + } + return null; + } else { + String templateQualifiedName = getQualifiedName(templateHint.getTemplateType()); + Map simpleNameToType = generatedClasses.get(templateQualifiedName); + if (simpleNameToType == null) { + return null; + } + return simpleNameToType.get(simpleName); + } + } + + public TypeMirror getType(String className) { + TypeElement element = environment.getElementUtils().getTypeElement(className); + if (element != null) { + return element.asType(); + } + return null; + } + + public TypeMirror getType(Class< ? > element) { + TypeMirror mirror; + if (element.isPrimitive()) { + if (element == boolean.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BOOLEAN); + } else if (element == byte.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.BYTE); + } else if (element == short.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.SHORT); + } else if (element == char.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.CHAR); + } else if (element == int.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.INT); + } else if (element == long.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.LONG); + } else if (element == float.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.FLOAT); + } else if (element == double.class) { + mirror = environment.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE); + } else if (element == void.class) { + mirror = environment.getTypeUtils().getNoType(TypeKind.VOID); + } else { + assert false; + return null; + } + } else { + TypeElement typeElement = environment.getElementUtils().getTypeElement(element.getCanonicalName()); + mirror = typeElement.asType(); + } + return mirror; + } + + public interface ProcessCallback { + + void callback(TypeElement template); + + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleProcessor.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,126 @@ +/* + * 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; + +import java.lang.annotation.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.ProcessorContext.ProcessCallback; +import com.oracle.truffle.codegen.processor.operation.*; +import com.oracle.truffle.codegen.processor.typesystem.*; + +/** + * THIS IS NOT PUBLIC API. + */ +//@SupportedAnnotationTypes({"com.oracle.truffle.codegen.Operation", "com.oracle.truffle.codegen.TypeLattice"}) +@SupportedSourceVersion(SourceVersion.RELEASE_7) +public class TruffleProcessor extends AbstractProcessor implements ProcessCallback { + + private ProcessorContext context; + private List> generators; + + private RoundEnvironment round; + + @Override + public boolean process(Set< ? extends TypeElement> annotations, RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + processImpl(roundEnv); + } + return false; + } + + @SuppressWarnings("unchecked") + private void processImpl(RoundEnvironment env) { + this.round = env; + // TODO run verifications that other annotations are not processed out of scope of the operation or typelattice. + try { + for (AnnotationProcessor generator : getGenerators()) { + for (Element e : env.getElementsAnnotatedWith(generator.getParser().getAnnotationType())) { + processElement(env, generator, e, false); + } + } + } finally { + this.round = null; + } + } + + private static void processElement(RoundEnvironment env, AnnotationProcessor generator, Element e, boolean callback) { + try { + generator.process(env, e, callback); + } catch (Throwable e1) { + handleThrowable(generator, e1, e); + } + } + + private static void handleThrowable(AnnotationProcessor generator, Throwable t, Element e) { + String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e; + generator.getContext().getLog().error(e, message + ": " + Utils.printException(t)); + } + + @SuppressWarnings("unchecked") + @Override + public void callback(TypeElement template) { + for (AnnotationProcessor generator : generators) { + Annotation annotation = template.getAnnotation(generator.getParser().getAnnotationType()); + if (annotation != null) { + processElement(round, generator, template, true); + } + } + } + + @Override + public Set getSupportedAnnotationTypes() { + Set annotations = new HashSet<>(); + for (AnnotationProcessor< ? > generator : getGenerators()) { + annotations.add(generator.getParser().getAnnotationType().getCanonicalName()); + } + return annotations; + } + + private List> getGenerators() { + if (generators == null && processingEnv != null) { + generators = new ArrayList<>(); + generators.add(new AnnotationProcessor<>(getContext(), new TypeSystemParser(getContext()), new TypeSystemCodeGenerator(getContext()))); + generators.add(new AnnotationProcessor<>(getContext(), new OperationParser(getContext()), new OperationCodeGenerator(getContext()))); + } + return generators; + } + + private ProcessorContext getContext() { + if (context == null) { + context = new ProcessorContext(processingEnv, this); + } + return context; + } + + @Override + public synchronized void init(ProcessingEnvironment env) { + this.processingEnv = env; + super.init(env); + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,107 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.Node.Child; +import com.oracle.truffle.api.nodes.Node.Children; + +/** + * THIS IS NOT PUBLIC API. + */ +public final class TruffleTypes { + + private final TypeMirror node; + private final TypeMirror nodeArray; + private final TypeMirror unexpectedValueException; + private final TypeMirror frame; + private final TypeMirror stableAnnotation; + private final TypeMirror contentStableAnnotation; + private final TypeMirror typeConversion; + + private final List errors = new ArrayList<>(); + + public TruffleTypes(ProcessorContext context) { + node = getRequired(context, Node.class); + 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); + typeConversion = getRequired(context, TypeConversion.class); + } + + public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) { + if (errors.isEmpty()) { + return true; + } + + for (String error : errors) { + context.getLog().error(element, mirror, error); + } + + return false; + } + + private TypeMirror 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; + } + + public TypeMirror getTypeConversion() { + return typeConversion; + } + + public TypeMirror getNode() { + return node; + } + + public TypeMirror getNodeArray() { + return nodeArray; + } + + public TypeMirror getFrame() { + return frame; + } + + public TypeMirror getUnexpectedValueException() { + return unexpectedValueException; + } + + public TypeMirror getStableAnnotation() { + return stableAnnotation; + } + + public TypeMirror getContentStableAnnotation() { + return contentStableAnnotation; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,551 @@ +/* + * 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; + +import java.io.*; +import java.lang.annotation.*; +import java.util.*; + +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.compiler.*; + +/** + * THIS IS NOT PUBLIC API. + */ +public class Utils { + + public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + if (method instanceof CodeExecutableElement) { + return ((CodeExecutableElement) method).getBody(); + } else { + return CompilerFactory.getCompiler(method).getMethodBody(env, method); + } + } + + public static List collectAnnotations( + ProcessorContext context, + AnnotationMirror markerAnnotation, String elementName, Element element, + Class< ? extends Annotation> annotationClass) { + List result = Utils.getAnnotationValueList(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; + } + + public static boolean hasError(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case SHORT: + case LONG: + case DECLARED: + case VOID: + case TYPEVAR: + return false; + case ARRAY: + return hasError(((ArrayType) mirror).getComponentType()); + case ERROR: + return true; + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + /** + * True if t1 is assignable to t2. + */ + public static boolean isAssignable(TypeMirror t1, TypeMirror t2) { + if (typeEquals(t1, t2)) { + return true; + } + if (isPrimitive(t1) || isPrimitive(t2)) { + // non-equal primitive types + 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) { + return false; + } + + List superTypes = getSuperTypes(e1); + for (TypeElement superType : superTypes) { + if (typeEquals(superType.asType(), t2)) { + return true; + } + } + return false; + } + + public static Set modifiers(Modifier... modifier) { + return new LinkedHashSet<>(Arrays.asList(modifier)); + } + + public static String getSimpleName(TypeElement element) { + return getSimpleName(element.asType()); + } + + public static String getSimpleName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case CHAR: + return "char"; + case DOUBLE: + return "double"; + case FLOAT: + return "float"; + case SHORT: + return "short"; + case INT: + return "int"; + case LONG: + return "long"; + case DECLARED: + return getGenericName(fromTypeMirror(mirror)); + case ARRAY: + return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]"; + case VOID: + return "void"; + case TYPEVAR: + return ((TypeParameterElement) ((TypeVariable) mirror).asElement()).getSimpleName().toString(); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); + } + } + + + private static String getGenericName(TypeElement element) { + String simpleName = element.getSimpleName().toString(); + + if (element.getTypeParameters().size() == 0) { + return simpleName; + } + + StringBuilder b = new StringBuilder(simpleName); + b.append("<"); + if (element.getTypeParameters().size() > 0) { + for (int i = 0; i < element.getTypeParameters().size(); i++) { + b.append("?"); + if (i < element.getTypeParameters().size() - 1) { + b.append(", "); + } + } + } + b.append(">"); + return b.toString(); + } + + public static String getQualifiedName(TypeElement element) { + return element.getQualifiedName().toString(); + } + + public static String getQualifiedName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case CHAR: + return "char"; + case DOUBLE: + return "double"; + case SHORT: + return "short"; + case FLOAT: + return "float"; + case INT: + return "int"; + case LONG: + return "long"; + case DECLARED: + return getQualifiedName(fromTypeMirror(mirror)); + case ARRAY: + return getQualifiedName(((ArrayType) mirror).getComponentType()); + case VOID: + return "void"; + case TYPEVAR: + return getSimpleName(mirror); + default: + throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror); + } + } + + public static boolean isVoid(TypeMirror mirror) { + return mirror.getKind() == TypeKind.VOID; + } + + public static boolean isPrimitive(TypeMirror mirror) { + return mirror.getKind().isPrimitive(); + } + + public static List getQualifiedSuperTypeNames(TypeElement element) { + List types = getSuperTypes(element); + List qualifiedNames = new ArrayList<>(); + for (TypeElement type : types) { + qualifiedNames.add(getQualifiedName(type)); + } + return qualifiedNames; + } + + public static List getDeclaredTypes(TypeElement element) { + return ElementFilter.typesIn(element.getEnclosedElements()); + } + + public static VariableElement findDeclaredField(TypeMirror type, String singletonName) { + List elements = ElementFilter.fieldsIn(fromTypeMirror(type).getEnclosedElements()); + for (VariableElement var : elements) { + if (var.getSimpleName().toString().equals(singletonName)) { + return var; + } + } + return null; + } + + public static TypeElement findEnclosingType(Element element) { + Element enclosing = element.getEnclosingElement(); + while (enclosing.getKind() != ElementKind.CLASS && enclosing.getKind() != ElementKind.ENUM && enclosing.getKind() != ElementKind.INTERFACE) { + enclosing = element.getEnclosingElement(); + } + + return (TypeElement) enclosing; + } + + public static List getSuperTypes(TypeElement element) { + List types = new ArrayList<>(); + List superTypes = null; + List superInterfaces = null; + if (element.getSuperclass() != null) { + TypeElement superElement = fromTypeMirror(element.getSuperclass()); + if (superElement != null) { + types.add(superElement); + superTypes = getSuperTypes(superElement); + } + } + for (TypeMirror interfaceMirror : element.getInterfaces()) { + TypeElement interfaceElement = fromTypeMirror(interfaceMirror); + if (interfaceElement != null) { + types.add(interfaceElement); + superInterfaces = getSuperTypes(interfaceElement); + } + } + + if (superTypes != null) { + types.addAll(superTypes); + } + + if (superInterfaces != null) { + types.addAll(superInterfaces); + } + + return types; + } + + public static String getPackageName(TypeElement element) { + return findPackageElement(element).getQualifiedName().toString(); + } + + public static String getPackageName(TypeMirror mirror) { + switch (mirror.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case SHORT: + case INT: + case LONG: + case VOID: + case TYPEVAR: + return null; + case DECLARED: + PackageElement pack = findPackageElement(fromTypeMirror(mirror)); + if (pack == null) { + throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror)); + } + return pack.getQualifiedName().toString(); + case ARRAY: + return getSimpleName(((ArrayType) mirror).getComponentType()); + default: + throw new RuntimeException("Unknown type specified " + mirror.getKind()); + } + } + + public static String createConstantName(String simpleName) { + //TODO use camel case to produce underscores. + return simpleName.toString().toUpperCase(); + } + + public static TypeElement fromTypeMirror(TypeMirror mirror) { + switch (mirror.getKind()) { + case DECLARED: + return (TypeElement) ((DeclaredType) mirror).asElement(); + case ARRAY: + return fromTypeMirror(((ArrayType) mirror).getComponentType()); + default: + return null; + } + } + + @SuppressWarnings("unchecked") + public static List getAnnotationValueList(AnnotationMirror mirror, String name) { + List result = new ArrayList<>(); + List< ? extends AnnotationValue> values = (List< ? extends AnnotationValue>) getAnnotationValue(mirror, name).getValue(); + for (AnnotationValue value : values) { + result.add((T) value.getValue()); + } + return result; + } + + public static TypeMirror getAnnotationValueType(AnnotationMirror mirror, String name) { + return (TypeMirror) getAnnotationValue(mirror, name).getValue(); + } + + public static TypeMirror getAnnotationValueTypeMirror(AnnotationMirror mirror, String name) { + return (TypeMirror) getAnnotationValue(mirror, name).getValue(); + } + + public static String getAnnotationValueString(AnnotationMirror mirror, String name) { + return (String) getAnnotationValue(mirror, name).getValue(); + } + + public static int getAnnotationValueInt(AnnotationMirror mirror, String name) { + return (int) getAnnotationValue(mirror, name).getValue(); + } + + public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) { + ExecutableElement valueMethod = null; + for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) { + if (method.getSimpleName().toString().equals(name)) { + valueMethod = method; + break; + } + } + + if (valueMethod == null) { + return null; + } + + AnnotationValue value = mirror.getElementValues().get(valueMethod); + if (value == null) { + value = valueMethod.getDefaultValue(); + } + return value; + } + + public static boolean getAnnotationValueBoolean(AnnotationMirror mirror, String name) { + return (Boolean) getAnnotationValue(mirror, name).getValue(); + } + + public static String printException(Throwable e) { + StringWriter string = new StringWriter(); + PrintWriter writer = new PrintWriter(string); + e.printStackTrace(writer); + writer.flush(); + return e.getMessage() + "\r\n" + string.toString(); + } + + public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class< ? > annotationClass) { + return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass); + } + + public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List< ? extends AnnotationMirror> mirrors, Class< ? > annotationClass) { + TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getName()); + for (AnnotationMirror mirror : mirrors) { + DeclaredType annotationType = mirror.getAnnotationType(); + TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); + if (actualAnnotationType.equals(expectedAnnotationType)) { + return mirror; + } + } + return null; + } + + private static PackageElement findPackageElement(Element type) { + Element searchType = type; + while (searchType.getEnclosingElement() != null && searchType.getEnclosingElement().getKind() != ElementKind.PACKAGE) { + searchType = type.getEnclosingElement(); + } + return (PackageElement) searchType.getEnclosingElement(); + } + + public static String firstLetterUpperCase(String name) { + if (name == null || name.isEmpty()) { + return name; + } + return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length()); + } + + public static String firstLetterLowerCase(String name) { + if (name == null || name.isEmpty()) { + return name; + } + return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length()); + } + + private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { + List methods = ElementFilter.methodsIn(element.getEnclosedElements()); + method: for (ExecutableElement method : methods) { + if (!method.getSimpleName().toString().equals(name)) { + continue; + } + if (method.getParameters().size() != params.length) { + continue; + } + for (int i = 0; i < params.length; i++) { + TypeMirror param1 = params[i]; + TypeMirror param2 = method.getParameters().get(i).asType(); + if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { + continue method; + } + } + return method; + } + return null; + } + + private static boolean isDeclaredMethod(TypeElement element, String name, TypeMirror[] params) { + return getDeclaredMethod(element, name, params) != null; + } + + public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { + List superElements = getSuperTypes(element); + + for (TypeElement typeElement : superElements) { + if (isDeclaredMethod(typeElement, name, params)) { + return true; + } + } + return false; + } + + private static ExecutableElement getDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) { + List superElements = getSuperTypes(element); + + for (TypeElement typeElement : superElements) { + ExecutableElement declared = getDeclaredMethod(typeElement, name, params); + if (declared != null) { + return declared; + } + } + return null; + } + + public static ExecutableElement getDeclaredMethodRecursive(TypeElement element, String name, TypeMirror[] params) { + ExecutableElement declared = getDeclaredMethod(element, name, params); + if (declared != null) { + return declared; + } + return getDeclaredMethodInSuperType(element, name, params); + } + + public static boolean typeEquals(TypeMirror type1, TypeMirror type2) { + if (type1 == null && type2 == null) { + return true; + } else if (type1 == null || type2 == null) { + return false; + } + String qualified1 = getQualifiedName(type1); + String qualified2 = getQualifiedName(type2); + return qualified1.equals(qualified2); + } + + + public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) { + if (typeEquals(t1, t2)) { + return 0; + } + Set t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1))); + if (t1SuperSet.contains(getQualifiedName(t2))) { + return -1; + } + + Set t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2))); + if (t2SuperSet.contains(getQualifiedName(t1))) { + return 1; + } + return 0; + } + + + public static boolean canThrowType(List thrownTypes, TypeMirror exceptionType) { + if (Utils.containsType(thrownTypes, exceptionType)) { + return true; + } + + if (isRuntimeException(exceptionType)) { + return true; + } + + // search for any supertypes + TypeElement exceptionTypeElement = fromTypeMirror(exceptionType); + List superTypes = getSuperTypes(exceptionTypeElement); + for (TypeElement typeElement : superTypes) { + if (Utils.containsType(thrownTypes, typeElement.asType())) { + return true; + } + } + + return false; + } + + private static boolean isRuntimeException(TypeMirror type) { + Set typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type))); + String typeName = getQualifiedName(type); + if (!typeSuperSet.contains(Throwable.class.getCanonicalName()) && !typeName.equals(Throwable.class.getCanonicalName())) { + throw new IllegalArgumentException("Given does not extend Throwable."); + } + return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || typeName.equals(RuntimeException.class.getCanonicalName()); + } + + private static boolean containsType(Collection collection, TypeMirror type) { + for (TypeMirror otherTypeMirror : collection) { + if (typeEquals(otherTypeMirror, type)) { + return true; + } + } + return false; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionContext.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.api; + +import javax.annotation.processing.*; + +import com.oracle.truffle.codegen.processor.api.element.*; + + +public interface ExtensionContext { + + ProcessingEnvironment getProcessingEnvironment(); + + RoundEnvironment getRoundEnvironment(); + + WritableElementFactory getElementFactory(); + + void addGeneratedElement(WritableElement element); + + void removeGeneratedElement(WritableElement element); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/ExtensionProcessor.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.api; + +import javax.lang.model.element.*; + + +public interface ExtensionProcessor { + + void process(ExtensionContext context, AnnotationMirror mirror, Element element); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableAnnotationMirror.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableAnnotationMirror.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.api.element; + +import javax.lang.model.element.*; + +public interface WritableAnnotationMirror extends AnnotationMirror { + + void setElementValue(ExecutableElement valueName, AnnotationValue value); + + AnnotationValue getElementValue(ExecutableElement valueName); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.api.element; + +import javax.lang.model.element.*; + + +public interface WritableElement extends Element { + + void addAnnotationMirror(AnnotationMirror annotationMirror); + + void removeAnnotationMirror(AnnotationMirror annotationMirror); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableElementFactory.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.api.element; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + + +public interface WritableElementFactory { + + WritableExecutableElement cloneExecutableElement(ExecutableElement method); + WritableVariableElement cloneVariableElement(VariableElement parameter); + WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror); + + WritableVariableElement createParameter(TypeMirror type, String simpleName); + WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName); + WritableAnnotationMirror createAnnotationMirror(DeclaredType annotationClass); + + Name createName(String name); + AnnotationValue createAnnotationValue(Object value); + TypeMirror createTypeMirror(Class javaClass); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableExecutableElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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.api.element; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public interface WritableExecutableElement extends ExecutableElement, WritableElement { + + void setReturnType(TypeMirror type); + void setDefaultValue(AnnotationValue defaultValue); + + void addParameter(VariableElement parameter); + void removeParamter(VariableElement parameter); + + void addThrownType(TypeMirror thrownType); + void removeThrownType(TypeMirror thrownType); + + void setSimpleName(Name name); + void setVarArgs(boolean varargs); + + void setBody(String body); + String getBody(); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableVariableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/api/element/WritableVariableElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.api.element; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public interface WritableVariableElement extends VariableElement, WritableElement { + + void setSimpleName(Name name); + void setType(TypeMirror type); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.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/CodeAnnotationMirror.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,81 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.codegen.processor.api.element.*; + +public class CodeAnnotationMirror implements WritableAnnotationMirror { + + private final DeclaredType annotationType; + private final Map values = new LinkedHashMap<>(); + + public CodeAnnotationMirror(DeclaredType annotationType) { + this.annotationType = annotationType; + } + + @Override + public DeclaredType getAnnotationType() { + return annotationType; + } + + @Override + public Map< ? extends ExecutableElement, ? extends AnnotationValue> getElementValues() { + return values; + } + + @Override + public AnnotationValue getElementValue(ExecutableElement method) { + return values.get(method); + } + + @Override + public void setElementValue(ExecutableElement method, AnnotationValue value) { + values.put(method, value); + } + + public ExecutableElement findExecutableElement(String name) { + List elements = ElementFilter.methodsIn(annotationType.asElement().getEnclosedElements()); + for (ExecutableElement executableElement : elements) { + if (executableElement.getSimpleName().toString().equals(name)) { + return executableElement; + } + } + return null; + } + + public static CodeAnnotationMirror clone(AnnotationMirror mirror) { + CodeAnnotationMirror copy = new CodeAnnotationMirror(mirror.getAnnotationType()); + for (ExecutableElement key : mirror.getElementValues().keySet()) { + copy.setElementValue(key, mirror.getElementValues().get(key)); + } + return copy; + } + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationValue.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/CodeAnnotationValue.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,88 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeAnnotationValue implements AnnotationValue { + + private final Object value; + + public CodeAnnotationValue(Object value) { + Objects.requireNonNull(value); + if ((value instanceof AnnotationMirror) || (value instanceof List< ? >) + || (value instanceof Boolean) || (value instanceof Byte) + || (value instanceof Character) || (value instanceof Double) + || (value instanceof VariableElement) || (value instanceof Float) + || (value instanceof Integer) || (value instanceof Long) + || (value instanceof Short) || (value instanceof String) + || (value instanceof TypeMirror)) { + this.value = value; + } else { + throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName()); + } + } + + @Override + public Object getValue() { + return value; + } + + @SuppressWarnings("unchecked") + @Override + public R accept(AnnotationValueVisitor v, P p) { + if (value instanceof AnnotationMirror) { + return v.visitAnnotation((AnnotationMirror) value, p); + } else if (value instanceof List< ? >) { + return v.visitArray((List< ? extends AnnotationValue>) value, p); + } else if (value instanceof Boolean) { + return v.visitBoolean((boolean) value, p); + } else if (value instanceof Byte) { + return v.visitByte((byte) value, p); + } else if (value instanceof Character) { + return v.visitChar((char) value, p); + } else if (value instanceof Double) { + return v.visitDouble((double) value, p); + } else if (value instanceof VariableElement) { + return v.visitEnumConstant((VariableElement) value, p); + } else if (value instanceof Float) { + return v.visitFloat((float) value, p); + } else if (value instanceof Integer) { + return v.visitInt((int) value, p); + } else if (value instanceof Long) { + return v.visitLong((long) value, p); + } else if (value instanceof Short) { + return v.visitShort((short) value, p); + } else if (value instanceof String) { + return v.visitString((String) value, p); + } else if (value instanceof TypeMirror) { + return v.visitType((TypeMirror) value, p); + } else { + return v.visitUnknown(this, p); + } + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeCompilationUnit.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/CodeCompilationUnit.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,59 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeCompilationUnit extends CodeElement { + + public CodeCompilationUnit() { + super(Collections. emptySet()); + } + + @Override + public TypeMirror asType() { + throw new UnsupportedOperationException(); + } + + @Override + public ElementKind getKind() { + return ElementKind.OTHER; + } + + @Override + public Name getSimpleName() { + throw new UnsupportedOperationException(); + } + + @Override + public R accept(ElementVisitor v, P p) { + for (TypeElement type : getEnclosedElements()) { + type.accept(v, p); + } + return null; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.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/CodeElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,345 @@ +/* + * 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; + +import java.io.*; +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.api.element.*; +import com.oracle.truffle.codegen.processor.codewriter.*; + +public abstract class CodeElement implements WritableElement, GeneratedElement { + + private final Set modifiers; + private List annotations; + private List enclosedElements; + + private Element enclosingElement; + + private Element generatorElement; + private AnnotationMirror generatorAnnotationMirror; + + public CodeElement() { + this.modifiers = new LinkedHashSet<>(); + } + + + @Override + public void setGeneratorAnnotationMirror(AnnotationMirror mirror) { + this.generatorAnnotationMirror = mirror; + } + + @Override + public void setGeneratorElement(Element element) { + this.generatorElement = element; + } + + @Override + public AnnotationMirror getGeneratorAnnotationMirror() { + return generatorAnnotationMirror; + } + + @Override + public Element getGeneratorElement() { + return generatorElement; + } + + public CodeElement(Set modifiers) { + this.modifiers = new LinkedHashSet<>(modifiers); + } + + public E add(E element) { + if (element == null) { + throw new NullPointerException(); + } + getEnclosedElements().add(element); + return element; + } + + public void remove(E element) { + getEnclosedElements().remove(element); + } + + @Override + public Set getModifiers() { + return modifiers; + } + + @Override + public List getEnclosedElements() { + if (enclosedElements == null) { + enclosedElements = parentableList(this, new ArrayList()); + } + return enclosedElements; + } + + @Override + public List getAnnotationMirrors() { + if (annotations == null) { + annotations = parentableList(this, new ArrayList()); + } + return annotations; + } + + @Override + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException(); + } + + @Override + public void addAnnotationMirror(AnnotationMirror annotationMirror) { + getAnnotationMirrors().add(annotationMirror); + } + + public void removeAnnotationMirror(AnnotationMirror annotationMirror) { + getAnnotationMirrors().remove(annotationMirror); + } + + void setEnclosingElement(Element parent) { + if (this.enclosingElement != null && parent != null) { + throw new IllegalStateException("Element already added to " + parent); + } + this.enclosingElement = parent; + } + + public Element getEnclosingElement() { + return enclosingElement; + } + + public CodeTypeElement getEnclosingClass() { + Element p = enclosingElement; + while (p != null && p.getKind() != ElementKind.CLASS + && p.getKind() != ElementKind.ENUM) { + p = p.getEnclosingElement(); + } + return (CodeTypeElement) p; + } + + List parentableList(Element parent, List list) { + return new ParentableList<>(parent, list); + } + + + @Override + public String toString() { + StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter(); + accept(codeWriter, null); + return codeWriter.getString(); + } + + private static class StringBuilderCodeWriter extends AbstractCodeWriter { + + public StringBuilderCodeWriter() { + this.writer = new CharArrayWriter(); + } + + @Override + protected Writer createWriter(CodeTypeElement clazz) throws IOException { + return writer; + } + public String getString() { + return new String(((CharArrayWriter) writer).toCharArray()); + } + + } + + + private static class ParentableList implements List { + + private final Element parent; + private final List delegate; + + public ParentableList(Element parent, List delegate) { + this.parent = parent; + this.delegate = delegate; + } + + private void addImpl(T element) { + if (element != null) { + if (element instanceof CodeElement) { + ((CodeElement) element).setEnclosingElement(parent); + } + } + } + + private static void removeImpl(Object element) { + if (element instanceof CodeElement) { + ((CodeElement) element).setEnclosingElement(null); + } + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return delegate.contains(o); + } + + @Override + public Iterator iterator() { + return delegate.iterator(); + } + + @Override + public Object[] toArray() { + return delegate.toArray(); + } + + @Override + public E[] toArray(E[] a) { + return delegate.toArray(a); + } + + @Override + public boolean add(T e) { + addImpl(e); + return delegate.add(e); + } + + @Override + public boolean remove(Object o) { + boolean removed = delegate.remove(o); + if (removed) { + removeImpl(o); + } + return removed; + } + + @Override + public boolean containsAll(Collection< ? > c) { + return delegate.containsAll(c); + } + + @Override + public boolean addAll(Collection< ? extends T> c) { + if (c != null) { + for (T t : c) { + addImpl(t); + } + } + return delegate.addAll(c); + } + + @Override + public boolean addAll(int index, Collection< ? extends T> c) { + if (c != null) { + for (T t : c) { + addImpl(t); + } + } + return delegate.addAll(index, c); + } + + @Override + public boolean removeAll(Collection< ? > c) { + if (c != null) { + for (Object t : c) { + removeImpl(t); + } + } + return delegate.removeAll(c); + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public boolean retainAll(Collection< ? > c) { + throw new UnsupportedOperationException("Not supported by parentable list"); + } + + @Override + public void clear() { + for (Object e : this) { + removeImpl(e); + } + delegate.clear(); + } + + @Override + public T get(int index) { + return delegate.get(index); + } + + @Override + public T set(int index, T element) { + removeImpl(delegate.get(index)); + addImpl(element); + return delegate.set(index, element); + } + + @Override + public void add(int index, T element) { + addImpl(element); + delegate.add(index, element); + } + + @Override + public T remove(int index) { + T element = delegate.remove(index); + removeImpl(element); + return element; + } + + @Override + public int indexOf(Object o) { + return delegate.indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + return delegate.lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return delegate.listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return delegate.listIterator(index); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex)); + } + + } + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElementScanner.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/CodeElementScanner.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,76 @@ +/* + * 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; + +import javax.lang.model.element.*; +import javax.lang.model.util.*; + +public abstract class CodeElementScanner extends ElementScanner7{ + + @Override + public final R visitExecutable(ExecutableElement e, P p) { + return visitExecutable(cast(e, CodeExecutableElement.class), p); + } + + public R visitExecutable(CodeExecutableElement e, P p) { + R ret = super.visitExecutable(e, p); + if (e.getBodyTree() != null) { + visitTree(e.getBodyTree(), p); + } + return ret; + } + + @Override + public R visitPackage(PackageElement e, P p) { + return super.visitPackage(e, p); + } + + @Override + public final R visitType(TypeElement e, P p) { + return visitType(cast(e, CodeTypeElement.class), p); + } + + public R visitType(CodeTypeElement e, P p) { + return super.visitType(e, p); + } + + @Override + public R visitTypeParameter(TypeParameterElement e, P p) { + return super.visitTypeParameter(e, p); + } + + private static E cast(Element element, Class clazz) { + return clazz.cast(element); + } + + public void visitTree(CodeTree e, P p) { + for (CodeTree tree : e.getEnclosedElements()) { + tree.acceptCodeElementScanner(this, p); + } + } + + @SuppressWarnings("unused") + public void visitImport(CodeImport e, P p) { + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.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/CodeExecutableElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,206 @@ +/* + * 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; + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.api.element.*; + +public class CodeExecutableElement extends CodeElement implements WritableExecutableElement { + + private final List throwables = new ArrayList<>(); + private final List parameters = parentableList(this, new ArrayList()); + + private TypeMirror returnType; + private Name name; + + private CodeTree bodyTree; + private String body; + private AnnotationValue defaultValue; + private boolean varArgs; + + public CodeExecutableElement(TypeMirror returnType, String name) { + super(Utils.modifiers()); + this.returnType = returnType; + this.name = CodeNames.of(name); + } + + public CodeExecutableElement(Set modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) { + super(modifiers); + this.returnType = returnType; + this.name = CodeNames.of(name); + for (CodeVariableElement codeParameter : parameters) { + addParameter(codeParameter); + } + } + + @Override + public List getThrownTypes() { + return throwables; + } + + @Override + public TypeMirror asType() { + return returnType; + } + + @Override + public ElementKind getKind() { + return ElementKind.METHOD; + } + + @Override + public List< ? extends TypeParameterElement> getTypeParameters() { + return Collections.emptyList(); + } + + @Override + public void setVarArgs(boolean varargs) { + this.varArgs = varargs; + } + + @Override + public boolean isVarArgs() { + return varArgs; + } + + @Override + public void setDefaultValue(AnnotationValue defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public AnnotationValue getDefaultValue() { + return defaultValue; + } + + @Override + public Name getSimpleName() { + return name; + } + + public CodeTreeBuilder createBuilder() { + CodeTreeBuilder builder = new CodeTreeBuilder(); + this.bodyTree = builder.getTree(); + this.bodyTree.setEnclosingElement(this); + return builder; + } + + public void setBodyTree(CodeTree body) { + this.bodyTree = body; + } + + public CodeTree getBodyTree() { + return bodyTree; + } + + public TypeMirror getReturnType() { + return returnType; + } + + @Override + public List getParameters() { + return parameters; + } + + public TypeMirror[] getParameterTypes() { + TypeMirror[] types = new TypeMirror[getParameters().size()]; + for (int i = 0; i < types.length; i++) { + types[i] = parameters.get(i).asType(); + } + return types; + } + + @Override + public void setReturnType(TypeMirror type) { + returnType = type; + } + + @Override + public void addParameter(VariableElement parameter) { + parameters.add(parameter); + } + + @Override + public void removeParamter(VariableElement parameter) { + parameters.remove(parameter); + } + + @Override + public void addThrownType(TypeMirror thrownType) { + throwables.add(thrownType); + } + + @Override + public void removeThrownType(TypeMirror thrownType) { + throwables.remove(thrownType); + } + + @Override + public void setSimpleName(Name name) { + this.name = name; + } + + @Override + public void setBody(String body) { + this.body = body; + } + + @Override + public String getBody() { + return body; + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitExecutable(this, p); + } + + + public static CodeExecutableElement clone(ProcessingEnvironment env, ExecutableElement method) { + CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString()); + for (TypeMirror thrownType : method.getThrownTypes()) { + copy.addThrownType(thrownType); + } + copy.setDefaultValue(method.getDefaultValue()); + + for (AnnotationMirror mirror : method.getAnnotationMirrors()) { + copy.addAnnotationMirror(mirror); + } + for (VariableElement var : method.getParameters()) { + copy.addParameter(var); + } + for (Element element : method.getEnclosedElements()) { + copy.add(element); + } + copy.setBody(Utils.getMethodBody(env, method)); + copy.getModifiers().addAll(method.getModifiers()); + return copy; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeImport.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/CodeImport.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,100 @@ +/* + * 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; + +import javax.lang.model.type.*; + +public class CodeImport implements Comparable { + + private final TypeMirror importType; + private final String importString; + private final boolean staticImport; + + public CodeImport(TypeMirror importedType, String importString, boolean staticImport) { + this.importType = importedType; + this.importString = importString; + this.staticImport = staticImport; + } + + public TypeMirror getImportType() { + return importType; + } + + public boolean isStaticImport() { + return staticImport; + } + + public String getImportString() { + return importString; + } + + @Override + public int compareTo(CodeImport o) { + if (staticImport && !o.staticImport) { + return 1; + } else if (!staticImport && o.staticImport) { + return -1; + } else { + return importString.compareTo(o.getImportString()); + } + } + + public

void accept(CodeElementScanner s, P p) { + s.visitImport(this, p); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((importString == null) ? 0 : importString.hashCode()); + result = prime * result + (staticImport ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + CodeImport other = (CodeImport) obj; + if (importString == null) { + if (other.importString != null) { + return false; + } + } else if (!importString.equals(other.importString)) { + return false; + } + if (staticImport != other.staticImport) { + return false; + } + return true; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeNames.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/CodeNames.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,90 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; + +public abstract class CodeNames { + + private static Map names = new HashMap<>(); + + public static Name of(String value) { + Name name = names.get(value); + if (name == null) { + name = new NameImpl(value); + names.put(value, name); + } + return name; + } + + private static class NameImpl implements Name { + + private final String name; + + public NameImpl(String name) { + this.name = name; + } + + @Override + public int length() { + return name.length(); + } + + @Override + public char charAt(int index) { + return name.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return name.subSequence(start, end); + } + + @Override + public boolean contentEquals(CharSequence cs) { + return name.contentEquals(cs); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Name) { + return ((Name) obj).contentEquals(name); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return name; + } + + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTree.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/CodeTree.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,81 @@ +/* + * 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; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeTree extends CodeElement { + + private final CodeTreeKind kind; + + private final TypeMirror type; + private final String string; + + public CodeTree(CodeTreeKind kind, TypeMirror type, String string) { + this.kind = kind; + this.type = type; + this.string = string; + } + + public TypeMirror getType() { + return type; + } + + public CodeTreeKind getCodeKind() { + return kind; + } + + public String getString() { + return string; + } + + public

void acceptCodeElementScanner(CodeElementScanner s, P p) { + s.visitTree(this, p); + } + + @Override + public TypeMirror asType() { + return type; + } + + @Override + public ElementKind getKind() { + return ElementKind.OTHER; + } + + @Override + public Name getSimpleName() { + return CodeNames.of(getString()); + } + + @Override + public R accept(ElementVisitor v, P p) { + if (v instanceof CodeElementScanner) { + acceptCodeElementScanner((CodeElementScanner) v, p); + return null; + } else { + throw new UnsupportedOperationException(); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.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/CodeTreeBuilder.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,705 @@ +/* + * 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; + +import static com.oracle.truffle.codegen.processor.ast.CodeTreeKind.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; + +public class CodeTreeBuilder { + + private BuilderCodeTree currentElement; + private final BuilderCodeTree root; + + public CodeTreeBuilder() { + this.root = new BuilderCodeTree(GROUP, null, null); + this.currentElement = root; + } + + public CodeTreeBuilder(CodeTree tree) { + this.root = (BuilderCodeTree) tree; + this.currentElement = root; + } + + public CodeTreeBuilder statement(String statement) { + return startStatement().string(statement).end(); + } + + public CodeTreeBuilder statement(CodeTree statement) { + return startStatement().tree(statement).end(); + } + + public static CodeTreeBuilder createBuilder() { + return new CodeTreeBuilder(); + } + + public static CodeTree singleString(String s) { + return new CodeTreeBuilder().string(s).getTree(); + } + + private CodeTreeBuilder push(CodeTreeKind kind) { + return push(new BuilderCodeTree(kind, null, null)); + } + + private CodeTreeBuilder push(String string) { + return push(new BuilderCodeTree(CodeTreeKind.STRING, null, string)); + } + + private CodeTreeBuilder push(TypeMirror type) { + return push(new BuilderCodeTree(CodeTreeKind.TYPE, type, null)); + } + + private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) { + return push(new BuilderCodeTree(kind, type, string)); + } + + private CodeTreeBuilder push(BuilderCodeTree tree) { + if (currentElement != null) { + currentElement.add(tree); + } + switch (tree.getCodeKind()) { + case COMMA_GROUP: + case GROUP: + case INDENT: + currentElement = tree; + break; + } + return this; + } + + private void clearLast(CodeTreeKind kind) { + clearLastRec(kind, currentElement.getEnclosedElements()); + } + + public CodeTreeBuilder startStatement() { + startGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + string(";").newLine(); + } + + @Override + public void afterEnd() { + } + }); + return this; + } + + public CodeTreeBuilder startGroup() { + return push(CodeTreeKind.GROUP); + } + + public CodeTreeBuilder startCommaGroup() { + return push(CodeTreeKind.COMMA_GROUP); + } + + public CodeTreeBuilder startCall(String callSite) { + return startCall(null, callSite); + } + + public CodeTreeBuilder startCall(String receiver, String callSite) { + if (receiver == null) { + return startGroup().string(callSite).startParanthesesCommaGroup().endAfter(); + } else { + return startGroup().string(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter(); + } + } + + public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) { + return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startStaticCall(ExecutableElement method) { + return startStaticCall(Utils.findEnclosingType(method).asType(), method.getSimpleName().toString()); + } + + public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) { + return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName); + } + + private CodeTreeBuilder endAndWhitespaceAfter() { + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(" "); + end(); + } + }); + return this; + } + + private CodeTreeBuilder endAfter() { + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + end(); + } + }); + return this; + } + + private CodeTreeBuilder startParanthesesCommaGroup() { + startGroup(); + string("(").startCommaGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string(")"); + } + }); + endAfter(); + return this; + } + + public CodeTreeBuilder startParantheses() { + startGroup(); + string("(").startGroup(); + registerCallBack(new EndCallback() { + @Override + public void beforeEnd() { + } + @Override + public void afterEnd() { + string(")"); + } + }); + endAfter(); + return this; + } + + public CodeTreeBuilder startDoubleQuote() { + startGroup().string("\""); + registerCallBack(new EndCallback() { + @Override + public void beforeEnd() { + } + @Override + public void afterEnd() { + string("\""); + } + }); + return this; + } + + public CodeTreeBuilder string(String chunk1) { + return push(chunk1); + } + + public CodeTreeBuilder string(String chunk1, String chunk2) { + return push(GROUP).string(chunk1).string(chunk2).end(); + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) { + return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end(); + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) { + return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end(); + } + + public CodeTreeBuilder tree(CodeTree treeToAdd) { + return push((BuilderCodeTree) treeToAdd).end(); + } + + public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) { + push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4); + for (int i = 0; i < chunks.length; i++) { + string(chunks[i]); + } + return end(); + } + + public CodeTreeBuilder dot() { + return string("."); + } + + public CodeTreeBuilder newLine() { + return push(NEW_LINE); + } + + public CodeTreeBuilder startWhile() { + return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startIf() { + return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startElseIf() { + clearLast(CodeTreeKind.NEW_LINE); + return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); + } + + public CodeTreeBuilder startElseBlock() { + clearLast(CodeTreeKind.NEW_LINE); + return startGroup().string(" else ").startBlock().endAfter(); + } + + private boolean clearLastRec(CodeTreeKind kind, List children) { + for (int i = children.size() - 1; i >= 0; i--) { + CodeTree child = children.get(i); + if (child.getCodeKind() == kind) { + children.remove(children.get(i)); + return true; + } else { + if (clearLastRec(kind, child.getEnclosedElements())) { + return true; + } + } + } + return false; + } + + public CodeTreeBuilder startCase() { + startGroup().string("case "); + registerCallBack(new EndCallback() { + @Override + public void beforeEnd() { + string(" :").newLine(); + } + @Override + public void afterEnd() { + } + }); + return this; + } + + public CodeTreeBuilder caseDefault() { + return startGroup().string("default :").newLine().end(); + } + + public CodeTreeBuilder startSwitch() { + return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter(); + } + + public CodeTreeBuilder startReturn() { + ExecutableElement method = findMethod(); + if (method != null && Utils.isVoid(method.getReturnType())) { + startStatement(); + return this; + } else { + return startStatement().string("return "); + } + } + + public CodeTreeBuilder startAssert() { + return startStatement().string("assert "); + } + + public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) { + return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startNew(String typeName) { + return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter(); + } + + public CodeTreeBuilder startIndention() { + return push(CodeTreeKind.INDENT); + } + + public CodeTreeBuilder end() { + BuilderCodeTree tree = currentElement; + EndCallback callback = tree.getAtEndListener(); + if (callback != null) { + callback.beforeEnd(); + toParent(); + callback.afterEnd(); + } else { + toParent(); + } + return this; + } + + private void toParent() { + Element parent = currentElement.getEnclosingElement(); + if (currentElement != root) { + this.currentElement = (BuilderCodeTree) parent; + } else { + this.currentElement = root; + } + } + + public CodeTreeBuilder startBlock() { + startGroup(); + string("{").newLine().startIndention(); + registerCallBack(new EndCallback() { + @Override + public void beforeEnd() { + } + @Override + public void afterEnd() { + string("}").newLine(); + } + }); + endAfter(); + return this; + } + + private void registerCallBack(EndCallback callback) { + currentElement.registerAtEnd(callback); + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) { + if (Utils.isVoid(type)) { + startStatement(); + tree(init); + end(); + } else { + startStatement(); + type(type); + string(" "); + string(name); + if (init != null) { + string(" = "); + tree(init); + } + end(); // statement + } + return this; + } + + public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) { + if (init == this) { + throw new IllegalArgumentException("Recursive builder usage."); + } + return declaration(type, name, init.getTree()); + } + + public CodeTreeBuilder declaration(TypeMirror type, String name) { + return declaration(type, name, (CodeTree) null); + } + + public CodeTreeBuilder create() { + return new CodeTreeBuilder(); + } + + public CodeTreeBuilder type(TypeMirror type) { + return push(type); + } + + public CodeTreeBuilder typeLiteral(TypeMirror type) { + return startGroup().type(type).string(".class").end(); + } + + private void assertRoot() { + if (currentElement != root) { + throw new IllegalStateException("CodeTreeBuilder was not ended properly."); + } + } + + public CodeTreeBuilder startCaseBlock() { + return startIndention(); + } + + public CodeTreeBuilder startThrow() { + return startStatement().string("throw "); + } + + public CodeTree getTree() { + assertRoot(); + return root; + } + + public CodeTree getRoot() { + return root; + } + + public CodeTreeBuilder cast(TypeMirror type, CodeTree content) { + if (Utils.isVoid(type)) { + tree(content); + return this; + } else if (Utils.getQualifiedName(type).equals("java.lang.Object")) { + tree(content); + return this; + } else { + return startGroup().string("(").type(type).string(")").string(" ").tree(content).end(); + } + } + + public CodeTreeBuilder startSuperCall() { + return string("super").startParanthesesCommaGroup(); + } + + public CodeTreeBuilder returnFalse() { + return startReturn().string("false").end(); + } + + public CodeTreeBuilder returnStatement() { + return statement("return"); + } + + private ExecutableElement findMethod() { + Element element = currentElement; + while (element != null && (element.getKind() != ElementKind.METHOD)) { + element = element.getEnclosingElement(); + } + return element != null ? (ExecutableElement) element : null; + } + + public CodeTreeBuilder returnTrue() { + return startReturn().string("true").end(); + } + + public CodeTreeBuilder instanceOf(String var, TypeMirror type) { + string(var); + TypeElement element = Utils.fromTypeMirror(type); + if (element == null) { + throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind()); + } + + string(" instanceof ").type(type); + return this; + } + + public CodeTreeBuilder defaultValue(TypeMirror mirror) { + switch (mirror.getKind()) { + case VOID: + return string(""); + case ARRAY: + case DECLARED: + case PACKAGE: + case NULL: + return string("null"); + case BOOLEAN: + return string("false"); + case BYTE: + return string("(byte) 0"); + case CHAR: + return string("(char) 0"); + case DOUBLE: + return string("0.0D"); + case LONG: + return string("0L"); + case INT: + return string("0"); + case FLOAT: + return string("0.0F"); + case SHORT: + return string("(short) 0"); + default: + throw new AssertionError(); + } + } + + public CodeTreeBuilder assertFalse() { + return startAssert().string("false").end(); + } + + public CodeTreeBuilder breakStatement() { + return statement("break"); + } + + public CodeTreeBuilder isNull() { + return string(" == null"); + } + + public CodeTreeBuilder isNotNull() { + return string(" != null"); + } + + public CodeTreeBuilder is(CodeTree tree) { + return string(" == ").tree(tree); + } + + public CodeTreeBuilder startTryBlock() { + return string("try ").startBlock(); + } + + public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) { + clearLast(CodeTreeKind.NEW_LINE); + string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") "); + return startBlock(); + } + + public CodeTreeBuilder startFinallyBlock() { + clearLast(CodeTreeKind.NEW_LINE); + string(" finally "); + return startBlock(); + } + + public CodeTreeBuilder null_() { + return string("null"); + } + + private static class BuilderCodeTree extends CodeTree { + + private EndCallback atEndListener; + + public BuilderCodeTree(CodeTreeKind kind, TypeMirror type, String string) { + super(kind, type, string); + } + + public void registerAtEnd(EndCallback atEnd) { + if (this.atEndListener != null) { + this.atEndListener = new CompoundCallback(this.atEndListener, atEnd); + } else { + this.atEndListener = atEnd; + } + } + + public EndCallback getAtEndListener() { + return atEndListener; + } + + @Override + public String toString() { + final StringBuilder b = new StringBuilder(); + acceptCodeElementScanner(new Printer(b), null); + return b.toString(); + } + + private static class CompoundCallback implements EndCallback { + + private final EndCallback callback1; + private final EndCallback callback2; + + public CompoundCallback(EndCallback callback1, EndCallback callback2) { + this.callback1 = callback1; + this.callback2 = callback2; + } + + @Override + public void afterEnd() { + callback1.afterEnd(); + callback2.afterEnd(); + } + + @Override + public void beforeEnd() { + callback1.beforeEnd(); + callback1.beforeEnd(); + } + } + + } + + private interface EndCallback { + + void beforeEnd(); + + void afterEnd(); + } + + private static class Printer extends CodeElementScanner { + + private int indent; + private boolean newLine; + private final String ln = "\n"; + + private final StringBuilder b; + + Printer(StringBuilder b) { + this.b = b; + } + + @Override + public void visitTree(CodeTree e, Void p) { + switch (e.getCodeKind()) { + case COMMA_GROUP: + List children = e.getEnclosedElements(); + for (int i = 0; i < children.size(); i++) { + children.get(i).acceptCodeElementScanner(this, p); + if (i < e.getEnclosedElements().size() - 1) { + b.append(", "); + } + } + break; + case GROUP: + super.visitTree(e, p); + break; + case INDENT: + indent(); + super.visitTree(e, p); + dedent(); + break; + case NEW_LINE: + writeLn(); + break; + case STRING: + if (e.getString() != null) { + write(e.getString()); + } else { + write("null"); + } + break; + case TYPE: + write(Utils.getSimpleName(e.getType())); + break; + default: + assert false; + return; + } + } + + private void indent() { + indent++; + } + + private void dedent() { + indent--; + } + + private void writeLn() { + write(ln); + newLine = true; + } + + private void write(String m) { + if (newLine && m != ln) { + writeIndent(); + newLine = false; + } + b.append(m); + } + + private void writeIndent() { + for (int i = 0; i < indent; i++) { + b.append(" "); + } + } + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeKind.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/CodeTreeKind.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,27 @@ +/* + * 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 enum CodeTreeKind { + STATIC_FIELD_REFERENCE, STATIC_METHOD_REFERENCE, GROUP, COMMA_GROUP, INDENT, STRING, NEW_LINE, TYPE; +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeElement.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/CodeTypeElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,203 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.codegen.processor.ast.CodeTypeMirror.DeclaredCodeTypeMirror; + +public class CodeTypeElement extends CodeElement implements TypeElement { + + private final List imports = parentableList(this, new ArrayList()); + + private final PackageElement packageElement; + + private final Name simpleName; + private final Name packageName; + private Name qualifiedName; + + private final List implementsInterfaces = new ArrayList<>(); + private final ElementKind kind; + private TypeMirror superClass; + + private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this); + + public CodeTypeElement(Set modifiers, ElementKind kind, PackageElement packageElement, String simpleName) { + super(modifiers); + this.kind = kind; + this.packageElement = packageElement; + this.simpleName = CodeNames.of(simpleName); + if (this.packageElement != null) { + this.packageName = packageElement.getQualifiedName(); + } else { + this.packageName = CodeNames.of("default"); + } + this.qualifiedName = createQualifiedName(); + } + + @Override + public TypeMirror asType() { + return mirror; + } + + @Override + public ElementKind getKind() { + return kind; + } + + public boolean containsField(String name) { + for (VariableElement field : getFields()) { + if (field.getSimpleName().toString().equals(name)) { + return true; + } + } + return false; + } + + @Override + public NestingKind getNestingKind() { + return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL; + } + + @Override + public Element getEnclosingElement() { + if (isTopLevelClass()) { + return packageElement; + } else { + return super.getEnclosingElement(); + } + } + + @Override + public TypeMirror getSuperclass() { + return superClass; + } + + @Override + public List getInterfaces() { + return implementsInterfaces; + } + + @Override + public List< ? extends TypeParameterElement> getTypeParameters() { + return Collections.emptyList(); + } + + public boolean isTopLevelClass() { + return super.getEnclosingElement() instanceof CodeCompilationUnit; + } + + public CodeVariableElement getField(String name) { + for (VariableElement field : ElementFilter.fieldsIn(getEnclosedElements())) { + if (field.getSimpleName().toString().equals(name)) { + return (CodeVariableElement) field; + } + } + return null; + } + + private Name createQualifiedName() { + TypeElement enclosingType = getEnclosingClass(); + if (enclosingType == null) { + return CodeNames.of(packageName + "." + simpleName); + } else { + return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName); + } + } + + @Override + void setEnclosingElement(Element element) { + super.setEnclosingElement(element); + + // update qualified name on container change + this.qualifiedName = createQualifiedName(); + } + + public Name getPackageName() { + return packageName; + } + + @Override + public Name getQualifiedName() { + return qualifiedName; + } + + @Override + public Name getSimpleName() { + return simpleName; + } + + public void setSuperClass(TypeMirror superType) { + this.superClass = superType; + } + + public List getImports() { + return imports; + } + + public List getImplements() { + return implementsInterfaces; + } + + @Override + public int hashCode() { + return getQualifiedName().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof TypeElement) { + return getQualifiedName().equals(((TypeElement) obj).getQualifiedName()); + } + return false; + } + + public List getFields() { + return ElementFilter.fieldsIn(getEnclosedElements()); + } + + public List getMethods() { + return ElementFilter.methodsIn(getEnclosedElements()); + } + + public List getInnerClasses() { + return ElementFilter.typesIn(getEnclosedElements()); + } + + @Override + public String toString() { + return getQualifiedName().toString(); + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitType(this, p); + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.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/CodeTypeMirror.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,95 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class CodeTypeMirror implements TypeMirror { + + private final TypeKind kind; + + public CodeTypeMirror(TypeKind kind) { + this.kind = kind; + } + + @Override + public TypeKind getKind() { + return kind; + } + + @Override + public R accept(TypeVisitor v, P p) { + throw new UnsupportedOperationException(); + } + + public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType { + + private final TypeMirror component; + + public ArrayCodeTypeMirror(TypeMirror component) { + super(TypeKind.ARRAY); + this.component = component; + } + + @Override + public TypeMirror getComponentType() { + return component; + } + + } + + public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType { + + private final CodeTypeElement clazz; + + public DeclaredCodeTypeMirror(CodeTypeElement clazz) { + super(TypeKind.DECLARED); + this.clazz = clazz; + } + + @Override + public Element asElement() { + return clazz; + } + + @Override + public TypeMirror getEnclosingType() { + return clazz.getEnclosingElement().asType(); + } + + @Override + public List< ? extends TypeMirror> getTypeArguments() { + return Collections.emptyList(); + } + + @Override + public String toString() { + return clazz.getQualifiedName().toString(); + } + + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.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/CodeVariableElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,144 @@ +/* + * 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; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.api.element.*; + +public final class CodeVariableElement extends CodeElement implements WritableVariableElement { + + private Name name; + private TypeMirror type; + private Object constantValue; + + private CodeTree init; + + public CodeVariableElement(TypeMirror type, String name) { + super(Utils.modifiers()); + this.type = type; + this.name = CodeNames.of(name); + } + + public CodeVariableElement(Set modifiers, TypeMirror type, String name) { + super(modifiers); + this.type = type; + this.name = CodeNames.of(name); + } + + public CodeVariableElement(Set modifiers, TypeMirror type, String name, String init) { + this(modifiers, type, name); + if (init != null) { + this.init = new CodeTree(CodeTreeKind.STRING, null, init); + } + } + + public CodeTreeBuilder createInitBuilder() { + CodeTreeBuilder builder = new CodeTreeBuilder(); + init = builder.getTree(); + init.setEnclosingElement(this); + return builder; + } + + public void setInit(CodeTree init) { + this.init = init; + } + + public CodeTree getInit() { + return init; + } + + public Name getSimpleName() { + return name; + } + + public TypeMirror getType() { + return type; + } + + @Override + public TypeMirror asType() { + return type; + } + + @Override + public ElementKind getKind() { + if (getEnclosingElement() instanceof ExecutableElement) { + return ElementKind.PARAMETER; + } else if (getEnclosingElement() instanceof TypeElement) { + return ElementKind.FIELD; + } else { + return ElementKind.PARAMETER; + } + } + + public void setConstantValue(Object constantValue) { + this.constantValue = constantValue; + } + + @Override + public Object getConstantValue() { + return constantValue; + } + + public String getName() { + return getSimpleName().toString(); + } + + @Override + public void setSimpleName(Name name) { + this.name = name; + } + + public void setName(String name) { + this.name = CodeNames.of(name); + } + + @Override + public void setType(TypeMirror type) { + this.type = type; + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitVariable(this, p); + } + + public static CodeVariableElement clone(VariableElement var) { + CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString()); + copy.setConstantValue(var.getConstantValue()); + for (AnnotationMirror mirror : var.getAnnotationMirrors()) { + copy.addAnnotationMirror(mirror); + } + for (Element element : var.getEnclosedElements()) { + copy.add(element); + } + return copy; + } + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/GeneratedElement.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/GeneratedElement.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,36 @@ +/* + * 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; + +import javax.lang.model.element.*; + + +public interface GeneratedElement { + + AnnotationMirror getGeneratorAnnotationMirror(); + void setGeneratorAnnotationMirror(AnnotationMirror mirror); + + Element getGeneratorElement(); + void setGeneratorElement(Element element); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,608 @@ +/* + * 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.codewriter; + +import static com.oracle.truffle.codegen.processor.Utils.*; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; + +public abstract class AbstractCodeWriter extends CodeElementScanner { + + protected Writer writer; + private int indent; + private boolean newLine; + + private OrganizedImports imports; + + public void visitCompilationUnit(CodeCompilationUnit e) { + for (TypeElement clazz : e.getEnclosedElements()) { + clazz.accept(this, null); + } + } + + protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException; + + @Override + public Void visitType(CodeTypeElement e, Void p) { + if (e.isTopLevelClass()) { + Writer w = null; + try { + imports = OrganizedImports.organize(e); + + w = createWriter(e); + writer = w; + writeRootClass(e); + } catch (IOException ex) { + throw new RuntimeException(ex); + } finally { + if (w != null) { + try { + w.close(); + } catch (Throwable e1) { + // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378 + // TODO temporary suppress errors on close. + } + } + writer = null; + } + } else { + writeClassImpl(e); + } + return null; + } + + private void writeRootClass(CodeTypeElement e) { + writeHeader(); + write("package ").write(e.getPackageName()).write(";").writeLn(); + writeEmptyLn(); + + Set generateImports = imports.generateImports(); + List typeImports = new ArrayList<>(); + List staticImports = new ArrayList<>(); + + for (CodeImport codeImport : generateImports) { + if (codeImport.isStaticImport()) { + staticImports.add(codeImport); + } else { + typeImports.add(codeImport); + } + } + Collections.sort(typeImports); + Collections.sort(staticImports); + + for (CodeImport imp : staticImports) { + imp.accept(this, null); + writeLn(); + } + if (!staticImports.isEmpty()) { + writeEmptyLn(); + } + + for (CodeImport imp : typeImports) { + imp.accept(this, null); + writeLn(); + } + if (!typeImports.isEmpty()) { + writeEmptyLn(); + } + + writeClassImpl(e); + } + + private void writeClassImpl(CodeTypeElement e) { + for (AnnotationMirror annotation : e.getAnnotationMirrors()) { + visitAnnotation(annotation); + writeLn(); + } + + writeModifiers(e.getModifiers()); + if (e.getKind() == ElementKind.ENUM) { + write("enum "); + } else { + write("class "); + } + write(e.getSimpleName()); + if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) { + write(" extends ").write(typeSimpleName(e.getSuperclass())); + } + if (e.getImplements().size() > 0) { + write(" implements "); + for (int i = 0; i < e.getImplements().size(); i++) { + write(typeSimpleName(e.getImplements().get(i))); + if (i < e.getImplements().size() - 1) { + write(", "); + } + } + } + + write(" {").writeLn(); + writeEmptyLn(); + indent(); + + List staticFields = getStaticFields(e); + List instanceFields = getInstanceFields(e); + + for (int i = 0; i < staticFields.size(); i++) { + VariableElement field = staticFields.get(i); + field.accept(this, null); + if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) { + write(","); + writeLn(); + } else { + write(";"); + writeLn(); + } + } + + if (staticFields.size() > 0) { + writeEmptyLn(); + } + + for (VariableElement field : instanceFields) { + field.accept(this, null); + write(";"); + writeLn(); + } + if (instanceFields.size() > 0) { + writeEmptyLn(); + } + + for (ExecutableElement method : getInstanceMethods(e)) { + method.accept(this, null); + } + + for (ExecutableElement method : getStaticMethods(e)) { + method.accept(this, null); + } + + for (TypeElement clazz : e.getInnerClasses()) { + clazz.accept(this, null); + } + + dedent(); + write("}"); + writeEmptyLn(); + } + + private static List getStaticFields(CodeTypeElement clazz) { + List staticFields = new ArrayList<>(); + for (VariableElement field : clazz.getFields()) { + if (field.getModifiers().contains(Modifier.STATIC)) { + staticFields.add(field); + } + } + return staticFields; + } + + private static List getInstanceFields(CodeTypeElement clazz) { + List instanceFields = new ArrayList<>(); + for (VariableElement field : clazz.getFields()) { + if (!field.getModifiers().contains(Modifier.STATIC)) { + instanceFields.add(field); + } + } + return instanceFields; + } + + private static List getStaticMethods(CodeTypeElement clazz) { + List staticMethods = new ArrayList<>(); + for (ExecutableElement method : clazz.getMethods()) { + if (method.getModifiers().contains(Modifier.STATIC)) { + staticMethods.add(method); + } + } + return staticMethods; + } + + private static List getInstanceMethods(CodeTypeElement clazz) { + List instanceMethods = new ArrayList<>(); + for (ExecutableElement method : clazz.getMethods()) { + if (!method.getModifiers().contains(Modifier.STATIC)) { + instanceMethods.add(method); + } + } + return instanceMethods; + } + + @Override + public Void visitVariable(VariableElement f, Void p) { + Element parent = f.getEnclosingElement(); + + for (AnnotationMirror annotation : f.getAnnotationMirrors()) { + visitAnnotation(annotation); + writeLn(); + } + + CodeTree init = null; + if (f instanceof CodeVariableElement) { + init = ((CodeVariableElement) f).getInit(); + } + + + if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) { + write(f.getSimpleName()); + if (init != null) { + if (init != null) { + write("("); + init.acceptCodeElementScanner(this, p); + write(")"); + } + } + } else { + writeModifiers(f.getModifiers()); + write(typeSimpleName(f.asType())); + write(" "); + write(f.getSimpleName()); + if (init != null) { + write(" = "); + init.acceptCodeElementScanner(this, p); + } + } + return null; + } + + public void visitAnnotation(AnnotationMirror e) { + write("@").write(typeSimpleName(e.getAnnotationType())); + + if (!e.getElementValues().isEmpty()) { + write("("); + final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value"); + + Map values = e.getElementValues(); + if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) { + visitAnnotationValue(values.get(defaultElement)); + } else { + Set methodsSet = values.keySet(); + List methodsList = new ArrayList<>(); + for (ExecutableElement method : methodsSet) { + if (values.get(method) == null) { + continue; + } + methodsList.add(method); + } + + Collections.sort(methodsList, new Comparator() { + @Override + public int compare(ExecutableElement o1, ExecutableElement o2) { + return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString()); + } + }); + + for (int i = 0; i < methodsList.size(); i++) { + ExecutableElement method = methodsList.get(i); + AnnotationValue value = values.get(method); + write(method.getSimpleName().toString()); + write(" = "); + visitAnnotationValue(value); + + if (i < methodsList.size() - 1) { + write(", "); + } + } + } + + write(")"); + } + } + + public void visitAnnotationValue(AnnotationValue e) { + e.accept(new AnnotationValueWriterVisitor(), null); + } + + private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7 { + @Override + public Void visitBoolean(boolean b, Void p) { + write(Boolean.toString(b)); + return null; + } + @Override + public Void visitByte(byte b, Void p) { + write(Byte.toString(b)); + return null; + } + @Override + public Void visitChar(char c, Void p) { + write(Character.toString(c)); + return null; + } + @Override + public Void visitDouble(double d, Void p) { + write(Double.toString(d)); + return null; + } + @Override + public Void visitFloat(float f, Void p) { + write(Float.toString(f)); + return null; + } + @Override + public Void visitInt(int i, Void p) { + write(Integer.toString(i)); + return null; + } + @Override + public Void visitLong(long i, Void p) { + write(Long.toString(i)); + return null; + } + @Override + public Void visitShort(short s, Void p) { + write(Short.toString(s)); + return null; + } + @Override + public Void visitString(String s, Void p) { + write("\""); + write(s); + write("\""); + return null; + } + @Override + public Void visitType(TypeMirror t, Void p) { + write(typeSimpleName(t)); + write(".class"); + return null; + } + @Override + public Void visitEnumConstant(VariableElement c, Void p) { + write(typeSimpleName(c.asType())); + write("."); + write(c.getSimpleName().toString()); + return null; + } + @Override + public Void visitAnnotation(AnnotationMirror a, Void p) { + AbstractCodeWriter.this.visitAnnotation(a); + return null; + } + @Override + public Void visitArray(List< ? extends AnnotationValue> vals, Void p) { + write("{"); + for (int i = 0; i < vals.size(); i++) { + AnnotationValue value = vals.get(i); + AbstractCodeWriter.this.visitAnnotationValue(value); + if (i < vals.size() - 1) { + write(", "); + } + } + write("}"); + return null; + } + } + + public ExecutableElement findExecutableElement(DeclaredType type, String name) { + List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); + for (ExecutableElement executableElement : elements) { + if (executableElement.getSimpleName().toString().equals(name)) { + return executableElement; + } + } + return null; + } + + @Override + public void visitImport(CodeImport e, Void p) { + if (e.isStaticImport()) { + write("import static ").write(e.getImportString()).write(";"); + } else { + write("import ").write(e.getImportString()).write(";"); + } + } + +// @Override +// public void visitParameter(CodeVariableElement e) { +// for (CodeAnnotationMirror annotation : e.getAnnotationMirrors()) { +// annotation.accept(this); +// } +// write(typeSimpleName(e.getType())); +// write(" "); +// write(e.getSimpleName()); +// } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + for (AnnotationMirror annotation : e.getAnnotationMirrors()) { + visitAnnotation(annotation); + writeLn(); + } + + writeModifiers(e.getModifiers()); + + if (e.getReturnType() != null) { + write(typeSimpleName(e.getReturnType())); + write(" "); + } + write(e.getSimpleName()); + write("("); + + for (int i = 0; i < e.getParameters().size(); i++) { + VariableElement param = e.getParameters().get(i); + param.accept(this, p); + if (i < e.getParameters().size() - 1) { + write(", "); + } + } + write(")"); + + List throwables = e.getThrownTypes(); + if (throwables.size() > 0) { + write(" throws "); + for (int i = 0; i < throwables.size(); i++) { + write(typeSimpleName(throwables.get(i))); + if (i < throwables.size() - 1) { + write(", "); + } + } + } + + if (e.getModifiers().contains(Modifier.ABSTRACT)) { + writeLn(";"); + } else if (e.getBodyTree() != null) { + writeLn(" {"); + indent(); + e.getBodyTree().acceptCodeElementScanner(this, p); + dedent(); + writeLn("}"); + } else if (e.getBody() != null) { + write(" {"); + write(e.getBody()); + writeLn("}"); + } else { + writeLn("{ }"); + } + writeEmptyLn(); + return null; + } + + @Override + public void visitTree(CodeTree e, Void p) { + CodeTreeKind kind = e.getCodeKind(); + + switch (kind) { + case COMMA_GROUP: + List children = e.getEnclosedElements(); + for (int i = 0; i < children.size(); i++) { + children.get(i).acceptCodeElementScanner(this, p); + if (i < e.getEnclosedElements().size() - 1) { + write(", "); + } + } + break; + case GROUP: + for (CodeTree tree : e.getEnclosedElements()) { + tree.acceptCodeElementScanner(this, p); + } + break; + case INDENT: + indent(); + for (CodeTree tree : e.getEnclosedElements()) { + tree.acceptCodeElementScanner(this, p); + } + dedent(); + break; + case NEW_LINE: + writeLn(); + break; + case STRING: + if (e.getString() != null) { + write(e.getString()); + } else { + write("null"); + } + break; + case STATIC_FIELD_REFERENCE: + if (e.getString() != null) { + write(imports.useStaticFieldImport(e.getType(), e.getString())); + } else { + write("null"); + } + break; + case STATIC_METHOD_REFERENCE: + if (e.getString() != null) { + write(imports.useStaticMethodImport(e.getType(), e.getString())); + } else { + write("null"); + } + break; + case TYPE: + write(imports.useImport(e.getType())); + break; + default: + assert false; + return; + } + } + + private static String typeSimpleName(TypeMirror type) { + return Utils.getSimpleName(type); + } + + protected void writeHeader() { + // default implementation does nothing + } + + private void writeModifiers(Set modifiers) { + if (modifiers != null) { + for (Modifier modifier : modifiers) { + write(modifier.toString()); + write(" "); + } + } + } + + private static final String LN = "\n"; + + protected void indent() { + indent++; + } + + protected void dedent() { + indent--; + } + + protected void writeLn() { + write(LN); + newLine = true; + } + + protected void writeLn(String text) { + write(text); + write(LN); + newLine = true; + } + + protected void writeEmptyLn() { + writeLn(); + } + + private AbstractCodeWriter write(Name name) { + return write(name.toString()); + } + + private AbstractCodeWriter write(String m) { + try { + if (newLine && m != LN) { + writeIndent(); + newLine = false; + } + writer.write(m); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + private void writeIndent() throws IOException { + for (int i = 0; i < indent; i++) { + writer.write(" "); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/FixWarningsVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/FixWarningsVisitor.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,130 @@ +/* + * 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.codewriter; + +import static com.oracle.truffle.codegen.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; + + +public class FixWarningsVisitor extends CodeElementScanner{ + + + private final Set symbolsUsed = new HashSet<>(); + + private final ProcessorContext context; + private final DeclaredType unusedAnnotation; + private final DeclaredType overrideType; + + public FixWarningsVisitor(ProcessorContext context, DeclaredType unusedAnnotation, DeclaredType overrideType) { + this.context = context; + this.unusedAnnotation = unusedAnnotation; + this.overrideType = overrideType; + } + + @Override + public Void visitType(CodeTypeElement e, Void p) { + List superTypes = Utils.getSuperTypes(e); + for (TypeElement type : superTypes) { + String qualifiedName = Utils.getQualifiedName(type); + if (qualifiedName.equals(Serializable.class.getCanonicalName())) { + if (!e.containsField("serialVersionUID")) { + e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), context.getType(long.class), "serialVersionUID", "1L")); + } + break; + } + } + + return super.visitType(e, p); + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + if (e.getParameters().isEmpty()) { + return null; + } else if (e.getModifiers().contains(Modifier.ABSTRACT)) { + return null; + } else if (containsOverride(e)) { + return null; + } + + symbolsUsed.clear(); + super.visitExecutable(e, p); + if (e.getBodyTree() == null && e.getBody() != null) { + computeSymbols(e.getBody()); + } + + for (VariableElement parameter : e.getParameters()) { + if (!symbolsUsed.contains(parameter.getSimpleName().toString())) { + e.getAnnotationMirrors().add(createUnusedAnnotationMirror()); + break; + } + } + return null; + } + + private boolean containsOverride(CodeExecutableElement e) { + for (AnnotationMirror mirror : e.getAnnotationMirrors()) { + if (Utils.typeEquals(overrideType, mirror.getAnnotationType())) { + return true; + } + } + return false; + } + + private CodeAnnotationMirror createUnusedAnnotationMirror() { + CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation); + mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused")); + return mirror; + } + + @Override + public void visitTree(CodeTree e, Void p) { + if (e.getString() != null) { + computeSymbols(e.getString()); + } + super.visitTree(e, p); + } + + private void computeSymbols(String s) { + // TODO there should not be any need for a StringTokenizer if we have a real AST for + // method bodies. Also the current solution is not perfect. What if one token + // is spread across multiple CodeTree instances? But for now that works. + StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false); + while (tokenizer.hasMoreElements()) { + String token = tokenizer.nextToken().trim(); + if (token.length() > 0) { + symbolsUsed.add(token); + } + } + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/GenerateOverrideVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/GenerateOverrideVisitor.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.codewriter; + +import static com.oracle.truffle.codegen.processor.Utils.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.ast.*; + +public class GenerateOverrideVisitor extends CodeElementScanner { + + private final DeclaredType overrideType; + + public GenerateOverrideVisitor(DeclaredType overrideType) { + this.overrideType = overrideType; + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) { + String name = e.getSimpleName().toString(); + TypeMirror[] params = e.getParameterTypes(); + + if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) { + e.addAnnotationMirror(new CodeAnnotationMirror(overrideType)); + } + } + return super.visitExecutable(e, p); + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,377 @@ +/* + * 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.codewriter; + +import static com.oracle.truffle.codegen.processor.Utils.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; + +public final class OrganizedImports { + + private final Map importUsage = new HashMap<>(); + private final Map staticImportUsage = new HashMap<>(); + + private final Map simpleNamesUsed = new HashMap<>(); + + private final Set declaredStaticMethods = new HashSet<>(); + private final Set declaredStaticFields = new HashSet<>(); + private final Set ambiguousStaticMethods = new HashSet<>(); + private final Set ambiguousStaticFields = new HashSet<>(); + + private final CodeTypeElement topLevelClass; + + private OrganizedImports(CodeTypeElement topLevelClass) { + this.topLevelClass = topLevelClass; + } + + 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); + return organized; + } + + public String useImport(TypeMirror type) { + String simpleName = getSimpleName(type); + TypeMirror usedByType = simpleNamesUsed.get(type); + if (usedByType == null) { + simpleNamesUsed.put(simpleName, type); + usedByType = type; + } else if (!typeEquals(type, usedByType)) { + // we need a qualified name + return getQualifiedName(type); + } + + // we can use the simple name + addUsage(type, importUsage); + return simpleName; + } + + 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())); + + 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()); + for (ExecutableElement method : methods) { + if (method.getModifiers().contains(Modifier.STATIC)) { + importedMethods.add(method.getSimpleName().toString()); + } + } + + boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods); + + Set importedFields = new HashSet<>(); + List fields = ElementFilter.fieldsIn(element.getEnclosedElements()); + for (VariableElement field : fields) { + if (field.getModifiers().contains(Modifier.STATIC)) { + importedFields.add(field.getSimpleName().toString()); + } + } + + boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields); + + return allMethodsAmbiguous && allFieldsAmbiguous; + } + + private static boolean processStaticImportElements(Set newElements, Set ambiguousElements, Set declaredElements) { + boolean allAmbiguous = false; + if (declaredElements.containsAll(newElements)) { + // all types already declared -> we can remove the import completely -> they will all get ambiguous + allAmbiguous = true; + } + Set newAmbiguous = new HashSet<>(); + Set newDeclared = new HashSet<>(); + + for (String newElement : newElements) { + if (declaredElements.contains(newElement)) { + newAmbiguous.add(newElement); + } else if (ambiguousElements.contains(newElement)) { + // nothing to do + } else { + newDeclared.add(newElement); + } + } + + ambiguousElements.addAll(newAmbiguous); + declaredElements.addAll(newDeclared); + return allAmbiguous; + } + + private static Set generateImports(CodeTypeElement e, Set toGenerate) { + Set autoImportedTypes = new HashSet<>(); + + // if type is declared inside a super type of this class -> no import + collectSuperTypeImports(e, autoImportedTypes); + collectInnerTypeImports(e, autoImportedTypes); + + 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))) { + 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; + } + + private static void collectInnerTypeImports(TypeElement e, Set autoImportedTypes) { + for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) { + collectSuperTypeImports(innerClass, autoImportedTypes); + collectInnerTypeImports(innerClass, autoImportedTypes); + } + } + + private static void collectSuperTypeImports(TypeElement e, Set autoImportedTypes) { + List superTypes = getSuperTypes(e); + for (TypeElement superType : superTypes) { + List declaredTypes = getDeclaredTypes(superType); + for (TypeElement declaredType : declaredTypes) { + autoImportedTypes.add(getQualifiedName(declaredType)); + } + } + } + + private static Set generateStaticImports(CodeTypeElement e, 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)); + + TreeSet importObjects = new TreeSet<>(); + for (TypeMirror importType : toGenerate) { + if (getPackageName(importType) == null) { + continue; // no package name -> no import + } + + String qualifiedName = getQualifiedName(importType); + if (autoImportedStaticTypes.contains(qualifiedName)) { + continue; + } + + importObjects.add(new CodeImport(importType, qualifiedName + ".*", true)); + } + + 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<>(); + + @Override + public void visitTree(CodeTree e, Void p) { + if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { + addStaticImport(e.getType()); + } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { + addStaticImport(e.getType()); + } else { + addImport(e.getType()); + } + super.visitTree(e, p); + } + + @Override + public Void visitExecutable(CodeExecutableElement e, Void p) { + visitAnnotations(e.getAnnotationMirrors()); + if (e.getReturnType() != null) { + addImport(e.getReturnType()); + } + for (TypeMirror type : e.getThrownTypes()) { + addImport(type); + } + return super.visitExecutable(e, p); + } + + @Override + public Void visitType(CodeTypeElement e, Void p) { + visitAnnotations(e.getAnnotationMirrors()); + + addImport(e.getSuperclass()); + for (TypeMirror type : e.getImplements()) { + addImport(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) { + for (AnnotationMirror mirror : mirrors) { + visitAnnotation(mirror); + } + } + + public void visitAnnotation(AnnotationMirror e) { + addImport(e.getAnnotationType()); + } + + @Override + public void visitImport(CodeImport e, Void p) { + } + + private void addStaticImport(TypeMirror type) { + addUsage(type, staticTypeReferences); + } + + private void addImport(TypeMirror type) { + addUsage(type, typeReferences); + } + + } + + 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 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/AbstractCompiler.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,66 @@ +/* + * 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.compiler; + +import java.lang.reflect.*; + + +public abstract class AbstractCompiler implements Compiler { + + + protected static Object method(Object o, String methodName) throws Exception { + Method method = o.getClass().getMethod(methodName); + method.setAccessible(true); + return method.invoke(o); + } + + protected static Object method(Object o, String methodName, Class[] paramTypes, Object ... values) throws Exception { + Method method = o.getClass().getMethod(methodName, paramTypes); + method.setAccessible(true); + return method.invoke(o, values); + } + + protected static Object field(Object o, String fieldName) throws Exception { + Field field = o.getClass().getField(fieldName); + field.setAccessible(true); + return field.get(o); + } + + protected static String parseHeader(String content) { + int index = content.indexOf("/*"); + if (index == -1) { + return null; + } + if (!content.substring(0, index).trim().equals("")) { + // just whitespace before + return null; + } + + int endIndex = content.indexOf("*/", index); + if (endIndex == -1) { + return null; + } + return content.substring(index, endIndex + 2); + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/Compiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/Compiler.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,35 @@ +/* + * 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.compiler; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + + +public interface Compiler { + + String getMethodBody(ProcessingEnvironment env, ExecutableElement method); + + String getHeaderComment(ProcessingEnvironment env, Element type); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/CompilerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/CompilerFactory.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,50 @@ +/* + * 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.compiler; + +import javax.lang.model.element.*; + +public class CompilerFactory { + + private static Compiler javac; + private static Compiler jdt; + + public static Compiler getCompiler(Element currentElement) { + if (JavaCCompiler.isValidElement(currentElement)) { + if (javac == null) { + javac = new JavaCCompiler(); + } + return javac; + } else if (JDTCompiler.isValidElement(currentElement)) { + if (jdt == null) { + jdt = new JDTCompiler(); + } + return jdt; + } else { + throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + "."); + } + } + + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JDTCompiler.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,113 @@ +/* + * 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.compiler; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.*; + +public class JDTCompiler extends AbstractCompiler { + + public static boolean isValidElement(Element currentElement) { + try { + Class elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl"); + return elementClass.isAssignableFrom(currentElement.getClass()); + } catch (ClassNotFoundException e) { + return false; + } + } + + @Override + public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + try { + + char[] source = getSource(method); + if (source == null) { + return null; + } + + /* + AbstractMethodDeclaration decl = ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); + int bodyStart = decl.bodyStart; + int bodyEnd = decl.bodyEnd; + */ + Object decl = method(field(method, "_binding"), "sourceMethod"); + int bodyStart = (int) field(decl, "bodyStart"); + int bodyEnd = (int) field(decl, "bodyEnd"); + + int length = bodyEnd - bodyStart; + char[] target = new char[length]; + System.arraycopy(source, bodyStart, target, 0, length); + + return new String(target); + } catch (Exception e) { + return Utils.printException(e); + } + } + + + private static char[] getSource(Element element) throws Exception { + /* + Binding binding = ((ElementImpl)element)._binding; + char[] source = null; + if (binding instanceof MethodBinding) { + source = ((MethodBinding) binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); + } else if (binding instanceof SourceTypeBinding) { + source = ((SourceTypeBinding)binding).scope.referenceContext.compilationResult.compilationUnit.getContents(); + } + return source; + */ + + Object binding = field(element, "_binding"); + Class methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding"); + Class referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); + + char[] source = null; + if (methodBindingClass.isAssignableFrom(binding.getClass())) { + Object sourceMethod = method(binding, "sourceMethod"); + if (sourceMethod == null) { + return null; + } + source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents"); + } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) { + source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents"); + } + return source; + } + + + @Override + public String getHeaderComment(ProcessingEnvironment env, Element type) { + try { + char[] source = getSource(type); + if (source == null) { + return null; + } + return parseHeader(new String(source)); + } catch (Exception e) { + return Utils.printException(e); + } + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/compiler/JavaCCompiler.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,95 @@ +/* + * 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.compiler; + +import javax.annotation.processing.*; +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.*; + + +public class JavaCCompiler extends AbstractCompiler { + + public static boolean isValidElement(Element currentElement) { + try { + Class elementClass = Class.forName("com.sun.tools.javac.code.Symbol"); + return elementClass.isAssignableFrom(currentElement.getClass()); + } catch (ClassNotFoundException e) { + return false; + } + } + + private static final Class[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class}; + private static final Class[] getCharContentSignature = new Class[]{boolean.class}; + + @Override + public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { + try { + /* + if (false) { + Pair treeAndTopLevel = ((JavacElements) env.getElementUtils()).getTreeAndTopLevel(method, null, null); + JCBlock block = ((JCMethodDecl) treeAndTopLevel.fst).getBody(); + int startPos = block.pos; + int endPos = block.endpos; + String methodBody = treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1, endPos).toString(); + return methodBody; + } + */ + + Object treeAndTopLevel = getTreeAndTopLevel(env, method); + Object block = method(field(treeAndTopLevel, "fst"), "getBody"); + int startPos = (int) field(block, "pos"); + int endPos = (int) field(block, "endpos"); + return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString(); + } catch (Exception e) { + return Utils.printException(e); + } + } + + private static CharSequence getContent(Object treeAndTopLevel) throws Exception { + /* + * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true); + */ + return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true); + } + + private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception { + /* + * Pair treeAndTopLevel = ((JavacElements) env.getElementUtils()).getTreeAndTopLevel(method, null, null); + */ + return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null); + } + + @Override + public String getHeaderComment(ProcessingEnvironment env, Element type) { + try { + String content = getContent(getTreeAndTopLevel(env, type)).toString(); + return parseHeader(content); + } catch (Exception e) { + return Utils.printException(e); + } + } + + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionCodeElementFactory.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,95 @@ +/* + * 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.ext; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.api.element.*; +import com.oracle.truffle.codegen.processor.ast.*; + + +final class ExtensionCodeElementFactory implements WritableElementFactory { + + private final ProcessorContext context; + + Element generatorElement; + AnnotationMirror generatorAnnotationMirror; + + public ExtensionCodeElementFactory(ProcessorContext context) { + this.context = context; + } + + @Override + public WritableExecutableElement cloneExecutableElement(ExecutableElement method) { + return updateGenerators(CodeExecutableElement.clone(context.getEnvironment(), method)); + } + + @Override + public WritableVariableElement cloneVariableElement(VariableElement var) { + return updateGenerators(CodeVariableElement.clone(var)); + } + + @Override + public WritableAnnotationMirror cloneAnnotationMirror(AnnotationMirror mirror) { + return CodeAnnotationMirror.clone(mirror); + } + + @Override + public WritableVariableElement createParameter(TypeMirror type, String simpleName) { + return updateGenerators(new CodeVariableElement(Utils.modifiers(), type, simpleName)); + } + + @Override + public WritableExecutableElement createExecutableElement(TypeMirror returnType, String methodName) { + return updateGenerators(new CodeExecutableElement(returnType, methodName)); + } + + @Override + public TypeMirror createTypeMirror(Class javaClass) { + return context.getType(javaClass); + } + + @Override + public WritableAnnotationMirror createAnnotationMirror(DeclaredType typeMirror) { + return new CodeAnnotationMirror(typeMirror); + } + + @Override + public Name createName(String name) { + return CodeNames.of(name); + } + + @Override + public AnnotationValue createAnnotationValue(Object value) { + return new CodeAnnotationValue(value); + } + + private E updateGenerators(E element) { + element.setGeneratorElement(generatorElement); + element.setGeneratorAnnotationMirror(generatorAnnotationMirror); + return element; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionContextImpl.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,79 @@ +/* + * 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.ext; + +import java.util.*; + +import javax.annotation.processing.*; + +import com.oracle.truffle.codegen.processor.api.*; +import com.oracle.truffle.codegen.processor.api.element.*; + + +public class ExtensionContextImpl implements ExtensionContext { + + private final ProcessingEnvironment env; + private final RoundEnvironment round; + private final WritableElementFactory factory; + + private final List elements = new ArrayList<>(); + + public ExtensionContextImpl(ProcessingEnvironment env, RoundEnvironment round, WritableElementFactory factory) { + this.env = env; + this.round = round; + this.factory = factory; + } + + + List returnElements() { + List returnElements = new ArrayList<>(this.elements); + this.elements.clear(); + return returnElements; + } + + @Override + public ProcessingEnvironment getProcessingEnvironment() { + return env; + } + + @Override + public RoundEnvironment getRoundEnvironment() { + return round; + } + + @Override + public WritableElementFactory getElementFactory() { + return factory; + } + + @Override + public void addGeneratedElement(WritableElement element) { + elements.add(element); + } + + @Override + public void removeGeneratedElement(WritableElement element) { + elements.remove(element); + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ext/ExtensionParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -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.ext; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.api.*; +import com.oracle.truffle.codegen.processor.api.element.*; + + +public class ExtensionParser { + + private final Map extensions = new HashMap<>(); + private final ProcessorContext context; + private final ExtensionCodeElementFactory factory; + private final ExtensionContextImpl extensionContext; + + public ExtensionParser(ProcessorContext context) { + this.context = context; + this.factory = new ExtensionCodeElementFactory(context); + this.extensionContext = new ExtensionContextImpl(context.getEnvironment(), null, factory); + } + + public List parseAll(TypeElement typeElement) { + List generatedMethods = new ArrayList<>(); + parseElement(generatedMethods, typeElement); + + List methods = ElementFilter.methodsIn(typeElement.getEnclosedElements()); + for (ExecutableElement method : methods) { + for (VariableElement var : method.getParameters()) { + parseElement(generatedMethods, var); + } + parseElement(generatedMethods, method); + } + + return generatedMethods; + } + + private void parseElement(List elements, Element element) { + List mirrors = element.getAnnotationMirrors(); + for (AnnotationMirror mirror : mirrors) { + ExtensionProcessor processor = findProcessor(element, mirror); + if (processor != null) { + try { + factory.generatorAnnotationMirror = mirror; + factory.generatorElement = element; + processor.process(extensionContext, mirror, element); + elements.addAll(extensionContext.returnElements()); + } catch (Throwable e) { + context.getLog().error(element, mirror, "Processor for '%s' failed with exception: \n\n%s.", Utils.getQualifiedName(mirror.getAnnotationType()), Utils.printException(e)); + } finally { + factory.generatorAnnotationMirror = null; + factory.generatorElement = null; + } + } + } + } + + private ExtensionProcessor findProcessor(Element element, AnnotationMirror mirror) { + String processorName = Utils.getQualifiedName(mirror.getAnnotationType()); + ExtensionProcessor processor = null; + if (extensions.containsKey(processorName)) { + processor = extensions.get(processorName); + } else { + AnnotationMirror foundExtension = Utils.findAnnotationMirror(context.getEnvironment(), mirror.getAnnotationType().asElement(), ExtensionAnnotation.class); + if (foundExtension != null) { + String className = Utils.getAnnotationValueString(foundExtension, "processorClassName"); + Class processorClass; + try { + processorClass = Class.forName(className); + } catch (ClassNotFoundException e) { + context.getLog().error(element, mirror, "Could not find processor class '%s' configured in '@%s'.", className, processorName); + return null; + } + try { + processor = (ExtensionProcessor) processorClass.newInstance(); + } catch (InstantiationException e) { + context.getLog().error(element, mirror, "Could not instantiate processor class '%s' configured in '@%s'.", className, processorName); + return null; + } catch (IllegalAccessException e) { + context.getLog().error(element, mirror, "Could not access processor class '%s' configured in '@%s'.", className, processorName); + return null; + } catch (ClassCastException e) { + context.getLog().error(element, mirror, "Processor class '%s' configured in '@%s' does not implement '%s'.", className, processorName, ExtensionProcessor.class.getName()); + return null; + } + } + extensions.put(processorName, processor); + } + return processor; + } + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/GenericParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/GenericParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import java.lang.annotation.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + +public class GenericParser extends OperationMethodParser { + + public GenericParser(ProcessorContext context, OperationData operation) { + super(context, operation); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + return createDefaultMethodSpec(null); + } + + @Override + protected ParameterSpec createValueParameterSpec(String valueName) { + return new ParameterSpec(valueName, getOperation().getTypeSystem().getGenericType(), Kind.EXECUTE, false); + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("returnValue", getOperation().getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE); + } + + @Override + public SpecializationData create(TemplateMethod method) { + return new SpecializationData(method, true, false); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return Generic.class; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationCodeGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationCodeGenerator.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,903 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import static com.oracle.truffle.codegen.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; +import com.oracle.truffle.codegen.processor.typesystem.*; + +public class OperationCodeGenerator extends CompilationUnitFactory { + + private static final String OPERATION_FIELD_NAME = "operation"; + + public OperationCodeGenerator(ProcessorContext context) { + super(context); + } + + private TypeMirror getUnexpectedValueException() { + return getContext().getTruffleTypes().getUnexpectedValueException(); + } + + private static String operationClassName(OperationData operation) { + return Utils.getSimpleName(operation.getTemplateType().asType()); + } + + private static String factoryClassName(OperationData operation) { + return operationClassName(operation) + "Factory"; + } + + private static String nodeClassName(OperationData operation) { + String name = operationClassName(operation); + if (name.length() > 2 && name.endsWith("Op")) { + name = name.substring(0, name.length() - 2); + } + return name + "Node"; + } + + private static String nodeClassName(SpecializationData specialization) { + String name = ""; + if (specialization.getOperation().getAllMethods().length > 1) { + name = specialization.getMethodName(); + if (name.startsWith("do")) { + name = name.substring(2); + } + } + return name + nodeClassName(specialization.getOperation()); + } + + private static String nodeVariableName(ParameterSpec spec) { + if (spec.getKind() == Kind.EXECUTE) { + return spec.getName() + "Node"; + } + return spec.getName(); + } + + private static String nodeVariableName(ActualParameter param) { + return nodeVariableName(param.getSpecification()); + } + + private static String valueVariableName(ParameterSpec spec) { + if (spec.getKind() == Kind.EXECUTE) { + return spec.getName() + "Value"; + } + return spec.getName(); + } + + private static String valueVariableName(ActualParameter param) { + return valueVariableName(param.getSpecification()); + } + + public static String executeMethodName(TypeData type) { + if (type.isGeneric()) { + return "executeGeneric"; + } + return "execute" + Utils.getSimpleName(type.getBoxedType()); + } + + private static EnumSet kinds(Kind... values) { + EnumSet result = EnumSet.noneOf(Kind.class); + for (Kind value : values) { + result.add(value); + } + return result; + } + + private static void addNodeParameters(CodeExecutableElement method, OperationData operation, EnumSet included) { + for (ParameterSpec spec : operation.getSpecification().getParameters()) { + if (included.contains(spec.getKind())) { + if (spec.getKind() == Kind.EXECUTE) { + method.addParameter(new CodeVariableElement(operation.getTypeSystem().getNodeType(), nodeVariableName(spec))); + } else { + method.addParameter(new CodeVariableElement(spec.getValueType(), nodeVariableName(spec))); + } + } + } + if (included.contains(Kind.CONSTRUCTOR_FIELD)) { + for (OperationFieldData field : operation.getConstructorFields()) { + method.addParameter(new CodeVariableElement(field.getJavaClass(), field.getName())); + } + } + } + + private static void addValueParameters(CodeExecutableElement method, OperationData operation, EnumSet included) { + for (ParameterSpec spec : operation.getSpecification().getParameters()) { + if (included.contains(spec.getKind())) { + method.addParameter(new CodeVariableElement(spec.getValueType(), valueVariableName(spec))); + } + } + if (included.contains(Kind.CONSTRUCTOR_FIELD)) { + for (OperationFieldData field : operation.getConstructorFields()) { + method.addParameter(new CodeVariableElement(field.getJavaClass(), field.getName())); + } + } + } + + private static void addOperationFieldName(CodeTreeBuilder body, OperationData operation) { + if (!operation.isUseSingleton()) { + body.string(OPERATION_FIELD_NAME); + } + } + + private static void addOperationVariable(Set modifiers, Element element, OperationData operation, CodeTypeElement operationGen) { + if (!operation.isUseSingleton()) { + TypeMirror type = findOperationType(operation, operationGen); + if (element instanceof CodeExecutableElement) { + ((CodeExecutableElement) element).addParameter(new CodeVariableElement(modifiers, type, OPERATION_FIELD_NAME)); + } else if (element instanceof CodeTypeElement) { + ((CodeTypeElement) element).add(new CodeVariableElement(modifiers, type, OPERATION_FIELD_NAME)); + } + } + } + + private static void addNodeNames(CodeTreeBuilder body, OperationData operation, EnumSet included) { + for (ParameterSpec spec : operation.getSpecification().getParameters()) { + if (included.contains(spec.getKind())) { + body.string(nodeVariableName(spec)); + } + } + if (included.contains(Kind.CONSTRUCTOR_FIELD)) { + for (OperationFieldData field : operation.getConstructorFields()) { + body.string(field.getName()); + } + } + } + + private static void addValueNames(CodeTreeBuilder body, OperationData operation, EnumSet included) { + for (ParameterSpec spec : operation.getSpecification().getParameters()) { + if (included.contains(spec.getKind())) { + body.string(valueVariableName(spec)); + } + } + if (included.contains(Kind.CONSTRUCTOR_FIELD)) { + for (OperationFieldData field : operation.getConstructorFields()) { + body.string(field.getName()); + } + } + } + + private static void addValueNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData specialization, EnumSet included) { + for (ActualParameter spec : specialization.getParameters()) { + if (included.contains(spec.getSpecification().getKind())) { + TypeData typeData = spec.getActualTypeData(specialization.getOperation().getTypeSystem()); + if (typeData.isGeneric()) { + body.string(valueVariableName(spec)); + } else { + String methodName = TypeSystemCodeGenerator.asTypeMethodName(typeData); + startCallTypeSystemMethod(context, body, specialization.getOperation(), methodName); + body.string(valueVariableName(spec)); + body.end().end(); + } + } + } + } + + public static VariableElement findSingleton(ProcessorContext context, OperationData operation) { + TypeMirror type = context.findGeneratedClassBySimpleName(OperationCodeGenerator.genClassName(operation), operation); + return Utils.findDeclaredField(type, OperationCodeGenerator.singletonName(operation)); + } + + private static TypeMirror findOperationType(OperationData operation, CodeTypeElement operationGen) { + if (operation.hasExtensions()) { + // return generated type + return operationGen.asType(); + } else { + // return default type + return operation.getTemplateType().asType(); + } + } + + private static String genClassName(OperationData operation) { + String name = getSimpleName(operation.getTemplateType()); + return name + "Gen"; + } + + private static String singletonName(OperationData operation) { + return createConstantName(getSimpleName(operation.getTemplateType().asType())); + } + + private static void startCallOperationMethod(CodeTreeBuilder body, OperationData operation, TemplateMethod method) { + body.startGroup(); + + if (operation.isUseSingleton()) { + body.string(singletonName(operation)); + body.string(".").startCall(method.getMethodName()); + } else { + body.string(OPERATION_FIELD_NAME); + body.string("."); + body.startCall(method.getMethodName()); + } + } + + private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, OperationData operation, String methodName) { + VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, operation.getTypeSystem()); + assert singleton != null; + + body.startGroup(); + body.staticReference(singleton.getEnclosingElement().asType(), singleton.getSimpleName().toString()); + body.string(".").startCall(methodName); + } + + private static void emitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData specialization, boolean onSpecialization, boolean needsCast) { + // Implict guards based on method signature + String andOperator = prefix; + for (ActualParameter param : specialization.getParameters()) { + if (param.getSpecification().getKind() == Kind.EXECUTE && !param.getActualTypeData(specialization.getOperation().getTypeSystem()).isGeneric()) { + body.string(andOperator); + startCallTypeSystemMethod(context, body, specialization.getOperation(), + TypeSystemCodeGenerator.isTypeMethodName(param.getActualTypeData(specialization.getOperation().getTypeSystem()))); + body.string(valueVariableName(param)); + body.end().end(); // call + andOperator = " && "; + } + } + + if (specialization.getGuards().length > 0) { + // Explicitly specified guards + for (SpecializationGuardData guard : specialization.getGuards()) { + if ((guard.isOnSpecialization() && onSpecialization) + || (guard.isOnExecution() && !onSpecialization)) { + body.string(andOperator); + + if (guard.getGuardDeclaration().getOrigin() == specialization.getOperation()) { + startCallOperationMethod(body, specialization.getOperation(), guard.getGuardDeclaration()); + } else { + startCallTypeSystemMethod(context, body, specialization.getOperation(), guard.getGuardMethod()); + } + + if (needsCast) { + addValueNamesWithCasts(context, body, specialization, kinds(Kind.EXECUTE, Kind.SHORT_CIRCUIT)); + } else { + addValueNames(body, specialization.getOperation(), kinds(Kind.EXECUTE, Kind.SHORT_CIRCUIT)); + } + body.end().end(); // call + andOperator = " && "; + } + } + } + } + + @Override + protected void createChildren(OperationData m) { + CodeTypeElement operationGen = null; + if (m.hasExtensions()) { + OperationGenFactory factory = new OperationGenFactory(context); + add(factory, m); + operationGen = (CodeTypeElement) factory.getElement(); + } + if (m.generateFactory) { + add(new OperationNodeFactory(context, operationGen), m); + } + } + + protected class OperationGenFactory extends ClassElementFactory { + + public OperationGenFactory(ProcessorContext context) { + super(context); + } + + @Override + protected CodeTypeElement create(OperationData operation) { + CodeTypeElement clazz = createClass(operation, modifiers(PUBLIC), genClassName(operation), operation.getTemplateType().asType(), false); + + clazz.add(createConstructorUsingFields(modifiers(PUBLIC), clazz)); + + if (operation.getExtensionElements() != null) { + clazz.getEnclosedElements().addAll(operation.getExtensionElements()); + } + return clazz; + } + + } + + + + protected class OperationNodeFactory extends ClassElementFactory { + + private final CodeTypeElement operationGen; + + public OperationNodeFactory(ProcessorContext context, CodeTypeElement operationGen) { + super(context); + this.operationGen = operationGen; + } + + @Override + protected CodeTypeElement create(OperationData operation) { + CodeTypeElement clazz = createClass(operation, modifiers(PUBLIC, FINAL), factoryClassName(operation), null, false); + + if (operation.isUseSingleton()) { + TypeMirror type = findOperationType(operation, operationGen); + CodeVariableElement singleton = new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), type, singletonName(operation)); + clazz.add(singleton); + CodeTreeBuilder singletonInit = singleton.createInitBuilder(); + singletonInit.startNew(type).end(); + } + + clazz.add(createConstructorUsingFields(modifiers(PRIVATE), clazz)); + clazz.add(createCreateMethod(operation)); + if (operation.getAllMethods().length > 1) { + clazz.add(createCreateSpecializedMethod(operation)); + } + if (operation.needsRewrites()) { + clazz.add(createSpecializeMethod(operation)); + clazz.add(createGeneratedGenericMethod(operation)); + } + + return clazz; + } + + @Override + protected void createChildren(OperationData operation) { + for (SpecializationData specialization : operation.getAllMethods()) { + add(new SpecializationNodeFactory(context, operationGen), specialization); + } + } + + private CodeExecutableElement createCreateMethod(OperationData operation) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), operation.getNodeType(), "create"); + addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE, Kind.CONSTRUCTOR_FIELD)); + + CodeTreeBuilder body = method.createBuilder(); + body.startReturn(); + if (operation.getAllMethods().length == 0) { + body.null_(); + } else { + body.startNew(nodeClassName(operation.getAllMethods()[0])); + emitNewOperation(body, operation); + addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + body.end(); + } + body.end(); + + return method; + } + + private void emitNewOperation(CodeTreeBuilder body, OperationData operation) { + if (!operation.isUseSingleton()) { + body.startGroup(); + if (operation.hasExtensions()) { + body.startNew(genClassName(operation)); + } else { + body.startNew(operation.getTemplateType().asType()); + } + addNodeNames(body, operation, kinds(Kind.CONSTRUCTOR_FIELD)); + body.end(); + body.end(); + } + } + + private CodeExecutableElement createCreateSpecializedMethod(OperationData operation) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getNodeType(), "createSpecialized"); + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass")); + addOperationVariable(modifiers(), method, operation, operationGen); + addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + + CodeTreeBuilder body = method.createBuilder(); + + boolean first = true; + for (TypeData type : operation.getTypeSystem().getTypes()) { + SpecializationData specialization = operation.findUniqueSpecialization(type); + if (specialization != null && !type.isGeneric()) { + if (first) { + body.startIf(); + first = false; + } else { + body.startElseIf(); + } + body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock(); + body.startReturn().startNew(nodeClassName(specialization)); + addOperationFieldName(body, operation); + addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + body.end().end(); + body.end(); + } + } + body.startReturn().startNew(nodeClassName(operation.getGenericSpecialization())); + addOperationFieldName(body, operation); + addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + body.end().end(); + return method; + } + + private CodeExecutableElement createSpecializeMethod(OperationData operation) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getNodeType(), "specialize"); + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); + addOperationVariable(modifiers(), method, operation, operationGen); + addValueParameters(method, operation, kinds(Kind.EXECUTE)); + addNodeParameters(method, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + + CodeTreeBuilder body = method.createBuilder(); + body.startStatement().string("boolean allowed = (minimumState == ").string(nodeClassName(operation.getAllMethods()[0])).string(".class)").end(); + + for (int i = 1; i < operation.getAllMethods().length; i++) { + SpecializationData specialization = operation.getAllMethods()[i]; + body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end(); + + if (specialization.isGeneric()) { + body.startIf().string("allowed").end().startBlock(); + } else { + body.startIf().string("allowed"); + emitGuards(getContext(), body, " && ", specialization, true, true); + body.end().startBlock(); + } + body.startReturn().startNew(nodeClassName(specialization)); + + addOperationFieldName(body, operation); + addNodeNames(body, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + body.end().end(); + body.end(); // block + } + body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); + + return method; + } + + + private void emitInvokeDoMethod(CodeTreeBuilder builder, SpecializationData specialization) { + if (specialization.getExceptions().length > 0) { + builder.startTryBlock(); + } + + builder.startReturn(); + startCallOperationMethod(builder, specialization.getOperation(), specialization); + for (ActualParameter param : specialization.getParameters()) { + boolean needsCast = param.getSpecification().getKind() == Kind.EXECUTE && !param.getActualTypeData(specialization.getOperation().getTypeSystem()).isGeneric(); + if (needsCast) { + startCallTypeSystemMethod(getContext(), builder, specialization.getOperation(), TypeSystemCodeGenerator.asTypeMethodName(param.getActualTypeData(specialization.getOperation().getTypeSystem()))); + } + builder.string(valueVariableName(param)); + if (needsCast) { + builder.end().end(); + } + } + builder.end().end(); // start call operation + builder.end(); // return + + if (specialization.getExceptions().length > 0) { + for (SpecializationThrowsData exception : specialization.getExceptions()) { + builder.end().startCatchBlock(exception.getJavaClass(), "ex"); + emitInvokeDoMethod(builder, exception.getTransitionTo()); + } + builder.end(); + } + } + + private CodeExecutableElement createGeneratedGenericMethod(OperationData operation) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), operation.getGenericSpecialization().getReturnType().getActualType(), "generatedGeneric"); + addOperationVariable(modifiers(), method, operation, operationGen); + addValueParameters(method, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + + CodeTreeBuilder builder = method.createBuilder(); + boolean ifStarted = false; + for (int i = 0; i < operation.getSpecializations().length; i++) { + SpecializationData specialization = operation.getSpecializations()[i]; + if (specialization.isUninitialized()) { + continue; + } + if (!specialization.isGeneric()) { + if (!ifStarted) { + builder.startIf(); + ifStarted = true; + } else { + builder.startElseIf(); + } + emitGuards(getContext(), builder, "", specialization, false, true); + builder.end().startBlock(); + } else { + builder.startElseBlock(); + } + + emitInvokeDoMethod(builder, specialization); + builder.end(); + } + return method; + } + } + + protected class SpecializationNodeFactory extends ClassElementFactory { + + private CodeTypeElement operationGen; + + public SpecializationNodeFactory(ProcessorContext context, CodeTypeElement operationGen) { + super(context); + this.operationGen = operationGen; + } + + @Override + public CodeTypeElement create(SpecializationData specialization) { + OperationData operation = specialization.getOperation(); + CodeTypeElement clazz = createClass(operation, modifiers(PRIVATE, STATIC, FINAL), nodeClassName(specialization), operation.getNodeType(), false); + + + CodeExecutableElement constructor = new CodeExecutableElement(modifiers(PROTECTED), null, clazz.getSimpleName().toString()); + clazz.add(constructor); + + CodeTreeBuilder builder = constructor.createBuilder(); + builder.startStatement().startSuperCall(); + addNodeNames(builder, operation, kinds(Kind.SUPER_ATTRIBUTE)); + builder.end().end(); + + if (!operation.isUseSingleton()) { + addOperationVariable(modifiers(), constructor, operation, operationGen); + addOperationVariable(modifiers(PRIVATE, FINAL), clazz, operation, operationGen); + builder.startStatement(); + builder.string("this."); + addOperationFieldName(builder, operation); + builder.string(" = "); + addOperationFieldName(builder, operation); + builder.end(); + } + addNodeParameters(constructor, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + + + for (ParameterSpec spec : operation.getSpecification().getParameters()) { + String name = nodeVariableName(spec); + + boolean isNodeAttribute = spec.getKind() == Kind.ATTRIBUTE && getContext().getEnvironment().getTypeUtils().isAssignable(spec.getValueType(), getContext().getTruffleTypes().getNode()); + boolean isNodeArrayAttribute = spec.getKind() == Kind.ATTRIBUTE && + getContext().getEnvironment().getTypeUtils().isAssignable(spec.getValueType(), getContext().getTruffleTypes().getNodeArray()); + if (spec.getKind() == Kind.EXECUTE || isNodeAttribute || isNodeArrayAttribute) { + CodeVariableElement field = new CodeVariableElement(modifiers(PRIVATE), operation.getTypeSystem().getNodeType(), name); + clazz.add(field); + field.addAnnotationMirror(new CodeAnnotationMirror((DeclaredType) getContext().getTruffleTypes().getStableAnnotation())); + if (isNodeArrayAttribute) { + field.addAnnotationMirror(new CodeAnnotationMirror((DeclaredType) getContext().getTruffleTypes().getContentStableAnnotation())); + } + builder.startStatement().string("this.").string(name).string(" = adoptChild(").string(name).string(")").end(); + } else if (spec.getKind() == Kind.ATTRIBUTE) { + clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), spec.getValueType(), name)); + builder.startStatement().string("this.").string(name).string(" = ").string(name).end(); + } + } + + TypeSystemData typeSystem = operation.getTypeSystem(); + for (TypeData type : typeSystem.getTypes()) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), executeMethodName(type)); + clazz.add(method); + addValueParameters(method, operation, kinds(Kind.SIGNATURE)); + if (!type.isGeneric()) { + method.addThrownType(getUnexpectedValueException()); + } + + if (specialization.getReturnType().getActualTypeData(typeSystem) == type) { + buildFunctionalExecuteMethod(method.createBuilder(), operation, specialization); + } else { + buildCastingExecuteMethod(method.createBuilder(), operation, specialization, type); + } + } + + if (typeSystem.getVoidType() != null) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), executeMethodName(typeSystem.getVoidType())); + addValueParameters(method, operation, kinds(Kind.SIGNATURE)); + buildCastingExecuteMethod(method.createBuilder(), operation, specialization, typeSystem.getVoidType()); + clazz.add(method); + } + + if (operation.needsRewrites() && !specialization.isGeneric() && !specialization.isUninitialized()) { + buildSpecializeStateMethod(clazz, operation); + } + buildSpecializeClassMethod(clazz, operation); + + return clazz; + } + + private void buildCastingExecuteMethod(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization, TypeData type) { + if (!type.isVoid()) { + builder.startStatement().type(specialization.getReturnType().getActualType()).string(" result").end(); + } + + boolean needsTry = !specialization.getReturnType().getActualTypeData(operation.getTypeSystem()).isGeneric(); + if (needsTry) { + builder.startTryBlock(); + } + + builder.startStatement(); + if (!type.isVoid()) { + builder.string("result = "); + } + builder.startCall(executeMethodName(specialization.getReturnType().getActualTypeData(operation.getTypeSystem()))).string("frame").end(); + builder.end(); // statement + + if (needsTry) { + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + + if (!type.isVoid()) { + builder.startReturn(); + if (!type.isGeneric()) { + startCallTypeSystemMethod(getContext(), builder, operation, TypeSystemCodeGenerator.expectTypeMethodName(type)); + } + + builder.string("ex.getResult()"); + + if (!type.isGeneric()) { + builder.end().end(); + } + builder.end(); // return + } else { + builder.string("// ignore").newLine(); + } + } + builder.end(); // try/catch + + if (!type.isVoid()) { + builder.startReturn(); + if (!type.isGeneric()) { + startCallTypeSystemMethod(getContext(), builder, operation, TypeSystemCodeGenerator.expectTypeMethodName(type)); + } + builder.string("result"); + if (!type.isGeneric()) { + builder.end().end(); + } + builder.end(); // return + } + } + + private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization) { + ActualParameter previousShortCircuitParameter = null; + for (ActualParameter param : specialization.getParameters()) { + if (param.getSpecification().getKind() != Kind.EXECUTE) { + // Nothing to do. + } else if (param.getActualTypeData(operation.getTypeSystem()).isGeneric()) { + buildGenericValueExecute(builder, operation, param, null); + } else { + buildSpecializedValueExecute(builder, operation, specialization, param); + } + + assert param.getSpecification().getKind() == Kind.SHORT_CIRCUIT || previousShortCircuitParameter == null; + } + + if (specialization.hasDynamicGuards()) { + builder.startIf(); + emitGuards(getContext(), builder, "", specialization, false, false); + builder.end().startBlock(); + } + if (specialization.getExceptions().length > 0) { + builder.startTryBlock(); + } + + if (specialization.isUninitialized() && operation.needsRewrites()) { + for (TemplateMethod listener : operation.getSpecializationListeners()) { + builder.startStatement(); + startCallOperationMethod(builder, operation, listener); + for (ActualParameter param : listener.getParameters()) { + builder.string(valueVariableName(param)); + } + builder.end().end(); + builder.end(); // statement + } + + builder.startStatement(); + builder.startCall("replace"); + builder.startCall(factoryClassName(operation), "specialize"); + builder.typeLiteral(builder.getRoot().getEnclosingClass().asType()); + addOperationFieldName(builder, operation); + addValueNames(builder, operation, kinds(Kind.EXECUTE)); + addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + builder.end().end().end(); + } + + if ((specialization.isUninitialized() || specialization.isGeneric()) && operation.needsRewrites()) { + builder.startReturn().startCall(factoryClassName(specialization.getOperation()), "generatedGeneric"); + addOperationFieldName(builder, operation); + addValueNames(builder, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + builder.end().end(); + } else { + builder.startReturn(); + + if (specialization.isUninitialized()) { + startCallOperationMethod(builder, specialization.getOperation(), specialization.getOperation().getGenericSpecialization()); + } else { + startCallOperationMethod(builder, specialization.getOperation(), specialization); + } + for (ActualParameter param : specialization.getParameters()) { + builder.string(valueVariableName(param)); + } + builder.end().end(); // operation call + builder.end(); // return + } + + if (specialization.getExceptions().length > 0) { + for (SpecializationThrowsData exception : specialization.getExceptions()) { + builder.end().startCatchBlock(exception.getJavaClass(), "ex"); + buildThrowSpecialize(builder, operation, exception.getTransitionTo(), null); + } + builder.end(); + } + if (specialization.hasDynamicGuards()) { + builder.end().startElseBlock(); + buildThrowSpecialize(builder, operation, specialization.findNextSpecialization(), null); + builder.end(); + } + } + + private void buildGenericValueExecute(CodeTreeBuilder builder, OperationData operation, ActualParameter param, ParameterSpec exceptionSpec) { + boolean shortCircuit = startShortCircuit(builder, operation.getGenericSpecialization(), + operation.getGenericSpecialization().findParameter(param.getSpecification().getName()), exceptionSpec); + + builder.startStatement(); + if (!shortCircuit) { + builder.type(operation.getTypeSystem().getGenericType()); + builder.string(" "); + } + builder.string(valueVariableName(param)); + builder.string(" = ").startCall(nodeVariableName(param), executeMethodName(operation.getTypeSystem().getGenericTypeData())).string("frame").end(); + builder.end(); + + endShortCircuit(builder, shortCircuit); + } + + private boolean startShortCircuit(CodeTreeBuilder builder, SpecializationData specialization, + ActualParameter forParam, ParameterSpec exceptionParam) { + ActualParameter shortCircuitParam = specialization.getPreviousParam(forParam); + if (shortCircuitParam == null || shortCircuitParam.getSpecification().getKind() != Kind.SHORT_CIRCUIT) { + return false; + } + + int shortCircuitIndex = 0; + for (ActualParameter parameter : specialization.getParameters()) { + if (parameter.getSpecification().getKind() == Kind.SHORT_CIRCUIT) { + if (parameter == shortCircuitParam) { + break; + } + shortCircuitIndex++; + } + } + + builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(shortCircuitParam.getSpecification().getName()).string(" = "); + ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; + + startCallOperationMethod(builder, specialization.getOperation(), shortCircuitData); + for (ActualParameter callParam : shortCircuitData.getParameters()) { + ParameterSpec spec = callParam.getSpecification(); + if (spec.getKind() == Kind.EXECUTE || spec.getKind() == Kind.SHORT_CIRCUIT || spec.getKind() == Kind.SIGNATURE) { + if (exceptionParam != null && callParam.getSpecification().getName().equals(exceptionParam.getName())) { + builder.string("ex.getResult()"); + } else { + builder.string(valueVariableName(spec)); + } + } + } + builder.end().end(); // call operation + + builder.end(); // statement + + builder.declaration(forParam.getActualType(), valueVariableName(forParam), + CodeTreeBuilder.createBuilder().defaultValue(forParam.getActualType())); + builder.startIf().string(valueVariableName(shortCircuitParam)).end(); + builder.startBlock(); + + return true; + } + + + private void endShortCircuit(CodeTreeBuilder builder, boolean shortCircuit) { + if (shortCircuit) { + builder.end(); + } + } + + private void buildSpecializedValueExecute(CodeTreeBuilder builder, OperationData operation, SpecializationData specialization, ActualParameter param) { + boolean shortCircuit = startShortCircuit(builder, specialization, param, null); + + if (!shortCircuit) { + builder.startStatement().type(param.getActualType()).string(" ").string(valueVariableName(param)).end(); + } + + builder.startTryBlock(); + builder.startStatement().string(valueVariableName(param)).string(" = "); + builder.startCall(nodeVariableName(param), executeMethodName(param.getActualTypeData(operation.getTypeSystem()))).string("frame").end(); + builder.end(); + + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + boolean execute = false; + for (ActualParameter exParam : specialization.getParameters()) { + if (exParam.getSpecification().getKind() != Kind.EXECUTE) { + // Nothing to do. + } else if (execute) { + buildGenericValueExecute(builder, operation, exParam, param.getSpecification()); + } else if (exParam == param) { + execute = true; + } + } + + buildThrowSpecialize(builder, operation, specialization.findNextSpecialization(), param.getSpecification()); + builder.end(); // catch block + + endShortCircuit(builder, shortCircuit); + builder.newLine(); + } + + private void buildThrowSpecialize(CodeTreeBuilder builder, OperationData operation, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) { + builder.startThrow().startCall("specialize"); + builder.string(nodeClassName(nextSpecialization) + ".class"); + addValueNames(builder, operation, kinds(Kind.SIGNATURE)); + for (ParameterSpec spec : operation.getSpecification().getParameters()) { + if (spec.getKind() == Kind.EXECUTE || spec.getKind() == Kind.SHORT_CIRCUIT) { + if (spec == exceptionSpec) { + builder.string("ex.getResult()"); + } else { + builder.string(valueVariableName(spec)); + } + } + } + builder.end().end(); + } + + private void buildSpecializeStateMethod(CodeTypeElement clazz, OperationData operation) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), getUnexpectedValueException(), "specialize"); + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); + addValueParameters(method, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT)); + clazz.add(method); + CodeTreeBuilder builder = method.createBuilder(); + + for (TemplateMethod listener : operation.getSpecializationListeners()) { + builder.startStatement(); + startCallOperationMethod(builder, operation, listener); + for (ActualParameter param : listener.getParameters()) { + builder.string(valueVariableName(param)); + } + builder.end().end(); + builder.end(); // statement + } + + builder.startStatement(); + builder.startCall("replace"); + builder.startCall(factoryClassName(operation), "specialize").string("minimumState"); + addOperationFieldName(builder, operation); + addValueNames(builder, operation, kinds(Kind.EXECUTE)); + addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + builder.end().end().end(); + + builder.startReturn().startNew(getUnexpectedValueException()).startCall(factoryClassName(operation), "generatedGeneric"); + addOperationFieldName(builder, operation); + addValueNames(builder, operation, kinds(Kind.SIGNATURE, Kind.EXECUTE, Kind.SHORT_CIRCUIT, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + builder.end().end().end(); + } + + private void buildSpecializeClassMethod(CodeTypeElement clazz, OperationData operation) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), getContext().getType(void.class), "specialize"); + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "specializationClass")); + if (!isDeclaredMethodInSuperType(clazz, method.getSimpleName().toString(), method.getParameterTypes())) { + return; + } + clazz.add(method); + CodeTreeBuilder builder = method.createBuilder(); + + builder.startStatement(); + builder.startCall("replace"); + builder.startCall(factoryClassName(operation), "createSpecialized").string("specializationClass"); + addOperationFieldName(builder, operation); + addNodeNames(builder, operation, kinds(Kind.EXECUTE, Kind.ATTRIBUTE, Kind.SUPER_ATTRIBUTE)); + builder.end().end().end(); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.typesystem.*; + +public class OperationData extends Template { + + private final TypeSystemData typeSystem; + private final String[] values; + private final String[] shortCircuitValues; + private final OperationFieldData[] operationFields; + private final OperationFieldData[] constructorFields; + private final OperationFieldData[] superFields; + private final TypeMirror nodeType; + + private MethodSpec specification; + private SpecializationData genericSpecialization; + private SpecializationData[] specializations; + private TemplateMethod[] specializationListeners; + private GuardData[] guards; + + boolean generateFactory = true; + + public OperationData(TypeElement templateType, AnnotationMirror templateTypeAnnotation, + TypeSystemData typeSystem, TypeMirror nodeType, + String[] values, String[] shortCircuitValues, + OperationFieldData[] operationFields, + OperationFieldData[] constructorFields, + OperationFieldData[] superFields) { + super(templateType, templateTypeAnnotation); + this.nodeType = nodeType; + this.typeSystem = typeSystem; + this.values = values; + this.shortCircuitValues = shortCircuitValues; + this.operationFields = operationFields; + this.constructorFields = constructorFields; + this.superFields = superFields; + } + + public boolean isUseSingleton() { + return constructorFields.length == 0; + } + + public boolean hasExtensions() { + return !getExtensionElements().isEmpty(); + } + + public List findGuards(String name) { + List foundGuards = new ArrayList<>(); + for (GuardData guardData : guards) { + if (guardData.getMethodName().equals(name)) { + foundGuards.add(guardData); + } + } + for (GuardData guardData : getTypeSystem().getGuards()) { + if (guardData.getMethodName().equals(name)) { + foundGuards.add(guardData); + } + } + return foundGuards; + } + + + void setGuards(GuardData[] guards) { + this.guards = guards; + } + + void setSpecification(MethodSpec specification) { + this.specification = specification; + } + + void setGenericSpecialization(SpecializationData genericSpecialization) { + this.genericSpecialization = genericSpecialization; + } + + void setSpecializations(SpecializationData[] specializations) { + this.specializations = specializations; + for (SpecializationData specialization : specializations) { + specialization.setOperation(this); + } + } + + void setSpecializationListeners(TemplateMethod[] specializationListeners) { + this.specializationListeners = specializationListeners; + } + + public String[] getValues() { + return values; + } + + public OperationFieldData[] getOperationFields() { + return operationFields; + } + + public String[] getShortCircuitValues() { + return shortCircuitValues; + } + + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public TypeMirror getNodeType() { + return nodeType; + } + + public SpecializationData[] getSpecializations() { + return specializations; + } + + public SpecializationData getGenericSpecialization() { + return genericSpecialization; + } + + public OperationFieldData[] getConstructorFields() { + return constructorFields; + } + + public OperationFieldData[] getSuperFields() { + return superFields; + } + + public MethodSpec getSpecification() { + return specification; + } + + public SpecializationData[] getAllMethods() { + return specializations; + } + + public boolean needsRewrites() { + boolean needsRewrites = getValues().length > 0 || getShortCircuitValues().length > 0; + needsRewrites &= specializations.length >= 2; + return needsRewrites; + } + + public TemplateMethod[] getSpecializationListeners() { + return specializationListeners; + } + + public GuardData[] getGuards() { + return guards; + } + + public SpecializationData findUniqueSpecialization(TypeData type) { + SpecializationData result = null; + for (SpecializationData specialization : specializations) { + if (specialization.getReturnType().getActualTypeData(getTypeSystem()) == type) { + if (result != null) { + // Result not unique; + return null; + } + result = specialization; + } + } + return result; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationFieldData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationFieldData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; + +public class OperationFieldData { + + private final String name; + private final TypeMirror javaClass; + + public OperationFieldData(String name, TypeMirror javaClass) { + this.name = name; + this.javaClass = javaClass; + } + + public String getName() { + return name; + } + + public TypeMirror getJavaClass() { + return javaClass; + } + + @Override + public String toString() { + return Utils.getSimpleName(javaClass); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationMethodParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import java.util.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + + +public abstract class OperationMethodParser extends TemplateMethodParser{ + + private final OperationData operation; + + public OperationMethodParser(ProcessorContext context, OperationData operation) { + super(context); + this.operation = operation; + } + + public OperationData getOperation() { + return operation; + } + + protected ParameterSpec createValueParameterSpec(String valueName) { + return new ParameterSpec(valueName, operation.getTypeSystem(), + Kind.EXECUTE, false, Cardinality.ONE); + } + + protected ParameterSpec createReturnParameterSpec() { + return createValueParameterSpec("operation"); + } + + protected final MethodSpec createDefaultMethodSpec(String shortCircuitName) { + List defaultParameters = new ArrayList<>(); + ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), Kind.SIGNATURE, true); + defaultParameters.add(frameSpec); + + for (String valueName : operation.getValues()) { + defaultParameters.add(createValueParameterSpec(valueName)); + } + + for (String valueName : operation.getShortCircuitValues()) { + if (shortCircuitName != null && valueName.equals(shortCircuitName)) { + break; + } + + defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName), + getContext().getType(boolean.class), Kind.SHORT_CIRCUIT, false)); + + defaultParameters.add(createValueParameterSpec(valueName)); + } + + for (OperationFieldData field : operation.getSuperFields()) { + defaultParameters.add(new ParameterSpec(field.getName(), field.getJavaClass(), Kind.SUPER_ATTRIBUTE, true)); + } + + for (OperationFieldData field : operation.getOperationFields()) { + defaultParameters.add(new ParameterSpec(field.getName(), field.getJavaClass(), Kind.ATTRIBUTE, false)); + } + + return new MethodSpec(createReturnParameterSpec(), defaultParameters); + } + + private static String shortCircuitValueName(String valueName) { + return "has" + Utils.firstLetterUpperCase(valueName) + "Value"; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/OperationParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; +import com.oracle.truffle.codegen.processor.typesystem.*; + +public class OperationParser extends TemplateParser { + + public OperationParser(ProcessorContext c) { + super(c); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return com.oracle.truffle.api.codegen.Operation.class; + } + + @Override + protected OperationData parse(Element element, AnnotationMirror templateTypeAnnotation) { + TypeElement templateType = (TypeElement) element; + + if (!verifyTemplateType(templateType, templateTypeAnnotation)) { + return null; + } + + TypeMirror typeSystemMirror = Utils.getAnnotationValueType(templateTypeAnnotation, "typeSystem"); + final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemMirror, true); + if (typeSystem == null) { + log.error(templateType, templateTypeAnnotation, "Type system '%s' is invalid.", Utils.getQualifiedName(typeSystemMirror)); + return null; + } + + TypeMirror nodeType = Utils.getAnnotationValueType(templateTypeAnnotation, "baseClass"); + if (Utils.typeEquals(nodeType, context.getTruffleTypes().getNode())) { + nodeType = typeSystem.getNodeType(); + } + + if (!Utils.isAssignable(nodeType, typeSystem.getNodeType())) { + log.error(templateType, templateTypeAnnotation, + Utils.getAnnotationValue(templateTypeAnnotation, "baseClass"), + "The baseClass does not extend the base class of the type system '%s'.", Utils.getQualifiedName(typeSystem.getNodeType())); + return null; + } + + for (VariableElement field : ElementFilter.fieldsIn(templateType.getEnclosedElements())) { + if (!field.getModifiers().contains(Modifier.STATIC) + && !field.getModifiers().contains(Modifier.FINAL)) { + log.error(field, "Field must be final."); + return null; + } + } + + + List valueNames = Utils.getAnnotationValueList(templateTypeAnnotation, "values"); + List shortCircuitNames = Utils.getAnnotationValueList(templateTypeAnnotation, "shortCircuitValues"); + + List names = new ArrayList<>(); + names.addAll(valueNames); + names.addAll(shortCircuitNames); + + List fieldAnnotations = Collections.emptyList(); // call collectionAnnotations instead if you want OperationField support enabled. + List fields = new ArrayList<>(); + for (AnnotationMirror fieldMirror : fieldAnnotations) { + String name = Utils.getAnnotationValueString(fieldMirror, "name"); + TypeMirror javaClass = Utils.getAnnotationValueType(fieldMirror, "javaClass"); + fields.add(new OperationFieldData(name, javaClass)); + names.add(name); + } + + List constructorFields = parseConstructorFields(templateType, true); + if (constructorFields == null) { + return null; + } + + List superConstructorFields = parseConstructorFields(Utils.fromTypeMirror(nodeType), false); + if (superConstructorFields == null) { + return null; + } + + List protectedSuperFields = parseProtectedFields(Utils.fromTypeMirror(nodeType)); + if (protectedSuperFields == null) { + return null; + } + + List matchedSuperFields = matchFields(superConstructorFields, protectedSuperFields); + if (matchedSuperFields == null) { + log.error(templateType, templateTypeAnnotation, Utils.getAnnotationValue(templateTypeAnnotation, "baseClass"), + "The signature of the protected fields (%s) and the first constructor(%s) in %s does not match.", + protectedSuperFields.toString(), + superConstructorFields.toString(), + Utils.getQualifiedName(nodeType)); + return null; + } + + for (OperationFieldData field : constructorFields) { + names.add(field.getName()); + } + + for (OperationFieldData field : matchedSuperFields) { + names.add(field.getName()); + } + + if (!verifyNames(templateType, templateTypeAnnotation, names)) { + return null; + } + + OperationData operationData = new OperationData(templateType, templateTypeAnnotation, typeSystem, nodeType, + valueNames.toArray(new String[valueNames.size()]), + shortCircuitNames.toArray(new String[shortCircuitNames.size()]), + fields.toArray(new OperationFieldData[fields.size()]), + constructorFields.toArray(new OperationFieldData[constructorFields.size()]), + matchedSuperFields.toArray(new OperationFieldData[matchedSuperFields.size()])); + + if (!verifyExclusiveMethodAnnotation(templateType, + Specialization.class, Generic.class, SpecializationListener.class, ShortCircuit.class, GuardCheck.class)) { + return noFactory(operationData); + } + + operationData.setExtensionElements(getExtensionParser().parseAll(templateType)); + + List genericSpecializations = parseMethods(operationData, new GenericParser(context, operationData)); + List guards = parseMethods(operationData, new GuardParser(context, operationData.getTypeSystem(), operationData)); + operationData.setGuards(guards.toArray(new GuardData[guards.size()])); + + SpecializationParser specializationParser = new SpecializationParser(context, operationData); + operationData.setSpecification(specializationParser.getSpecification()); + List specializations = parseMethods(operationData, specializationParser); + List shortCircuits = parseMethods(operationData, new ShortCircuitParser(context, operationData)); + List listeners = parseMethods(operationData, new SpecializationListenerParser(context, operationData)); + + if (specializations == null || genericSpecializations == null || shortCircuits == null || listeners == null || guards == null) { + return noFactory(operationData); + } + + + SpecializationData genericSpecialization = null; + if (genericSpecializations.size() > 1) { + for (SpecializationData generic : genericSpecializations) { + log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName()); + } + return noFactory(operationData); + } else if (genericSpecializations.size() == 1) { + genericSpecialization = genericSpecializations.get(0); + } + + if (specializations.size() > 1 && genericSpecialization == null) { + log.error(templateType, "Need a @%s method.", Generic.class.getSimpleName()); + return noFactory(operationData); + } + + Collections.sort(specializations, new Comparator() { + @Override + public int compare(SpecializationData o1, SpecializationData o2) { + return compareSpecialization(typeSystem, o1, o2); + } + }); + + List allSpecializations = new ArrayList<>(specializations); + if (genericSpecialization != null) { + allSpecializations.add(genericSpecialization); + TemplateMethod uninializedMethod = new TemplateMethod(genericSpecialization.getSpecification(), new CodeExecutableElement(context.getType(void.class), "doUninialized"), + genericSpecialization.getMarkerAnnotation(), genericSpecialization.getReturnType(), genericSpecialization.getParameters()); + allSpecializations.add(0, new SpecializationData(uninializedMethod, false, true)); + } + + // verify order is not ambiguous + verifySpecializationOrder(typeSystem, specializations); + + operationData.setGenericSpecialization(genericSpecialization); + operationData.setSpecializations(allSpecializations.toArray(new SpecializationData[allSpecializations.size()])); + operationData.setSpecializationListeners(listeners.toArray(new TemplateMethod[listeners.size()])); + + if (!assignShortCircuitsToSpecializations(operationData, allSpecializations, shortCircuits)) { + return null; + } + + if (!verifyNamingConvention(specializations, "do")) { + return noFactory(operationData); + } + + if (!verifyNamesUnique(specializations)) { + return noFactory(operationData); + } + + if (!verifyNamingConvention(shortCircuits, "needs")) { + return noFactory(operationData); + } + + if (!verifySpecializationThrows(typeSystem, specializations)) { + return noFactory(operationData); + } + + return operationData; + } + + private static List matchFields(List params, + List fields) { + + if (params.size() != fields.size()) { + return null; + } + + List matchedFields = new ArrayList<>(); + for (int i = 0; i < params.size(); i++) { + OperationFieldData param = params.get(i); + OperationFieldData field = fields.get(i); + if (!Utils.typeEquals(param.getJavaClass(), field.getJavaClass())) { + return null; + } + matchedFields.add(new OperationFieldData(field.getName(), param.getJavaClass())); + } + + return matchedFields; + } + + private static List parseProtectedFields(Element element) { + List opFields = new ArrayList<>(); + List fields = ElementFilter.fieldsIn(element.getEnclosedElements()); + for (VariableElement var : fields) { + if (var.getModifiers().contains(Modifier.STATIC)) { + continue; + } + + if (var.getModifiers().contains(Modifier.PROTECTED)) { + opFields.add(new OperationFieldData(var.getSimpleName().toString(), var.asType())); + } + } + return opFields; + + } + + private List parseConstructorFields(Element element, boolean failOnMultipleConstructors) { + if (element == null) { + return Collections.emptyList(); + } + + List constructors = ElementFilter.constructorsIn(element.getEnclosedElements()); + ExecutableElement constructor = null; + if (constructors.size() > 1) { + if (failOnMultipleConstructors) { + for (ExecutableElement c : constructors) { + log.error(c, "The Operation annotated class must not define multiple constructors."); + } + return null; + } else { + // take first constructor + constructor = constructors.get(0); + } + } else if (constructors.size() == 1) { + constructor = constructors.get(0); + } + + List constructorFields = new ArrayList<>(); + if (constructor != null) { + for (VariableElement var : constructor.getParameters()) { + constructorFields.add(new OperationFieldData(var.getSimpleName().toString(), var.asType())); + } + } + return constructorFields; + } + + private static OperationData noFactory(OperationData data) { + data.generateFactory = false; + return data; + } + + private boolean verifySpecializationThrows(TypeSystemData typeSystem, List specializations) { + Map specializationMap = new HashMap<>(); + for (SpecializationData spec : specializations) { + specializationMap.put(spec.getMethodName(), spec); + } + boolean valid = true; + for (SpecializationData sourceSpecialization : specializations) { + if (sourceSpecialization.getExceptions() != null) { + for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) { + SpecializationData targetSpecialization = specializationMap.get(throwsData.getTransitionToName()); + AnnotationValue value = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "transitionTo"); + if (targetSpecialization == null) { + log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value, + "Specialization with name '%s' not found.", throwsData.getTransitionToName()); + valid = false; + } else if (compareSpecialization(typeSystem, sourceSpecialization, targetSpecialization) >= 0) { + log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), value, + "The order of the target specializalization must be higher than the source specialization.", throwsData.getTransitionToName()); + valid = false; + } + + for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) { + if (otherThrowsData != throwsData + && Utils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) { + AnnotationValue javaClassValue = Utils.getAnnotationValue(throwsData.getAnnotationMirror(), "javaClass"); + log.error(throwsData.getSpecialization().getMethod(), throwsData.getAnnotationMirror(), javaClassValue, + "Duplicate exception type.", throwsData.getTransitionToName()); + valid = false; + } + } + } + } + } + return valid; + } + + + private boolean assignShortCircuitsToSpecializations(OperationData operation, + List specializations, + List shortCircuits) { + + Map> groupedShortCircuits = groupShortCircuits(shortCircuits); + + boolean valid = true; + + for (String valueName : operation.getShortCircuitValues()) { + List availableCircuits = groupedShortCircuits.get(valueName); + + if (availableCircuits == null || availableCircuits.isEmpty()) { + log.error(operation.getTemplateType(), operation.getTemplateTypeAnnotation(), + "@%s method for short cut value '%s' required.", + ShortCircuit.class.getSimpleName(), valueName); + valid = false; + continue; + } + + + boolean sameMethodName = true; + String methodName = availableCircuits.get(0).getMethodName(); + for (ShortCircuitData circuit : availableCircuits) { + if (!circuit.getMethodName().equals(methodName)) { + sameMethodName = false; + } + } + + if (!sameMethodName) { + for (ShortCircuitData circuit : availableCircuits) { + log.error(circuit.getMethod(), circuit.getMarkerAnnotation(), "All short circuits for short cut value '%s' must have the same method name.", valueName); + } + valid = false; + continue; + } + + ShortCircuitData genericCircuit = null; + for (ShortCircuitData circuit : availableCircuits) { + if (isGenericShortCutMethod(circuit, operation.getTypeSystem().getGenericType())) { + genericCircuit = circuit; + break; + } + } + + if (genericCircuit == null) { + log.error(operation.getTemplateType(), operation.getTemplateTypeAnnotation(), + "No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName); + valid = false; + continue; + } + + for (ShortCircuitData circuit : availableCircuits) { + if (circuit != genericCircuit) { + circuit.setGenericShortCircuitMethod(genericCircuit); + } + } + } + + if (!valid) { + return valid; + } + + for (SpecializationData specialization : specializations) { + ShortCircuitData[] assignedShortCuts = new ShortCircuitData[operation.getShortCircuitValues().length]; + + for (int i = 0; i < operation.getShortCircuitValues().length; i++) { + List availableShortCuts = groupedShortCircuits.get(operation.getShortCircuitValues()[i]); + + ShortCircuitData genericShortCircuit = null; + for (ShortCircuitData circuit : availableShortCuts) { + if (circuit.isGeneric()) { + genericShortCircuit = circuit; + } else if (circuit.isCompatibleTo(specialization)) { + assignedShortCuts[i] = circuit; + } + } + + if (assignedShortCuts[i] == null) { + assignedShortCuts[i] = genericShortCircuit; + } + } + specialization.setShortCircuits(assignedShortCuts); + } + return true; + } + + private static boolean isGenericShortCutMethod(TemplateMethod method, TypeMirror genericType) { + for (ActualParameter parameter : method.getParameters()) { + if (parameter.getSpecification().getKind() == Kind.EXECUTE) { + if (!Utils.typeEquals(genericType, parameter.getActualType())) { + return false; + } + } + } + return true; + } + + private static Map> groupShortCircuits(List shortCircuits) { + Map> group = new HashMap<>(); + for (ShortCircuitData shortCircuit : shortCircuits) { + List circuits = group.get(shortCircuit.getValueName()); + if (circuits == null) { + circuits = new ArrayList<>(); + group.put(shortCircuit.getValueName(), circuits); + } + circuits.add(shortCircuit); + } + return group; + } + + private boolean verifyNamingConvention(List methods, String prefix) { + boolean valid = true; + for (int i = 0; i < methods.size(); i++) { + TemplateMethod m1 = methods.get(i); + if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) { + log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Naming convention: method name must start with '%s'.", prefix); + valid = false; + } + } + return valid; + } + + private boolean verifyNamesUnique(List methods) { + boolean valid = true; + for (int i = 0; i < methods.size(); i++) { + TemplateMethod m1 = methods.get(i); + for (int j = i + 1; j < methods.size(); j++) { + TemplateMethod m2 = methods.get(j); + + if (m1.getMethodName().equalsIgnoreCase(m2.getMethodName())) { + log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName()); + log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Method name '%s' used multiple times", m1.getMethodName()); + return false; + } + } + } + return valid; + } + + private boolean verifySpecializationOrder(TypeSystemData typeSystem, List specializations) { + for (int i = 0; i < specializations.size(); i++) { + SpecializationData m1 = specializations.get(i); + for (int j = i + 1; j < specializations.size(); j++) { + SpecializationData m2 = specializations.get(j); + int inferredOrder = compareSpecializationWithoutOrder(typeSystem, m1, m2); + + if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { + int specOrder = m1.getOrder() - m2.getOrder(); + if (specOrder == 0) { + log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder()); + log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Order value %d used multiple times", m1.getOrder()); + return false; + } else if ((specOrder < 0 && inferredOrder > 0) || (specOrder > 0 && inferredOrder < 0)) { + log.error(m1.getMethod(), m1.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + log.error(m2.getMethod(), m2.getMarkerAnnotation(), "Explicit order values %d and %d are inconsistent with type lattice ordering.", m1.getOrder(), m2.getOrder()); + return false; + } + } else if (inferredOrder == 0) { + SpecializationData m = (m1.getOrder() == Specialization.DEFAULT_ORDER ? m1 : m2); + log.error(m.getMethod(), m.getMarkerAnnotation(), "Cannot calculate a consistent order for this specialization. Define the order attribute to resolve this."); + return false; + } + } + } + return true; + } + + private static int compareSpecialization(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) { + int result = compareSpecializationWithoutOrder(typeSystem, m1, m2); + if (result == 0) { + if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { + return m1.getOrder() - m2.getOrder(); + } + } + return result; + } + + private static int compareSpecializationWithoutOrder(TypeSystemData typeSystem, SpecializationData m1, SpecializationData m2) { + if (m1.getSpecification() != m2.getSpecification()) { + throw new UnsupportedOperationException("Cannot compare two specializations with different specifications."); + } + + int result = compareActualParameter(typeSystem, m1.getReturnType(), m2.getReturnType()); + + for (ParameterSpec spec : m1.getSpecification().getParameters()) { + ActualParameter p1 = m1.findParameter(spec); + ActualParameter p2 = m2.findParameter(spec); + + if (p1 != null && p2 != null && !Utils.typeEquals(p1.getActualType(), p2.getActualType())) { + int typeResult = compareActualParameter(typeSystem, p1, p2); + if (result == 0) { + result = typeResult; + } else if (Math.signum(result) != Math.signum(typeResult)) { + // We cannot define an order. + return 0; + } + } + } + return result; + } + + private static int compareActualParameter(TypeSystemData typeSystem, ActualParameter p1, ActualParameter p2) { + int index1 = typeSystem.findType(p1.getActualType()); + int index2 = typeSystem.findType(p2.getActualType()); + + assert index1 != index2; + assert !(index1 == -1 ^ index2 == -1); + + return index1 - index2; + } + + private boolean verifyNames(TypeElement element, AnnotationMirror mirror, List names) { + boolean valid = true; + + for (int i = 0; i < names.size(); i++) { + String name = names.get(i); + if (!JavaName.isValid(name)) { + log.error(element, mirror, "Name '%s' is not a valid java identifier.", name); + valid = false; + } else if (JavaName.isReserved(name)) { + log.error(element, mirror, "Name '%s' is a reserved java identifier.", name); + valid = false; + } + for (int j = i + 1; j < names.size(); j++) { + String otherName = names.get(j); + if (name.equalsIgnoreCase(otherName)) { + log.error(element, mirror, "Name '%s' is not unique.", name); + valid = false; + } + } + } + return valid; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + + +public class ShortCircuitData extends TemplateMethod { + + private ShortCircuitData genericShortCircuitMethod; + + private final String valueName; + + public ShortCircuitData(TemplateMethod template, String valueName) { + super(template); + this.valueName = valueName; + } + + public String getValueName() { + return valueName; + } + + public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) { + this.genericShortCircuitMethod = genericShortCircuitMethod; + } + + public boolean isGeneric() { + return genericShortCircuitMethod == null; + } + + public ShortCircuitData getGeneric() { + if (isGeneric()) { + return this; + } else { + return genericShortCircuitMethod; + } + } + + public boolean isCompatibleTo(SpecializationData specialization) { + if (isGeneric() && specialization.isGeneric()) { + return true; + } + + for (ActualParameter param : getParameters()) { + ParameterSpec paramSpec = param.getSpecification(); + if (paramSpec.getKind() == Kind.EXECUTE) { + ActualParameter specializationParam = specialization.findParameter(paramSpec.getName()); + if (!Utils.typeEquals(param.getActualType(), specializationParam.getActualType())) { + return false; + } + } + } + return true; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/ShortCircuitParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + + +public class ShortCircuitParser extends OperationMethodParser { + + private final Set shortCircuitValues; + + public ShortCircuitParser(ProcessorContext context, OperationData operation) { + super(context, operation); + shortCircuitValues = new HashSet<>(Arrays.asList(operation.getShortCircuitValues())); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + String shortCircuitValue = Utils.getAnnotationValueString(mirror, "value"); + + if (!shortCircuitValues.contains(shortCircuitValue)) { + getContext().getLog().error(method, mirror, "Invalid short circuit value %s.", shortCircuitValue); + return null; + } + + return createDefaultMethodSpec(shortCircuitValue); + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("has", getContext().getType(boolean.class), Kind.SHORT_CIRCUIT, false); + } + + @Override + public ShortCircuitData create(TemplateMethod method) { + String shortCircuitValue = Utils.getAnnotationValueString(method.getMarkerAnnotation(), "value"); + assert shortCircuitValue != null; + assert shortCircuitValues.contains(shortCircuitValue); + return new ShortCircuitData(method, shortCircuitValue); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return ShortCircuit.class; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.template.*; + +public class SpecializationData extends TemplateMethod { + + private final int order; + private final boolean generic; + private final boolean uninitialized; + private final SpecializationThrowsData[] exceptions; + private SpecializationGuardData[] guards; + private ShortCircuitData[] shortCircuits; + + private OperationData operation; + + public SpecializationData(TemplateMethod template, int order, SpecializationThrowsData[] exceptions) { + super(template.getSpecification(), template.getMethod(), template.getMarkerAnnotation(), template.getReturnType(), template.getParameters()); + this.order = order; + this.generic = false; + this.uninitialized = false; + this.exceptions = exceptions; + + for (SpecializationThrowsData exception : exceptions) { + exception.setSpecialization(this); + } + } + + public SpecializationData(TemplateMethod template, boolean generic, boolean uninitialized) { + super(template.getSpecification(), template.getMethod(), template.getMarkerAnnotation(), template.getReturnType(), template.getParameters()); + this.order = Specialization.DEFAULT_ORDER; + this.generic = generic; + this.uninitialized = uninitialized; + this.exceptions = new SpecializationThrowsData[0]; + this.guards = new SpecializationGuardData[0]; + } + + public void setOperation(OperationData operation) { + this.operation = operation; + } + + void setGuards(SpecializationGuardData[] guards) { + this.guards = guards; + } + + public OperationData getOperation() { + return operation; + } + + public int getOrder() { + return order; + } + + public boolean isGeneric() { + return generic; + } + + public boolean isUninitialized() { + return uninitialized; + } + + public SpecializationThrowsData[] getExceptions() { + return exceptions; + } + + public SpecializationGuardData[] getGuards() { + return guards; + } + + public void setShortCircuits(ShortCircuitData[] shortCircuits) { + this.shortCircuits = shortCircuits; + } + + public ShortCircuitData[] getShortCircuits() { + return shortCircuits; + } + + public SpecializationData findNextSpecialization() { + SpecializationData[] allMethods = operation.getAllMethods(); + for (int i = 0; i < allMethods.length - 1; i++) { + if (allMethods[i] == this) { + return allMethods[i + 1]; + } + } + throw new IllegalArgumentException(); + } + + public boolean hasDynamicGuards() { + for (SpecializationGuardData guard : getGuards()) { + if (guard.isOnExecution()) { + return true; + } + } + return false; + } + + public ActualParameter getPreviousParam(ActualParameter searchParam) { + ActualParameter prev = null; + for (ActualParameter param : getParameters()) { + if (param == searchParam) { + return prev; + } + prev = param; + } + return prev; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationGuardData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationGuardData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import com.oracle.truffle.codegen.processor.typesystem.*; + +public class SpecializationGuardData { + + private final String guardMethod; + private final boolean onSpecialization; + private final boolean onExecution; + + private GuardData guardDeclaration; + + public SpecializationGuardData(String guardMethod, boolean onSpecialization, boolean onExecution) { + this.guardMethod = guardMethod; + this.onSpecialization = onSpecialization; + this.onExecution = onExecution; + } + + public String getGuardMethod() { + return guardMethod; + } + + public boolean isOnExecution() { + return onExecution; + } + + public boolean isOnSpecialization() { + return onSpecialization; + } + + void setGuardDeclaration(GuardData compatibleGuard) { + this.guardDeclaration = compatibleGuard; + } + + public GuardData getGuardDeclaration() { + return guardDeclaration; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationListenerParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationListenerParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import java.lang.annotation.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + + +public class SpecializationListenerParser extends OperationMethodParser { + + private final MethodSpec specification; + + public SpecializationListenerParser(ProcessorContext context, OperationData operation) { + super(context, operation); + this.specification = createDefaultMethodSpec(null); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + return specification; + } + + @Override + protected ParameterSpec createReturnParameterSpec() { + return new ParameterSpec("void", getContext().getType(void.class), Kind.ATTRIBUTE, false); + } + + @Override + public TemplateMethod create(TemplateMethod method) { + return method; + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return SpecializationListener.class; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; +import com.oracle.truffle.codegen.processor.typesystem.*; + + +public class SpecializationParser extends OperationMethodParser { + + private final MethodSpec specification; + + public SpecializationParser(ProcessorContext context, OperationData operation) { + super(context, operation); + this.specification = createDefaultMethodSpec(null); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + return specification; + } + public MethodSpec getSpecification() { + return specification; + } + + @Override + public SpecializationData create(TemplateMethod method) { + return parseSpecialization(method); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return Specialization.class; + } + + private SpecializationData parseSpecialization(TemplateMethod template) { + int order = Utils.getAnnotationValueInt(template.getMarkerAnnotation(), "order"); + if (order < 0 && order != Specialization.DEFAULT_ORDER) { + getContext().getLog().error(template.getMethod(), template.getMarkerAnnotation(), "Invalid order attribute %d. The value must be >= 0 or the default value."); + return null; + } + + List exceptionDefs = Utils.collectAnnotations(getContext(), template.getMarkerAnnotation(), "exceptions", template.getMethod(), SpecializationThrows.class); + SpecializationThrowsData[] exceptionData = new SpecializationThrowsData[exceptionDefs.size()]; + for (int i = 0; i < exceptionData.length; i++) { + AnnotationMirror mirror = exceptionDefs.get(i); + TypeMirror javaClass = Utils.getAnnotationValueType(mirror, "javaClass"); + String transitionTo = Utils.getAnnotationValueString(mirror, "transitionTo"); + exceptionData[i] = new SpecializationThrowsData(mirror, javaClass, transitionTo); + + if (!Utils.canThrowType(template.getMethod().getThrownTypes(), javaClass)) { + getContext().getLog().error(template.getMethod(), "Method must specify a throws clause with the exception type '%s'.", Utils.getQualifiedName(javaClass)); + return null; + } + } + + Arrays.sort(exceptionData, new Comparator() { + @Override + public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) { + return Utils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass()); + } + }); + SpecializationData specialization = new SpecializationData(template, order, exceptionData); + + boolean valid = true; + List guardDefs = Utils.collectAnnotations(getContext(), template.getMarkerAnnotation(), "guards", template.getMethod(), SpecializationGuard.class); + SpecializationGuardData[] guardData = new SpecializationGuardData[guardDefs.size()]; + for (int i = 0; i < guardData.length; i++) { + AnnotationMirror guardMirror = guardDefs.get(i); + String guardMethod = Utils.getAnnotationValueString(guardMirror, "methodName"); + boolean onSpecialization = Utils.getAnnotationValueBoolean(guardMirror, "onSpecialization"); + boolean onExecution = Utils.getAnnotationValueBoolean(guardMirror, "onExecution"); + + if (!onSpecialization && !onExecution) { + String message = "Either onSpecialization, onExecution or both must be enabled."; + getContext().getLog().error(template.getMethod(), guardMirror, message); + valid = false; + continue; + } + + guardData[i] = new SpecializationGuardData(guardMethod, onSpecialization, onExecution); + + GuardData compatibleGuard = matchSpecializationGuard(guardMirror, specialization, guardData[i]); + if (compatibleGuard != null) { + guardData[i].setGuardDeclaration(compatibleGuard); + } else { + valid = false; + } + } + + if (!valid) { + return null; + } + + specialization.setGuards(guardData); + + return specialization; + } + + private GuardData matchSpecializationGuard(AnnotationMirror mirror, SpecializationData specialization, SpecializationGuardData specializationGuard) { + List foundGuards = getOperation().findGuards(specializationGuard.getGuardMethod()); + GuardData compatibleGuard = null; + for (GuardData guardData : foundGuards) { + if (isGuardCompatible(specialization, guardData)) { + compatibleGuard = guardData; + break; + } + } + + if (compatibleGuard == null) { + ParameterSpec returnTypeSpec = new ParameterSpec("returnValue", getContext().getType(boolean.class), Kind.ATTRIBUTE, false); + List expectedParameterSpecs = new ArrayList<>(); + + for (ActualParameter param : filterGuardParameters(specialization)) { + ParameterSpec spec = param.getSpecification(); + expectedParameterSpecs.add(new ParameterSpec(spec.getName(), param.getActualType(), Kind.ATTRIBUTE, false)); + } + String expectedSignature = TemplateMethodParser.createExpectedSignature(specializationGuard.getGuardMethod(), returnTypeSpec, expectedParameterSpecs); + AnnotationValue value = Utils.getAnnotationValue(mirror, "methodName"); + getContext().getLog().error(specialization.getMethod(), mirror, value, "No guard with signature '%s' found in type system.", expectedSignature); + return null; + } + + return compatibleGuard; + } + + private static boolean isGuardCompatible(SpecializationData specialization, GuardData guard) { + Iterator guardParameters = Arrays.asList(guard.getParameters()).iterator(); + for (ActualParameter param : filterGuardParameters(specialization)) { + if (!guardParameters.hasNext()) { + return false; + } + ActualParameter guardParam = guardParameters.next(); + if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType())) { + return false; + } + } + if (guardParameters.hasNext()) { + return false; + } + return true; + } + + private static List filterGuardParameters(SpecializationData specialization) { + List parameters = new ArrayList<>(); + for (ActualParameter param : specialization.getParameters()) { + if (param.getSpecification().getKind() != Kind.EXECUTE + && param.getSpecification().getKind() != Kind.SHORT_CIRCUIT) { + continue; + } + parameters.add(param); + } + return parameters; + } + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationThrowsData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/operation/SpecializationThrowsData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.operation; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +public class SpecializationThrowsData { + + private final AnnotationMirror annotationMirror; + private final TypeMirror javaClass; + private final String transitionTo; + private SpecializationData specialization; + + public SpecializationThrowsData(AnnotationMirror annotationMirror, TypeMirror javaClass, String transitionTo) { + this.annotationMirror = annotationMirror; + this.javaClass = javaClass; + this.transitionTo = transitionTo; + } + + + void setSpecialization(SpecializationData specialization) { + this.specialization = specialization; + } + + public TypeMirror getJavaClass() { + return javaClass; + } + + public SpecializationData getSpecialization() { + return specialization; + } + + public AnnotationMirror getAnnotationMirror() { + return annotationMirror; + } + + public String getTransitionToName() { + return transitionTo; + } + + public SpecializationData getTransitionTo() { + for (SpecializationData s : specialization.getOperation().getAllMethods()) { + if (s.getMethodName().equals(transitionTo)) { + return s; + } + } + throw new IllegalArgumentException(); + } +} + diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.typesystem.*; + +public class ActualParameter { + + private final ParameterSpec specification; + private final TypeMirror actualType; + + public ActualParameter(ParameterSpec specification, TypeMirror actualType) { + this.specification = specification; + this.actualType = actualType; + } + + public ParameterSpec getSpecification() { + return specification; + } + + public TypeMirror getActualType() { + return actualType; + } + + public TypeData getActualTypeData(TypeSystemData typeSystem) { + return typeSystem.getTypes()[typeSystem.findType(actualType)]; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ClassElementFactory.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import static com.oracle.truffle.codegen.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; + +public abstract class ClassElementFactory extends CodeElementFactory { + + public ClassElementFactory(ProcessorContext context) { + super(context); + } + + @Override + protected abstract CodeTypeElement create(M m); + + protected CodeExecutableElement createConstructorUsingFields(Set modifiers, CodeTypeElement clazz) { + CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString()); + CodeTreeBuilder builder = method.createBuilder(); + TypeElement superClass = fromTypeMirror(clazz.getSuperclass()); + ExecutableElement constructor = findConstructor(superClass); + if (constructor != null && constructor.getParameters().size() > 0) { + builder.startStatement(); + builder.startSuperCall(); + for (VariableElement parameter : constructor.getParameters()) { + method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString())); + builder.string(parameter.getSimpleName().toString()); + } + builder.end(); // super + builder.end(); // statement + } + + for (VariableElement field : clazz.getFields()) { + if (field.getModifiers().contains(STATIC)) { + continue; + } + String fieldName = field.getSimpleName().toString(); + method.addParameter(new CodeVariableElement(field.asType(), fieldName)); + builder.startStatement(); + builder.string("this."); + builder.string(fieldName); + builder.string(" = "); + if (isAssignable(field.asType(), getContext().getTruffleTypes().getNode())) { + builder.string("adoptChild(").string(fieldName).string(")"); + } else { + builder.string(fieldName); + } + builder.end(); // statement + } + + return method; + } + + private static ExecutableElement findConstructor(TypeElement clazz) { + List constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements()); + if (constructors.isEmpty()) { + return null; + } else { + return constructors.get(0); + } + } + + protected CodeTypeElement createClass(Template model, Set modifiers, String simpleName, TypeMirror superType, boolean enumType) { + TypeElement templateType = model.getTemplateType(); + + PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType); + CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName); + TypeMirror resolvedSuperType = superType; + if (resolvedSuperType == null) { + resolvedSuperType = getContext().getType(Object.class); + } + clazz.setSuperClass(resolvedSuperType); + + CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class)); + generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType())); + clazz.addAnnotationMirror(generatedByAnnotation); + + context.registerType(model.getTemplateType(), clazz.asType()); + + return clazz; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CodeElementFactory.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; + +public abstract class CodeElementFactory { + + protected final ProcessorContext context; + private M model; + + private CodeElement element; + + public CodeElementFactory(ProcessorContext context) { + this.context = context; + } + + protected abstract CodeElement create(M m); + + @SuppressWarnings("unused") + protected void createChildren(M m) { } + + @SuppressWarnings("unchecked") + public final CodeElement process(M m) { + model = m; + element = (CodeElement) create(model); + if (element != null) { + createChildren(model); + } + return element; + } + + public CodeElement getElement() { + return element; + } + + protected void add(CodeElementFactory factory, MO m) { + this.element.add(factory.process(m)); + } + + public ProcessorContext getContext() { + return context; + } + + public M getModel() { + return model; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/CompilationUnitFactory.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; + +public abstract class CompilationUnitFactory extends CodeElementFactory { + + public CompilationUnitFactory(ProcessorContext context) { + super(context); + } + + @Override + public final CodeCompilationUnit create(M m) { + return new CodeCompilationUnit(); + } + + @Override + protected abstract void createChildren(M m); + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/JavaName.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/JavaName.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import java.util.*; +import java.util.regex.*; + + +public final class JavaName { + + private static final String[] RESERVED_NAMES = new String[]{"abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", "if", + "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", + "while"}; + + private static final Set RESERVED_NAMES_SET = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(RESERVED_NAMES))); + + private static final Pattern VALID_JAVA_NAME_PATTERN = Pattern.compile("[_a-zA-z][_a-zA-Z0-9]*"); + + private JavaName() { + super(); + } + + public static boolean isReserved(String name) { + return RESERVED_NAMES_SET.contains(name); + } + + public static boolean isValid(String typeName) { + return VALID_JAVA_NAME_PATTERN.matcher(typeName).matches(); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import java.util.*; + +public class MethodSpec { + + private final ParameterSpec returnType; + private final List parameters; + + public MethodSpec(ParameterSpec returnType, List parameters) { + this.returnType = returnType; + this.parameters = parameters; + } + + public ParameterSpec getReturnType() { + return returnType; + } + + public List getParameters() { + return parameters; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.typesystem.*; + +public class ParameterSpec { + + public enum Kind { + EXECUTE, SIGNATURE, SUPER_ATTRIBUTE, ATTRIBUTE, CONSTRUCTOR_FIELD, SHORT_CIRCUIT + } + + public enum Cardinality { + ONE, MULTIPLE; + } + + private final String name; + private final TypeMirror[] allowedTypes; + private final TypeMirror valueType; + private final Kind kind; + private final boolean optional; + private final Cardinality cardinality; + + public ParameterSpec(String name, TypeMirror[] allowedTypes, TypeMirror valueType, Kind kind, boolean optional, Cardinality cardinality) { + this.valueType = valueType; + this.allowedTypes = allowedTypes; + this.name = name; + this.kind = kind; + this.optional = optional; + this.cardinality = cardinality; + } + + public ParameterSpec(String name, TypeMirror singleFixedType, Kind kind, boolean optional) { + this(name, new TypeMirror[]{singleFixedType}, singleFixedType, kind, optional, Cardinality.ONE); + } + + public ParameterSpec(String name, TypeSystemData typeSystem, Kind kind, boolean optional, Cardinality cardinality) { + this(name, typeSystem.getPrimitiveTypeMirrors(), typeSystem.getGenericType(), kind, optional, cardinality); + } + + public final String getName() { + return name; + } + + public Kind getKind() { + return kind; + } + + public final boolean isOptional() { + return optional; + } + + public final Cardinality getCardinality() { + return cardinality; + } + + public TypeMirror[] getAllowedTypes() { + return allowedTypes; + } + + public boolean matches(TypeMirror actualType) { + for (int i = 0; i < allowedTypes.length; i++) { + TypeMirror mirror = allowedTypes[i]; + if (Utils.typeEquals(actualType, mirror)) { + return true; + } + } + return false; + } + + public TypeMirror getValueType() { + return valueType; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/Template.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.api.element.*; + +public abstract class Template { + + private final TypeElement templateType; + private final AnnotationMirror annotation; + + private List extensionElements; + + public Template(TypeElement templateType, AnnotationMirror annotation) { + this.templateType = templateType; + this.annotation = annotation; + } + + public TypeElement getTemplateType() { + return templateType; + } + + public AnnotationMirror getTemplateTypeAnnotation() { + return annotation; + } + + public List< ? extends WritableElement> getExtensionElements() { + return extensionElements; + } + + public void setExtensionElements(List< ? extends WritableElement> extensionMethods) { + this.extensionElements = extensionMethods; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + Utils.getSimpleName(getTemplateType()) + "]"; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import javax.lang.model.element.*; + +public class TemplateMethod { + + private final MethodSpec specification; + private final ExecutableElement method; + private final AnnotationMirror markerAnnotation; + private final ActualParameter returnType; + private final ActualParameter[] parameters; + + public TemplateMethod(MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType, ActualParameter[] parameters) { + this.specification = specification; + this.method = method; + this.markerAnnotation = markerAnnotation; + this.returnType = returnType; + this.parameters = parameters; + } + + public TemplateMethod(TemplateMethod method) { + this.specification = method.specification; + this.method = method.method; + this.markerAnnotation = method.markerAnnotation; + this.returnType = method.returnType; + this.parameters = method.parameters; + } + + + public MethodSpec getSpecification() { + return specification; + } + + public ActualParameter getReturnType() { + return returnType; + } + + public ActualParameter[] getParameters() { + return parameters; + } + + public ActualParameter findParameter(String valueName) { + for (ActualParameter param : getParameters()) { + if (param.getSpecification().getName().equals(valueName)) { + return param; + } + } + return null; + } + + public ActualParameter findParameter(ParameterSpec spec) { + for (ActualParameter param : getParameters()) { + if (param.getSpecification() == spec) { + return param; + } + } + return null; + } + + public ExecutableElement getMethod() { + return method; + } + + public String getMethodName() { + return getMethod().getSimpleName().toString(); + } + + public AnnotationMirror getMarkerAnnotation() { + return markerAnnotation; + } + + @Override + public String toString() { + return getClass().getSimpleName() + " [method = " + method + "]"; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import static com.oracle.truffle.codegen.processor.Utils.*; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; + +public abstract class TemplateMethodParser { + + private final ProcessorContext context; + + public TemplateMethodParser(ProcessorContext context) { + this.context = context; + } + + public ProcessorContext getContext() { + return context; + } + + public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); + + public abstract E create(TemplateMethod method); + + public abstract Class getAnnotationType(); + + public final E parse(ExecutableElement method, AnnotationMirror annotation, Template template) { + MethodSpec methodSpecification = createSpecification(method, annotation); + if (methodSpecification == null) { + return null; + } + + ParameterSpec returnTypeSpec = methodSpecification.getReturnType(); + List parameterSpecs = new ArrayList<>(); + parameterSpecs.addAll(methodSpecification.getParameters()); + + ActualParameter returnTypeMirror = resolveTypeMirror(returnTypeSpec, method.getReturnType(), template); + if (returnTypeMirror == null) { + String expectedReturnType = createTypeSignature(returnTypeSpec, true); + String actualReturnType = Utils.getSimpleName(method.getReturnType()); + + String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, + createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs)); + + context.getLog().error(method, annotation, message); + return null; + } + + Iterator< ? extends VariableElement> variableIterator = method.getParameters().iterator(); + Iterator< ? extends ParameterSpec> specificationIterator = parameterSpecs.iterator(); + + List resolvedMirrors = new ArrayList<>(); + VariableElement parameter = null; + ParameterSpec specification = null; + while (specificationIterator.hasNext() || specification != null) { + if (specification == null) { + specification = specificationIterator.next(); + } + + if (parameter == null && variableIterator.hasNext()) { + parameter = variableIterator.next(); + } + + if (parameter == null) { + if (specification.getCardinality() == Cardinality.MULTIPLE) { + specification = null; + continue; + } else if (!specification.isOptional()) { + // non option type specification found -> argument missing + String expectedType = createTypeSignature(specification, false); + + String message = String.format("Missing argument \"%s\".\nExpected signature: \n %s", expectedType, + createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs)); + + context.getLog().error(method, message); + return null; + } else { + // specification is optional -> continue + specification = null; + continue; + } + } + + ActualParameter resolvedMirror = resolveTypeMirror(specification, parameter.asType(), template); + + if (resolvedMirror == null) { + if (specification.isOptional()) { + specification = null; + continue; + } + + String expectedReturnType = createTypeSignature(specification, false); + String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName(); + + String message = String.format("The provided argument type \"%s\" does not match expected type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType, + createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs)); + + context.getLog().error(parameter, message); + return null; + } + + resolvedMirrors.add(resolvedMirror); + parameter = null; // consume parameter + + if (specification.getCardinality() != Cardinality.MULTIPLE) { + specification = null; + } + } + + if (variableIterator.hasNext()) { + parameter = variableIterator.next(); + String actualReturnType = Utils.getSimpleName(parameter.asType()) + " " + parameter.getSimpleName(); + String message = String.format("No argument expected but found \"%s\".\nExpected signature: \n %s", actualReturnType, + createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs)); + + context.getLog().error(parameter, message); + return null; + } + + ActualParameter[] paramMirrors = resolvedMirrors.toArray(new ActualParameter[resolvedMirrors.size()]); + return create(new TemplateMethod(methodSpecification, method, annotation, returnTypeMirror, paramMirrors)); + } + + private ActualParameter resolveTypeMirror(ParameterSpec specification, TypeMirror mirror, Template typeSystem) { + TypeMirror resolvedType = mirror; + if (hasError(resolvedType)) { + resolvedType = context.resolveNotYetCompiledType(mirror, typeSystem); + } + + if (!specification.matches(resolvedType)) { + return null; + } + return new ActualParameter(specification, resolvedType); + } + + public static String createExpectedSignature(String methodName, ParameterSpec returnType, List< ? extends ParameterSpec> parameters) { + StringBuilder b = new StringBuilder(); + + b.append(" "); + b.append(createTypeSignature(returnType, true)); + + b.append(" "); + b.append(methodName); + b.append("("); + + for (int i = 0; i < parameters.size(); i++) { + ParameterSpec specification = parameters.get(i); + if (specification.isOptional()) { + b.append("["); + } + if (specification.getCardinality() == Cardinality.MULTIPLE) { + b.append("{"); + } + + b.append(createTypeSignature(specification, false)); + + if (specification.isOptional()) { + b.append("]"); + } + + if (specification.getCardinality() == Cardinality.MULTIPLE) { + b.append("}"); + } + + if (i < parameters.size() - 1) { + b.append(", "); + } + + } + + b.append(")"); + + TypeMirror[] types = null; + + //TODO allowed types may differ so different must be generated. + if (returnType.getAllowedTypes().length > 1) { + types = returnType.getAllowedTypes(); + } + for (ParameterSpec param : parameters) { + if (param.getAllowedTypes().length > 1) { + types = param.getAllowedTypes(); + } + } + if (types != null) { + b.append("\n\n "); + b.append(" = {"); + String separator = ""; + for (TypeMirror type : types) { + b.append(separator).append(Utils.getSimpleName(type)); + separator = ", "; + } + b.append("}"); + } + return b.toString(); + } + + private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) { + StringBuilder builder = new StringBuilder(); + if (spec.getAllowedTypes().length > 1) { + builder.append(""); + } else if (spec.getAllowedTypes().length == 1) { + builder.append(Utils.getSimpleName(spec.getAllowedTypes()[0])); + } else { + builder.append("void"); + } + if (!typeOnly) { + builder.append(" "); + builder.append(spec.getName()); + } + return builder.toString(); + } + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.template; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.api.element.*; +import com.oracle.truffle.codegen.processor.ext.*; + +public abstract class TemplateParser extends AbstractParser { + + private final ExtensionParser extensionParser; + + public TemplateParser(ProcessorContext c) { + super(c); + extensionParser = new ExtensionParser(c); + } + + public ExtensionParser getExtensionParser() { + return extensionParser; + } + + protected boolean verifyExclusiveMethodAnnotation(TypeElement type, Class ... annotationTypes) { + boolean valid = true; + List methods = ElementFilter.methodsIn(type.getEnclosedElements()); + for (ExecutableElement method : methods) { + List foundAnnotations = new ArrayList<>(); + for (int i = 0; i < annotationTypes.length; i++) { + Class annotationType = annotationTypes[i]; + AnnotationMirror mirror = Utils.findAnnotationMirror(context.getEnvironment(), method, annotationType); + if (mirror != null) { + foundAnnotations.add(mirror); + } + } + if (foundAnnotations.size() > 1) { + List annotationNames = new ArrayList<>(); + for (AnnotationMirror mirror : foundAnnotations) { + annotationNames.add("@" + Utils.getSimpleName(mirror.getAnnotationType())); + } + + for (AnnotationMirror mirror : foundAnnotations) { + context.getLog().error(method, mirror, "Non exclusive usage of annotations %s.", annotationNames); + } + valid = false; + } + } + return valid; + } + + protected boolean verifyTemplateType(TypeElement template, AnnotationMirror annotation) { + // annotation type on class path!? + boolean valid = true; + TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName()); + if (annotationTypeElement == null) { + log.error(template, annotation, "Required class " + getAnnotationType().getName() + " is not on the classpath."); + valid = false; + } + if (template.getModifiers().contains(Modifier.PRIVATE)) { + log.error(template, annotation, "The annotated class must have at least package protected visibility."); + valid = false; + } + + if (template.getModifiers().contains(Modifier.FINAL)) { + log.error(template, annotation, "The annotated class must not be final."); + valid = false; + } + + return valid; + } + + protected List parseMethods(Template template, TemplateMethodParser parser) { + TypeElement type = template.getTemplateType(); + + List methods = new ArrayList<>(); + methods.addAll(ElementFilter.methodsIn(type.getEnclosedElements())); + if (template.getExtensionElements() != null) { + for (WritableElement e : template.getExtensionElements()) { + if (e instanceof ExecutableElement) { + methods.add((ExecutableElement) e); + } + } + } + + List parsedMethods = new ArrayList<>(); + boolean valid = true; + for (ExecutableElement method : methods) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, parser.getAnnotationType()); + if (mirror != null) { + if (method.getModifiers().contains(Modifier.PRIVATE)) { + log.error(method, "Methods annotated with @%s must not be private.", parser.getAnnotationType().getSimpleName()); + valid = false; + continue; + } + E parsedMethod = parser.parse(method, mirror, template); + if (parsedMethod != null) { + parsedMethods.add(parsedMethod); + } else { + valid = false; + } + } + } + if (!valid) { + return null; + } + return parsedMethods; + } + + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import com.oracle.truffle.codegen.processor.template.*; + + +public class GuardData extends TemplateMethod { + + private final Template origin; + + public GuardData(TemplateMethod method, Template origin) { + super(method); + this.origin = origin; + } + + public Template getOrigin() { + return origin; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + + +public class GuardParser extends TypeSystemMethodParser { + + private final Template origin; + + public GuardParser(ProcessorContext context, TypeSystemData typeSystem, Template origin) { + super(context, typeSystem); + this.origin = origin; + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + List specs = new ArrayList<>(); + specs.add(new ParameterSpec("value1", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE)); + specs.add(new ParameterSpec("valueN", getTypeSystem(), Kind.EXECUTE, false, Cardinality.MULTIPLE)); + ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), Kind.ATTRIBUTE, false); + return new MethodSpec(returnTypeSpec, specs); + } + + @Override + public GuardData create(TemplateMethod method) { + return new GuardData(method, origin); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return GuardCheck.class; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import com.oracle.truffle.codegen.processor.template.*; + +public class TypeCastData extends TemplateMethod { + + private final TypeData targetType; + private final TypeData sourceType; + + public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) { + super(method); + this.sourceType = sourceType; + this.targetType = targetType; + } + + public boolean isGeneric() { + return sourceType.isGeneric(); + } + + public TypeData getSourceType() { + return sourceType; + } + + public TypeData getTargetType() { + return targetType; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + + +class TypeCastParser extends TypeSystemMethodParser { + + public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + TypeData targetType = findTypeByMethodName(method, mirror, "as"); + if (targetType == null) { + return null; + } + List specs = new ArrayList<>(); + specs.add(new ParameterSpec("value", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE)); + ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType(), Kind.ATTRIBUTE, false); + MethodSpec spec = new MethodSpec(returnTypeSpec, specs); + return spec; + } + + @Override + public TypeCastData create(TemplateMethod method) { + TypeData targetType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "as"); + ActualParameter parameter = method.findParameter("value"); + return new TypeCastData(method, parameter.getActualTypeData(getTypeSystem()), targetType); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return TypeCast.class; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import com.oracle.truffle.codegen.processor.template.*; + +public class TypeCheckData extends TemplateMethod { + + private final TypeData checkedType; + private final TypeData valueType; + + public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) { + super(method); + this.checkedType = checkedType; + this.valueType = valueType; + } + + public boolean isGeneric() { + return valueType.isGeneric(); + } + + public TypeData getCheckedType() { + return checkedType; + } + + public TypeData getValueType() { + return valueType; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.Kind; + +class TypeCheckParser extends TypeSystemMethodParser { + + public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + TypeData targetType = findTypeByMethodName(method, mirror, "is"); + if (targetType == null) { + return null; + } + List specs = new ArrayList<>(); + specs.add(new ParameterSpec("value", getTypeSystem(), Kind.EXECUTE, false, Cardinality.ONE)); + ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), Kind.ATTRIBUTE, false); + MethodSpec spec = new MethodSpec(returnTypeSpec, specs); + return spec; + } + + @Override + public TypeCheckData create(TemplateMethod method) { + TypeData checkedType = findTypeByMethodName(method.getMethod(), method.getMarkerAnnotation(), "is"); + assert checkedType != null; + ActualParameter parameter = method.findParameter("value"); + assert parameter != null; + return new TypeCheckData(method, checkedType, parameter.getActualTypeData(getTypeSystem())); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return TypeCheck.class; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; + +public class TypeData extends Template { + + protected TypeSystemData typeSystem; + private final TypeMirror primitiveType; + private final TypeMirror boxedType; + + private final List typeCasts = new ArrayList<>(); + private final List typeChecks = new ArrayList<>(); + + public TypeData(TypeElement templateType, AnnotationMirror annotation, + TypeMirror primitiveType, TypeMirror boxedType) { + super(templateType, annotation); + this.primitiveType = primitiveType; + this.boxedType = boxedType; + } + + void addTypeCast(TypeCastData typeCast) { + this.typeCasts.add(typeCast); + } + + void addTypeCheck(TypeCheckData typeCheck) { + this.typeChecks.add(typeCheck); + } + + public List getTypeCasts() { + return typeCasts; + } + + public List getTypeChecks() { + return typeChecks; + } + + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + public TypeMirror getPrimitiveType() { + return primitiveType; + } + + public TypeMirror getBoxedType() { + return boxedType; + } + + public boolean isGeneric() { + return Utils.typeEquals(boxedType, getTypeSystem().getGenericType()); + } + + public boolean isVoid() { + if (getTypeSystem().getVoidType() == null) { + return false; + } + return Utils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType()); + } +} + diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import static com.oracle.truffle.codegen.processor.Utils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.ast.*; +import com.oracle.truffle.codegen.processor.template.*; + +public class TypeSystemCodeGenerator extends CompilationUnitFactory { + + public TypeSystemCodeGenerator(ProcessorContext context) { + super(context); + } + + public static String isTypeMethodName(TypeData type) { + return "is" + Utils.getSimpleName(type.getBoxedType()); + } + + public static String asTypeMethodName(TypeData type) { + return "as" + Utils.getSimpleName(type.getBoxedType()); + } + + public static String expectTypeMethodName(TypeData type) { + return "expect" + Utils.getSimpleName(type.getBoxedType()); + } + + /** + * Finds the generated singleton field for a TypeSytemData instance. TypeSystemCodeGenerator must be applied to the + * TypeSystemData model before use. + */ + public static VariableElement findSingleton(ProcessorContext context, TypeSystemData typeSystem) { + TypeMirror type = context.findGeneratedClassBySimpleName(TypeClassFactory.typeName(typeSystem), typeSystem); + return Utils.findDeclaredField(type, TypeClassFactory.singletonName(typeSystem.getTemplateType().asType())); + } + + @Override + protected void createChildren(TypeSystemData m) { + add(new TypeClassFactory(context), m); + } + + protected static class TypeClassFactory extends ClassElementFactory { + + private static final String LOCAL_VALUE = "value"; + + public TypeClassFactory(ProcessorContext context) { + super(context); + } + + @Override + public CodeTypeElement create(TypeSystemData typeSystem) { + String name = typeName(typeSystem); + CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC), name, typeSystem.getTemplateType().asType(), false); + + clazz.getImplements().add(getContext().getTruffleTypes().getTypeConversion()); + + clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz)); + CodeVariableElement singleton = createSingleton(clazz); + clazz.add(singleton); + + clazz.add(createGetTopType(typeSystem)); + clazz.add(createConvertTo(typeSystem, singleton)); + + for (TypeData type : typeSystem.getTypes()) { + if (!type.isGeneric()) { + CodeExecutableElement isType = createIsTypeMethod(type); + if (isType != null) { + clazz.add(isType); + } + CodeExecutableElement asType = createAsTypeMethod(type); + if (asType != null) { + clazz.add(asType); + } + + for (TypeData sourceType : collectExpectSourceTypes(type)) { + CodeExecutableElement expect = createExpectTypeMethod(type, sourceType); + if (expect != null) { + clazz.add(expect); + } + } + } + } + + clazz.getEnclosedElements().addAll(typeSystem.getExtensionElements()); + + return clazz; + } + + private static List collectExpectSourceTypes(TypeData type) { + Set sourceTypes = new HashSet<>(); + sourceTypes.add(type.getTypeSystem().getGenericTypeData()); + for (TypeCastData cast : type.getTypeCasts()) { + sourceTypes.add(cast.getSourceType()); + } + for (TypeCheckData cast : type.getTypeChecks()) { + sourceTypes.add(cast.getCheckedType()); + } + return new ArrayList<>(sourceTypes); + } + + + private CodeExecutableElement createConvertTo(TypeSystemData typeSystem, CodeVariableElement singleton) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Object.class), "convertTo"); + method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "targetType")); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), "value")); + + CodeTreeBuilder builder = method.createBuilder(); + + boolean first = true; + for (TypeData type : typeSystem.getTypes()) { + if (first) { + builder.startIf(); + first = false; + } else { + builder.startElseIf(); + } + builder.string("targetType").string(" == ").typeLiteral(type.getBoxedType()); + builder.end(); // if + builder.startBlock(); + + builder.startReturn(); + + if (typeEquals(type.getBoxedType(), getContext().getType(Object.class))) { + builder.string("value"); + } else { + builder.string(singleton.getName()).string(".").startCall(asTypeMethodName(type)).string("value").end(); + } + + builder.end(); // return + + builder.end(); // block + } + + builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); + + return method; + } + + private CodeExecutableElement createGetTopType(TypeSystemData typeSystem) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), "getTopType"); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + if (typeSystem.getTypes().length > 0) { + builder.typeLiteral(typeSystem.getTypes()[0].getBoxedType()); + } else { + builder.null_(); + } + builder.end(); // return + + return method; + } + + private static String typeName(TypeSystemData typeSystem) { + String name = getSimpleName(typeSystem.getTemplateType()); + return name + "Gen"; + } + + private static String singletonName(TypeMirror type) { + return createConstantName(getSimpleName(type)); + } + + private CodeVariableElement createSingleton(CodeTypeElement clazz) { + CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel().getTemplateType().asType())); + field.createInitBuilder().startNew(clazz.asType()).end(); + return field; + } + + private CodeExecutableElement createIsTypeMethod(TypeData type) { + if (!type.getTypeChecks().isEmpty()) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), + TypeSystemCodeGenerator.isTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + + CodeTreeBuilder body = method.createBuilder(); + body.startReturn().instanceOf(LOCAL_VALUE, type.getBoxedType()).end(); + + return method; + } + + private CodeExecutableElement createAsTypeMethod(TypeData type) { + if (!type.getTypeCasts().isEmpty()) { + return null; + } + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), + TypeSystemCodeGenerator.asTypeMethodName(type)); + method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); + + CodeTreeBuilder body = method.createBuilder(); + body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); + + return method; + } + + private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); + method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE)); + method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException()); + + CodeTreeBuilder body = method.createBuilder(); + body.startIf().startCall(null, TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock(); + body.startReturn().startCall(null, TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end(); + body.end(); // if-block + body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end(); + + return method; + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemData.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; + +public class TypeSystemData extends Template { + + private final TypeData[] types; + private final TypeMirror[] primitiveTypeMirrors; + private final TypeMirror[] boxedTypeMirrors; + + private final TypeMirror nodeType; + private final TypeMirror genericType; + + private final TypeData voidType; + + private List guards; + + + public TypeSystemData(TypeElement templateType, AnnotationMirror annotation, + TypeData[] types, TypeMirror nodeType, TypeMirror genericType, TypeData voidType) { + super(templateType, annotation); + this.voidType = voidType; + this.types = types; + this.nodeType = nodeType; + this.genericType = genericType; + + this.primitiveTypeMirrors = new TypeMirror[types.length]; + for (int i = 0; i < types.length; i++) { + primitiveTypeMirrors[i] = types[i].getPrimitiveType(); + } + + this.boxedTypeMirrors = new TypeMirror[types.length]; + for (int i = 0; i < types.length; i++) { + boxedTypeMirrors[i] = types[i].getBoxedType(); + } + + for (TypeData type : types) { + type.typeSystem = this; + } + if (voidType != null) { + voidType.typeSystem = this; + } + } + + public TypeData getVoidType() { + return voidType; + } + + void setGuards(List guards) { + this.guards = guards; + } + + public List getGuards() { + return guards; + } + + public TypeData[] getTypes() { + return types; + } + + public TypeMirror[] getPrimitiveTypeMirrors() { + return primitiveTypeMirrors; + } + + public TypeMirror[] getBoxedTypeMirrors() { + return boxedTypeMirrors; + } + + public TypeMirror getNodeType() { + return nodeType; + } + + public TypeMirror getGenericType() { + return genericType; + } + + public TypeData getGenericTypeData() { + TypeData result = types[types.length - 1]; + assert result.getBoxedType() == genericType; + return result; + } + + public TypeData findType(String simpleName) { + for (TypeData type : types) { + if (Utils.getSimpleName(type.getBoxedType()).equals(simpleName)) { + return type; + } + } + return null; + } + + public int findType(TypeMirror type) { + for (int i = 0; i < types.length; i++) { + if (Utils.typeEquals(types[i].getPrimitiveType(), type)) { + return i; + } + } + return -1; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemMethodParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import javax.lang.model.element.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; + + +abstract class TypeSystemMethodParser extends TemplateMethodParser { + + private final TypeSystemData typeSystem; + + public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context); + this.typeSystem = typeSystem; + } + + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + protected TypeData findTypeByMethodName(ExecutableElement method, AnnotationMirror annotationMirror, String prefix) { + String methodName = method.getSimpleName().toString(); + if (!methodName.startsWith(prefix)) { + String annotationName = Utils.getSimpleName(annotationMirror.getAnnotationType()); + getContext().getLog().error(method, "Methods annotated with %s must match the pattern '%s'.", + annotationName, String.format("%s${typeName}", prefix)); + return null; + } + String typeName = methodName.substring(prefix.length(), methodName.length()); + TypeData type = typeSystem.findType(typeName); + if (type == null) { + String annotationName = TypeSystem.class.getSimpleName(); + getContext().getLog().error(method, "Type '%s' is not declared in this @%s.", typeName, annotationName); + return null; + } + + return type; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.codegen.processor.typesystem; + +import static com.oracle.truffle.codegen.processor.Utils.*; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.operation.*; +import com.oracle.truffle.codegen.processor.template.*; + +public class TypeSystemParser extends TemplateParser { + + public TypeSystemParser(ProcessorContext c) { + super(c); + } + + @Override + public Class< ? extends Annotation> getAnnotationType() { + return TypeSystem.class; + } + + @Override + protected TypeSystemData parse(Element element, AnnotationMirror mirror) { + TypeElement templateType = (TypeElement) element; + AnnotationMirror templateTypeAnnotation = mirror; + + if (!verifyTemplateType(templateType, templateTypeAnnotation)) { + return null; + } + + TypeData[] types = parseTypes(templateType, templateTypeAnnotation); + if (types == null) { + return null; + } + + TypeMirror nodeType = Utils.getAnnotationValueType(templateTypeAnnotation, "nodeBaseClass"); + TypeMirror genericType = context.getType(Object.class); + + TypeData voidType = null; + if (Utils.getAnnotationValueBoolean(templateTypeAnnotation, "hasVoid")) { + voidType = new TypeData(templateType, templateTypeAnnotation, context.getType(void.class), context.getType(Void.class)); + } + + TypeSystemData typeSystem = new TypeSystemData(templateType, templateTypeAnnotation, types, nodeType, genericType, voidType); + + if (!verifyNodeBaseType(typeSystem)) { + return null; + } + + if (!verifyExclusiveMethodAnnotation(templateType, TypeCast.class, TypeCheck.class, GuardCheck.class)) { + return null; + } + + typeSystem.setExtensionElements(getExtensionParser().parseAll(templateType)); + + List casts = parseMethods(typeSystem, new TypeCastParser(context, typeSystem)); + List checks = parseMethods(typeSystem, new TypeCheckParser(context, typeSystem)); + List guards = parseMethods(typeSystem, new GuardParser(context, typeSystem, typeSystem)); + + if (casts == null || checks == null || guards == null) { + return null; + } + + for (TypeCheckData check : checks) { + check.getCheckedType().addTypeCheck(check); + } + + for (TypeCastData cast : casts) { + cast.getTargetType().addTypeCast(cast); + } + + typeSystem.setGuards(guards); + + if (!verifyGenericTypeChecksAndCasts(types)) { + return null; + } + + if (!verifyMethodSignatures(element, types)) { + return null; + } + + if (!verifyNamesUnique(templateType, templateTypeAnnotation, types)) { + return null; + } + + return typeSystem; + } + + private boolean verifyGenericTypeChecksAndCasts(TypeData[] types) { + boolean valid = true; + for (TypeData type : types) { + if (!type.getTypeChecks().isEmpty()) { + boolean hasGeneric = false; + for (TypeCheckData typeCheck : type.getTypeChecks()) { + if (typeCheck.isGeneric()) { + hasGeneric = true; + break; + } + } + if (!hasGeneric) { + log.error(type.getTypeSystem().getTemplateType(), + "No generic but specific @%s method %s for type %s specified. " + + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCheck.class.getSimpleName(), TypeSystemCodeGenerator.isTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), + TypeCheck.class.getSimpleName(), Object.class.getSimpleName()); + valid = false; + } + } + if (!type.getTypeCasts().isEmpty()) { + boolean hasGeneric = false; + for (TypeCastData typeCast : type.getTypeCasts()) { + if (typeCast.isGeneric()) { + hasGeneric = true; + break; + } + } + if (!hasGeneric) { + log.error(type.getTypeSystem().getTemplateType(), + "No generic but specific @%s method %s for type %s specified. " + + "Specify a generic @%s method with parameter type %s to resolve this.", + TypeCast.class.getSimpleName(), TypeSystemCodeGenerator.asTypeMethodName(type), Utils.getSimpleName(type.getBoxedType()), + TypeCast.class.getSimpleName(), Object.class.getSimpleName()); + valid = false; + } + } + } + return valid; + } + + private boolean verifyNodeBaseType(TypeSystemData typeSystem) { + List types = new ArrayList<>(Arrays.asList(typeSystem.getTypes())); + if (typeSystem.getVoidType() != null) { + types.add(typeSystem.getVoidType()); + } + + TypeMirror[] args = new TypeMirror[]{context.getTruffleTypes().getFrame()}; + List missingMethods = new ArrayList<>(); + for (TypeData typeData : types) { + String methodName = OperationCodeGenerator.executeMethodName(typeData); + ExecutableElement declared = Utils.getDeclaredMethodRecursive(Utils.fromTypeMirror(typeSystem.getNodeType()), methodName, args); + if (declared == null || declared.getModifiers().contains(Modifier.FINAL)) { + missingMethods.add(String.format("public %s %s(%s)", + Utils.getSimpleName(typeData.getPrimitiveType()), methodName, + Utils.getSimpleName(context.getTruffleTypes().getFrame()))); + } + } + + if (!missingMethods.isEmpty()) { + log.error(typeSystem.getTemplateType(), typeSystem.getTemplateTypeAnnotation(), + Utils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "nodeBaseClass"), + "The class '%s' does not declare the required non final method(s) %s.", + Utils.getQualifiedName(typeSystem.getNodeType()), missingMethods); + return false; + } + + return true; + } + + private TypeData[] parseTypes(TypeElement templateType, AnnotationMirror templateTypeAnnotation) { + List typeMirrors = Utils.getAnnotationValueList(templateTypeAnnotation, "types"); + if (typeMirrors.size() == 0) { + log.error(templateType, templateTypeAnnotation, "At least one type child must be defined."); + return null; + } + + final AnnotationValue annotationValue = Utils.getAnnotationValue(templateTypeAnnotation, "types"); + final TypeMirror objectType = context.getType(Object.class); + + List types = new ArrayList<>(); + for (TypeMirror primitiveType : typeMirrors) { + + if (isPrimitiveWrapper(primitiveType)) { + log.error(templateType, templateTypeAnnotation, annotationValue, + "Types must not contain primitive wrapper types."); + continue; + } + + TypeMirror boxedType = primitiveType; + if (boxedType.getKind().isPrimitive()) { + boxedType = processingEnv.getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); + } + + if (Utils.typeEquals(boxedType, objectType)) { + log.error(templateType, templateTypeAnnotation, annotationValue, + "Types must not contain the generic type java.lang.Object."); + continue; + } + + types.add(new TypeData(templateType, templateTypeAnnotation, primitiveType, boxedType)); + } + + verifyTypeOrder(templateType, templateTypeAnnotation, annotationValue, types); + + types.add(new TypeData(templateType, templateTypeAnnotation, objectType, objectType)); + + return types.toArray(new TypeData[types.size()]); + } + + private void verifyTypeOrder(TypeElement templateType, AnnotationMirror templateTypeAnnotation, AnnotationValue annotationValue, List types) { + Map> invalidTypes = new HashMap<>(); + + for (int i = types.size() - 1; i >= 0; i--) { + TypeData typeData = types.get(i); + TypeMirror type = typeData.getBoxedType(); + if (invalidTypes.containsKey(Utils.getQualifiedName(type))) { + log.error(templateType, templateTypeAnnotation, annotationValue, + "Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", + invalidTypes.get(Utils.getQualifiedName(type)), Utils.getQualifiedName(type)); + } + List nextInvalidTypes = Utils.getQualifiedSuperTypeNames(Utils.fromTypeMirror(type)); + nextInvalidTypes.add(getQualifiedName(type)); + + for (String qualifiedName : nextInvalidTypes) { + List inheritedTypes = invalidTypes.get(qualifiedName); + if (inheritedTypes == null) { + inheritedTypes = new ArrayList<>(); + invalidTypes.put(qualifiedName, inheritedTypes); + } + inheritedTypes.add(Utils.getQualifiedName(typeData.getBoxedType())); + } + } + } + + private boolean isPrimitiveWrapper(TypeMirror type) { + Types types = context.getEnvironment().getTypeUtils(); + for (TypeKind kind : TypeKind.values()) { + if (!kind.isPrimitive()) { + continue; + } + if (Utils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) { + return true; + } + } + return false; + } + + + private boolean verifyMethodSignatures(Element element, TypeData[] types) { + Set generatedIsMethodNames = new HashSet<>(); + Set generatedAsMethodNames = new HashSet<>(); + Set generatedExpectMethodNames = new HashSet<>(); + + for (TypeData typeData : types) { + generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData)); + generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData)); + generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData)); + } + + boolean valid = true; + List methods = ElementFilter.methodsIn(element.getEnclosedElements()); + for (ExecutableElement method : methods) { + if (method.getModifiers().contains(Modifier.PRIVATE)) { + // will not conflict overridden methods + continue; + } else if (method.getParameters().size() != 1) { + continue; + } + String methodName = method.getSimpleName().toString(); + if (generatedIsMethodNames.contains(methodName)) { + valid &= verifyIsMethod(method); + } else if (generatedAsMethodNames.contains(methodName)) { + valid &= verifyAsMethod(method); + } else if (generatedExpectMethodNames.contains(methodName)) { + valid &= verifyExpectMethod(method); + } + } + return valid; + } + + private boolean verifyIsMethod(ExecutableElement method) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCheck.class); + if (mirror == null) { + log.error(method, "Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName()); + return false; + } + return true; + } + + private boolean verifyAsMethod(ExecutableElement method) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, TypeCast.class); + if (mirror == null) { + log.error(method, "Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName()); + return false; + } + return true; + } + + private boolean verifyExpectMethod(ExecutableElement method) { + log.error(method, "Method starting with the pattern expect${typeName} must not be declared manually."); + return false; + } + + private boolean verifyNamesUnique(TypeElement templateType, AnnotationMirror templateTypeAnnotation, TypeData[] types) { + boolean valid = true; + for (int i = 0; i < types.length; i++) { + for (int j = i + 1; j < types.length; j++) { + String name1 = Utils.getSimpleName(types[i].getBoxedType()); + String name2 = Utils.getSimpleName(types[j].getBoxedType()); + if (name1.equalsIgnoreCase(name2)) { + log.error(templateType, templateTypeAnnotation, "Two types result in the same name: %s, %s.", name1, name2); + valid = false; + } + } + } + return valid; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AbstractTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AbstractTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,64 @@ +/* + * 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.sl.test; + +import java.io.*; + +import org.junit.*; + +import com.oracle.truffle.sl.*; + +public class AbstractTest { + public static final int REPEATS = 10; + private static final String NEWLINE = System.getProperty("line.separator"); + + private static String concat(String[] string) { + StringBuilder result = new StringBuilder(); + for (String s : string) { + result.append(s).append(NEWLINE); + } + return result.toString(); + } + + private static String repeat(String s, int count) { + StringBuilder result = new StringBuilder(s.length() * count); + for (int i = 0; i < count; i++) { + result.append(s); + } + return result.toString(); + } + + protected void executeSL(String[] input, String[] expectedOutput, boolean useConsole) { + InputStream in = new ByteArrayInputStream(concat(input).getBytes()); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrintStream printer = new PrintStream(useConsole ? new SplitOutputStream(out, System.err) : out); + PrintStream origErr = System.err; + System.setErr(printer); + + SimpleLanguage.run(in, printer, REPEATS, true); + + System.setErr(origErr); + Assert.assertEquals(repeat(concat(expectedOutput), REPEATS), new String(out.toByteArray())); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AddTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AddTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,55 @@ +/* + * 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.sl.test; + +import org.junit.*; + +public class AddTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { ", +" print 3 + 4; ", +" print 3 + \"4\"; ", +" print \"3\" + 4; ", +" print \"3\" + \"4\"; ", +" print 3 + 4000000000000; ", +" print 3000000000000 + 4; ", +" print 3000000000000 + 4000000000000; ", +"} ", + }; + + private static String[] OUTPUT = new String[] { +"7", +"34", +"34", +"34", +"4000000000003", +"3000000000004", +"7000000000000", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ComparisonTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ComparisonTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,55 @@ +/* + * 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.sl.test; + +import org.junit.*; + +public class ComparisonTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { ", +" print 4 < 20; ", +" print 4 < \"20\"; ", +" print \"4\" < 20; ", +" print \"4\" < \"20\"; ", +" print 4 < 20000000000000; ", +" print 4000000000000 < 20; ", +" print 4000000000000 < 20000000000000; ", +"} ", + }; + + private static String[] OUTPUT = new String[] { +"true", +"false", +"false", +"false", +"true", +"false", +"true", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopPrintTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopPrintTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,47 @@ +/* + * 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.sl.test; + +import org.junit.*; + +public class LoopPrintTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { ", +" i = 0; ", +" while (i < 1000) { ", +" i = i + 1; ", +" } ", +" print i; ", +"} ", + }; + + private static String[] OUTPUT = new String[] { +"1000", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,47 @@ +/* + * 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.sl.test; + +import org.junit.*; + +public class LoopTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { ", +" i = 0; ", +" while (i < 1000) { ", +" i = i + 1; ", +" } ", +" return i; ", +"} ", + }; + + private static String[] OUTPUT = new String[] { +"1000", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/MulTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/MulTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,49 @@ +/* + * 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.sl.test; + +import org.junit.*; + +public class MulTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { ", +" print 3 * 4; ", +" print 3 * 4000000000000; ", +" print 3000000000000 * 4; ", +" print 3000000000000 * 4000000000000; ", +"} ", + }; + + private static String[] OUTPUT = new String[] { +"12", +"12000000000000", +"12000000000000", +"12000000000000000000000000", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SplitOutputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SplitOutputStream.java Mon Jan 07 13:04:04 2013 +0100 @@ -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.sl.test; + +import java.io.*; + +public class SplitOutputStream extends OutputStream { + + private final OutputStream[] outputs; + + public SplitOutputStream(OutputStream... outputs) { + this.outputs = outputs; + } + + @Override + public void write(int b) throws IOException { + for (OutputStream out : outputs) { + out.write(b); + } + } + + @Override + public void write(byte[] b) throws IOException { + for (OutputStream out : outputs) { + out.write(b); + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + for (OutputStream out : outputs) { + out.write(b, off, len); + } + } + + @Override + public void flush() throws IOException { + for (OutputStream out : outputs) { + out.flush(); + } + } + + @Override + public void close() throws IOException { + for (OutputStream out : outputs) { + out.close(); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SumTest.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,49 @@ +/* + * 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.sl.test; + +import org.junit.*; + +public class SumTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { ", +" i = 0; ", +" sum = 0; ", +" while (i < 1000) { ", +" sum = sum + 100000000; ", +" i = i + 1; ", +" } ", +" return sum; ", +"} ", + }; + + private static String[] OUTPUT = new String[] { +"100000000000", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,118 @@ +/* + * 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.sl; + +import java.io.*; +import java.math.*; +import java.util.*; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.ops.*; +import com.oracle.truffle.sl.types.*; + +public class NodeFactory { + + private final HashMap functions; + private final PrintStream printOutput; + + private FrameDescriptor frameDescriptor; + private TypedNode returnValue; + + public NodeFactory(PrintStream printOutput) { + this.functions = new HashMap<>(); + this.printOutput = printOutput; + } + + public FunctionDefinitionNode findFunction(String name) { + return functions.get(name); + } + + public void startFunction() { + frameDescriptor = new FrameDescriptor(TypesGen.TYPES); + } + + public void createFunction(StatementNode body, String name) { + functions.put(name, new FunctionDefinitionNode(body, frameDescriptor, name, returnValue)); + } + + public TypedNode createLocal(String name) { + return ReadLocalOpFactory.create(frameDescriptor.findOrAddFrameSlot(name)); + } + + public TypedNode createStringLiteral(String value) { + return StringLiteralFactory.create(value); + } + + public StatementNode createAssignment(String name, TypedNode right) { + return WriteLocalOpFactory.create(right, frameDescriptor.findOrAddFrameSlot(name)); + } + + public StatementNode createPrint(List expressions) { + return new PrintNode(expressions, printOutput); + } + + public StatementNode createWhile(ConditionNode condition, StatementNode body) { + return new WhileNode(condition, body); + } + + public StatementNode createBlock(List statements) { + return new BlockNode(statements.toArray(new StatementNode[statements.size()])); + } + + public TypedNode createBinary(String operation, TypedNode left, TypedNode right) { + switch (operation) { + case "+": + return AddOpFactory.create(left, right); + case "*": + return MulOpFactory.create(left, right); + case "<": + return LessThanOpFactory.create(left, right); + case "&&": + return LogicalAndOpFactory.create(left, right); + default: + throw new RuntimeException("unexpected operation: " + operation); + } + } + + public TypedNode createNumericLiteral(String value) { + try { + return IntegerLiteralFactory.create(Integer.parseInt(value)); + } catch (NumberFormatException ex) { + return BigIntegerLiteralFactory.create(new BigInteger(value)); + } + } + + public TypedNode createTime() { + return TimeOpFactory.create(); + } + + public StatementNode createReturn(TypedNode value) { + FrameSlot slot = frameDescriptor.findOrAddFrameSlot(""); + if (returnValue == null) { + returnValue = ReadLocalOpFactory.create(slot); + } + StatementNode write = WriteLocalOpFactory.create(value, slot); + return new ReturnNode(write); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLArguments.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLArguments.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,34 @@ +/* + * 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.sl; + +import com.oracle.truffle.api.*; + +public final class SLArguments extends Arguments { + + public final Object[] arguments; + + public SLArguments(Object[] arguments) { + this.arguments = arguments; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,74 @@ +/* + * 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.sl; + +import java.io.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.parser.*; +import com.oracle.truffle.sl.tools.*; + +public class SimpleLanguage { + + public static void main(String[] args) throws IOException { + run(new FileInputStream(args[0]), System.out, 10, true); + } + + public static void run(InputStream input, PrintStream printOutput, int repeats, boolean log) { + System.out.printf("== running on %s\n", Truffle.getRuntime().getName()); + + NodeFactory factory = new NodeFactory(printOutput); + + Parser parser = new Parser(new Scanner(input), factory); + parser.Parse(); + + FunctionDefinitionNode rootNode = factory.findFunction("main"); + if (log) { + GraphPrinter.print(rootNode); + } + + try { + CallTarget function = Truffle.getRuntime().createCallTarget(rootNode, rootNode.getFrameDescriptor()); + for (int i = 0; i < repeats; i++) { + Arguments arguments = new SLArguments(new Object[0]); + + long start = System.nanoTime(); + Object result = function.call(null, arguments); + long end = System.nanoTime(); + + if (result != null) { + printOutput.println(result); + } + if (log) { + System.out.printf("== iteration %d: %.3f ms\n", (i + 1), (end - start) / 1000000.0); + } + } + + } finally { + if (log) { + GraphPrinter.print(rootNode); + } + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BlockNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,42 @@ +/* + * 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.sl.nodes; + +import com.oracle.truffle.api.frame.*; + +public class BlockNode extends StatementNode { + + @Children + private final StatementNode[] statements; + + public BlockNode(StatementNode[] statements) { + this.statements = adoptChildren(statements); + } + + @Override + public void executeVoid(VirtualFrame frame) { + for (StatementNode statement : statements) { + statement.executeVoid(frame); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BreakException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BreakException.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,28 @@ +/* + * 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.sl.nodes; + +public final class BreakException extends ControlFlowException { + + private static final long serialVersionUID = -91013036379258890L; +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BreakNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/BreakNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,39 @@ +/* + * 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.sl.nodes; + +import com.oracle.truffle.api.frame.*; + +public final class BreakNode extends StatementNode { + + private final BreakException target; + + public BreakNode(BreakException target) { + this.target = target; + } + + @Override + public void executeVoid(VirtualFrame frame) { + throw target; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,30 @@ +/* + * 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.sl.nodes; + +import com.oracle.truffle.api.frame.*; + +public abstract class ConditionNode extends StatementNode { + + public abstract boolean executeCondition(VirtualFrame frame); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ContinueException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ContinueException.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,28 @@ +/* + * 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.sl.nodes; + +public final class ContinueException extends ControlFlowException { + + private static final long serialVersionUID = 5329687983726237188L; +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ContinueNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ContinueNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,39 @@ +/* + * 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.sl.nodes; + +import com.oracle.truffle.api.frame.*; + +public final class ContinueNode extends StatementNode { + + private final ContinueException target; + + public ContinueNode(ContinueException target) { + this.target = target; + } + + @Override + public void executeVoid(VirtualFrame frame) { + throw target; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ControlFlowException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ControlFlowException.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,37 @@ +/* + * 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.sl.nodes; + +/** + * Common base class for exceptions that are used to implement control flow. + */ +public abstract class ControlFlowException extends RuntimeException { + + private static final long serialVersionUID = 4924673852577649008L; + + @SuppressWarnings("all") + @Override + public final Throwable fillInStackTrace() { + return null; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionDefinitionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionDefinitionNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,67 @@ +/* + * 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.sl.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.types.*; + +public class FunctionDefinitionNode extends RootNode { + + private final FrameDescriptor frameDescriptor; + private final String name; + @Child + private StatementNode body; + @Child + private TypedNode returnValue; + + public FunctionDefinitionNode(StatementNode body, FrameDescriptor frameDescriptor, String name, TypedNode returnValue) { + this.body = adoptChild(body); + this.frameDescriptor = frameDescriptor; + this.name = name; + this.returnValue = adoptChild(returnValue); + } + + @Override + public Object execute(VirtualFrame frame) { + try { + body.executeVoid(frame); + } catch (ReturnException ex) { + // Nothing to do, we just need to return. + } + if (returnValue != null) { + return returnValue.executeGeneric(frame); + } else { + return null; + } + } + + public FrameDescriptor getFrameDescriptor() { + return frameDescriptor; + } + + @Override + public String toString() { + return "Function " + name + "@" + Integer.toHexString(hashCode()); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.nodes; + +import com.oracle.truffle.api.frame.*; + +public class IfNode extends StatementNode { + + @Child + private ConditionNode condition; + @Child + private StatementNode thenPart; + @Child + private StatementNode elsePart; + + public IfNode(ConditionNode condition, StatementNode thenPart, StatementNode elsePart) { + this.condition = adoptChild(condition); + this.thenPart = adoptChild(thenPart); + this.elsePart = adoptChild(elsePart); + } + + @Override + public void executeVoid(VirtualFrame frame) { + if (condition.executeCondition(frame)) { + thenPart.executeVoid(frame); + } else if (elsePart != null) { + elsePart.executeVoid(frame); + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,52 @@ +/* + * 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.sl.nodes; + +import java.io.*; +import java.util.*; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.types.*; + +public class PrintNode extends StatementNode { + + @Children + private final TypedNode[] expressions; + + private final PrintStream output; + + public PrintNode(List expressions, PrintStream output) { + this.expressions = adoptChildren(expressions.toArray(new TypedNode[expressions.size()])); + this.output = output; + } + + @ExplodeLoop + @Override + public void executeVoid(VirtualFrame frame) { + for (TypedNode expression : expressions) { + output.print(expression.executeGeneric(frame)); + } + output.println(); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReturnException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReturnException.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,28 @@ +/* + * 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.sl.nodes; + +public final class ReturnException extends ControlFlowException { + + private static final long serialVersionUID = 4073191346281369231L; +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReturnNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReturnNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,43 @@ +/* + * 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.sl.nodes; + +import com.oracle.truffle.api.frame.*; + +public class ReturnNode extends StatementNode { + + private static final ReturnException EXCEPTION = new ReturnException(); + + @Child + private StatementNode expr; + + public ReturnNode(StatementNode expr) { + this.expr = adoptChild(expr); + } + + @Override + public void executeVoid(VirtualFrame frame) { + expr.executeVoid(frame); + throw EXCEPTION; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/StatementNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/StatementNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,31 @@ +/* + * 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.sl.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public abstract class StatementNode extends Node { + + public abstract void executeVoid(VirtualFrame frame); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WhileNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WhileNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.nodes; + +import com.oracle.truffle.api.frame.*; + +public class WhileNode extends StatementNode { + + @Child + private ConditionNode condition; + @Child + private StatementNode body; + + private final BreakException breakTarget; + private final ContinueException continueTarget; + + public WhileNode(ConditionNode condition, StatementNode body) { + this.condition = adoptChild(condition); + this.body = adoptChild(body); + + this.breakTarget = new BreakException(); + this.continueTarget = new ContinueException(); + } + + @Override + public void executeVoid(VirtualFrame frame) { + try { + while (condition.executeCondition(frame)) { + try { + body.executeVoid(frame); + } catch (ContinueException ex) { + if (ex != continueTarget) { + throw ex; + } + // Fall through to next loop iteration. + } + } + } catch (BreakException ex) { + if (ex != breakTarget) { + throw ex; + } + // Done executing this loop, exit method to execute statement following the loop. + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/AddOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/AddOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,60 @@ +/* + * 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.sl.ops; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.intrinsics.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class, values = {"left", "right"}) +public class AddOp { + + @Specialization + @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger") + public int doInteger(int left, int right) { + return ExactMath.addExact(left, right); + } + + @Specialization + public BigInteger doBigInteger(BigInteger left, BigInteger right) { + return left.add(right); + } + + @Specialization + public String doStringDirect(String left, String right) { + return left + right; + } + + @Specialization + @SpecializationGuard(methodName = "isString") + public String doString(Object left, Object right) { + return left.toString() + right.toString(); + } + + @Generic + public Object doGeneric(Object left, Object right) { + throw new RuntimeException("addition not defined for types " + left.getClass().getSimpleName() + ", " + right.getClass().getSimpleName()); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/BigIntegerLiteral.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/BigIntegerLiteral.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,43 @@ +/* + * 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.sl.ops; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class) +public class BigIntegerLiteral { + + private final BigInteger value; + + public BigIntegerLiteral(BigInteger value) { + this.value = value; + } + + @Specialization + public BigInteger doBigInteger() { + return value; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/IfOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/IfOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.ops; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.sl.types.*; + +@SuppressWarnings("unused") +@Operation(typeSystem = Types.class, values = {"condition"}, shortCircuitValues = {"ifPart", "elsePart"}) +public class IfOp { + + @ShortCircuit("ifPart") + public boolean needsIfPart(boolean condition) { + return condition; + } + + @ShortCircuit("ifPart") + public boolean needsIfPart(Object condition) { + if (TypesGen.TYPES.isBoolean(condition)) { + return TypesGen.TYPES.asBoolean(condition); + } + throw new RuntimeException("operation not defined for type " + condition.getClass().getSimpleName()); + } + + @ShortCircuit("elsePart") + public boolean needsElsePart(Object condition, boolean hasIfPart, Object ifPart) { + return !hasIfPart; + } + + @ShortCircuit("elsePart") + public boolean needsElsePart(boolean condition, boolean hasIfPart, int ifPart) { + return !hasIfPart; + } + + @ShortCircuit("elsePart") + public boolean needsElsePart(boolean condition, boolean hasIfPart, BigInteger ifPart) { + return !hasIfPart; + } + + @Specialization + public int doInteger(boolean condition, boolean hasIfPart, int ifPart, boolean hasElsePart, int elsePart) { + return hasIfPart ? ifPart : elsePart; + } + + @Specialization + public BigInteger doBigInteger(boolean condition, boolean hasIfPart, BigInteger ifPart, boolean hasElsePart, BigInteger elsePart) { + return hasIfPart ? ifPart : elsePart; + } + + @Generic + public Object doGeneric(Object condition, boolean hasIfPart, Object ifPart, boolean hasElsePart, Object elsePart) { + return hasIfPart ? ifPart : elsePart; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/IntegerLiteral.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/IntegerLiteral.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,41 @@ +/* + * 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.sl.ops; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class) +public class IntegerLiteral { + + private final int value; + + public IntegerLiteral(int value) { + this.value = value; + } + + @Specialization + protected int doInteger() { + return this.value; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/LessThanOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/LessThanOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,53 @@ +/* + * 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.sl.ops; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class, values = {"left", "right"}) +public class LessThanOp { + + @Specialization + public boolean doInteger(int left, int right) { + return left < right; + } + + @Specialization + public boolean doBigInteger(BigInteger left, BigInteger right) { + return left.compareTo(right) < 0; + } + + @Specialization + @SpecializationGuard(methodName = "isString") + public boolean doString(Object left, Object right) { + return left.toString().compareTo(right.toString()) < 0; + } + + @Generic + public boolean doGeneric(Object left, Object right) { + throw new RuntimeException("comparison not defined for types " + left.getClass().getSimpleName() + ", " + right.getClass().getSimpleName()); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/LogicalAndOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/LogicalAndOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,51 @@ +/* + * 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.sl.ops; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.sl.types.*; + +@SuppressWarnings("unused") +@Operation(typeSystem = Types.class, values = {"left"}, shortCircuitValues = {"right"}) +public class LogicalAndOp { + + @ShortCircuit(value = "right") + public boolean needsRight(boolean left) { + return left; + } + + @ShortCircuit(value = "right") + public boolean needsRight(Object left) { + return TypesGen.TYPES.asBoolean(left); + } + + @Specialization + public boolean doBoolean(boolean left, boolean hasRight, boolean right) { + return hasRight && right; + } + + @Generic + public Object doGeneric(Object left, boolean hasRight, Object right) { + throw new RuntimeException("operation not defined for type " + left.getClass().getSimpleName()); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/MulOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/MulOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,49 @@ +/* + * 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.sl.ops; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.intrinsics.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class, values = {"left", "right"}) +public class MulOp { + + @Specialization + @SpecializationThrows(javaClass = ArithmeticException.class, transitionTo = "doBigInteger") + public int doInteger(int left, int right) { + return ExactMath.multiplyExact(left, right); + } + + @Specialization + public BigInteger doBigInteger(BigInteger left, BigInteger right) { + return left.multiply(right); + } + + @Generic + public Object doGeneric(Object left, Object right) { + throw new RuntimeException("multiplication not defined for types " + left.getClass().getSimpleName() + ", " + right.getClass().getSimpleName()); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/ReadLocalOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/ReadLocalOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,58 @@ +/* + * 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.sl.ops; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class, baseClass = FrameSlotNode.class) +public class ReadLocalOp { + + @Specialization(order = 2) + public int doInteger(VirtualFrame frame, FrameSlot slot) { + return frame.getInt(slot); + } + + @Specialization + public BigInteger doBigInteger(VirtualFrame frame, FrameSlot slot) { + return (BigInteger) frame.getObject(slot); + } + + @Specialization + public boolean doBoolean(VirtualFrame frame, FrameSlot slot) { + return frame.getBoolean(slot); + } + + @Specialization + public String doString(VirtualFrame frame, FrameSlot slot) { + return (String) frame.getObject(slot); + } + + @Generic + public Object doGeneric(VirtualFrame frame, FrameSlot slot) { + return frame.getObject(slot); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/StringLiteral.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/StringLiteral.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,41 @@ +/* + * 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.sl.ops; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class) +public class StringLiteral { + + private final String value; + + public StringLiteral(String value) { + this.value = value; + } + + @Specialization + protected String doString() { + return value; + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/TimeOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/TimeOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,37 @@ +/* + * 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.sl.ops; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class, baseClass = TypedNode.class) +public class TimeOp { + + public static final long START_TIME = System.currentTimeMillis(); + + @Specialization + public int doInt() { + return (int) (System.currentTimeMillis() - START_TIME); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/WriteLocalOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/ops/WriteLocalOp.java Mon Jan 07 13:04:04 2013 +0100 @@ -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.sl.ops; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.sl.types.*; + +@Operation(typeSystem = Types.class, baseClass = FrameSlotNode.class, values = "right") +public class WriteLocalOp { + + @Specialization + public int doInteger(VirtualFrame frame, int right, FrameSlot slot) { + frame.setInt(slot, right); + return right; + } + + @Specialization + public BigInteger doBigInteger(VirtualFrame frame, BigInteger right, FrameSlot slot) { + frame.setObject(slot, right); + return right; + } + + @Specialization + public boolean doBoolean(VirtualFrame frame, boolean right, FrameSlot slot) { + frame.setBoolean(slot, right); + return right; + } + + @Specialization + public String doString(VirtualFrame frame, String right, FrameSlot slot) { + frame.setObject(slot, right); + return right; + } + + @Generic + public Object doGeneric(VirtualFrame frame, Object right, FrameSlot slot) { + frame.setObject(slot, right); + return right; + } + + @SpecializationListener + protected void onSpecialize(VirtualFrame frame, Object value, FrameSlot slot) { + slot.setType(value.getClass()); + frame.updateToLatestVersion(); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Copyright.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Copyright.frame Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,25 @@ +/* + * 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. + */ + + // The content of this file is automatically generated. DO NOT EDIT. + diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,212 @@ +/*------------------------------------------------------------------------- +Compiler Generator Coco/R, +Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +extended by M. Loeberbauer & A. Woess, Univ. of Linz +ported from C# to Java by Wolfgang Ahorner +with improvements by Pat Terry, Rhodes University + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As an exception, it is allowed to write an extension of Coco/R that is +used as a plugin in non-free software. + +If not otherwise stated, any source code generated by Coco/R (other than +Coco/R itself) does not fall under the GNU General Public License. +------------------------------------------------------------------------*/ +-->begin +import java.util.*; + +import com.oracle.truffle.sl.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.types.*; + +// Checkstyle: stop +public class Parser { +-->constants + static final boolean T = true; + static final boolean x = false; + static final int minErrDist = 2; + + public Token t; // last recognized token + public Token la; // lookahead token + int errDist = minErrDist; + + public final Scanner scanner; + public final Errors errors; + private final NodeFactory factory; + -->declarations + public Parser(Scanner scanner, NodeFactory factory) { + this.scanner = scanner; + this.factory = factory; + errors = new Errors(); + } + + void SynErr(int n) { + if (errDist >= minErrDist) + errors.SynErr(la.line, la.col, n); + errDist = 0; + } + + public void SemErr(String msg) { + if (errDist >= minErrDist) + errors.SemErr(t.line, t.col, msg); + errDist = 0; + } + + void Get() { + for (;;) { + t = la; + la = scanner.Scan(); + if (la.kind <= maxT) { + ++errDist; + break; + } +-->pragmas + la = t; + } + } + + void Expect(int n) { + if (la.kind == n) + Get(); + else { + SynErr(n); + } + } + + boolean StartOf(int s) { + return set[s][la.kind]; + } + + void ExpectWeak(int n, int follow) { + if (la.kind == n) + Get(); + else { + SynErr(n); + while (!StartOf(follow)) + Get(); + } + } + + boolean WeakSeparator(int n, int syFol, int repFol) { + int kind = la.kind; + if (kind == n) { + Get(); + return true; + } else if (StartOf(repFol)) + return false; + else { + SynErr(n); + while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) { + Get(); + kind = la.kind; + } + return StartOf(syFol); + } + } + +-->productions + + public void Parse() { + la = new Token(); + la.val = ""; + Get(); +-->parseRoot + } + + private static final boolean[][] set = { +-->initialization + }; + + public String ParseErrors() { + java.io.PrintStream oldStream = System.out; + + java.io.OutputStream out = new java.io.ByteArrayOutputStream(); + java.io.PrintStream newStream = new java.io.PrintStream(out); + + errors.errorStream = newStream; + + Parse(); + + String errorStream = out.toString(); + errors.errorStream = oldStream; + + return errorStream; + + } +} // end Parser + +class Errors { + + public int count = 0; // number of errors detected + public java.io.PrintStream errorStream = System.out; // error messages go to this stream + public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text + + protected void printMsg(int line, int column, String msg) { + StringBuffer b = new StringBuffer(errMsgFormat); + int pos = b.indexOf("{0}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, line); + } + pos = b.indexOf("{1}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, column); + } + pos = b.indexOf("{2}"); + if (pos >= 0) + b.replace(pos, pos + 3, msg); + errorStream.println(b.toString()); + } + + public void SynErr(int line, int col, int n) { + String s; + switch (n) {-->errors + default: + s = "error " + n; + break; + } + printMsg(line, col, s); + count++; + } + + public void SemErr(int line, int col, String s) { + printMsg(line, col, s); + count++; + } + + public void SemErr(String s) { + errorStream.println(s); + count++; + } + + public void Warning(int line, int col, String s) { + printMsg(line, col, s); + } + + public void Warning(String s) { + errorStream.println(s); + } +} // Errors + +class FatalError extends RuntimeException { + + public static final long serialVersionUID = 1L; + + public FatalError(String s) { + super(s); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,453 @@ +/* + * 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. + */ + + // The content of this file is automatically generated. DO NOT EDIT. + +package com.oracle.truffle.sl.parser; +import java.util.*; + +import com.oracle.truffle.sl.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.types.*; + +// Checkstyle: stop +public class Parser { + public static final int _EOF = 0; + public static final int _identifier = 1; + public static final int _stringLiteral = 2; + public static final int _numericLiteral = 3; + public static final int maxT = 25; + + static final boolean T = true; + static final boolean x = false; + static final int minErrDist = 2; + + public Token t; // last recognized token + public Token la; // lookahead token + int errDist = minErrDist; + + public final Scanner scanner; + public final Errors errors; + private final NodeFactory factory; + + public Parser(Scanner scanner, NodeFactory factory) { + this.scanner = scanner; + this.factory = factory; + errors = new Errors(); + } + + void SynErr(int n) { + if (errDist >= minErrDist) + errors.SynErr(la.line, la.col, n); + errDist = 0; + } + + public void SemErr(String msg) { + if (errDist >= minErrDist) + errors.SemErr(t.line, t.col, msg); + errDist = 0; + } + + void Get() { + for (;;) { + t = la; + la = scanner.Scan(); + if (la.kind <= maxT) { + ++errDist; + break; + } + + la = t; + } + } + + void Expect(int n) { + if (la.kind == n) + Get(); + else { + SynErr(n); + } + } + + boolean StartOf(int s) { + return set[s][la.kind]; + } + + void ExpectWeak(int n, int follow) { + if (la.kind == n) + Get(); + else { + SynErr(n); + while (!StartOf(follow)) + Get(); + } + } + + boolean WeakSeparator(int n, int syFol, int repFol) { + int kind = la.kind; + if (kind == n) { + Get(); + return true; + } else if (StartOf(repFol)) + return false; + else { + SynErr(n); + while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) { + Get(); + kind = la.kind; + } + return StartOf(syFol); + } + } + + void SimpleLanguage() { + Function(); + while (la.kind == 4) { + Function(); + } + } + + void Function() { + Expect(4); + factory.startFunction(); + Expect(1); + String name = t.val; + StatementNode body = Block(); + factory.createFunction(body, name); + } + + StatementNode Block() { + StatementNode result; + List statements = new ArrayList<>(); + Expect(5); + while (StartOf(1)) { + StatementNode statement = Statement(); + statements.add(statement); + } + Expect(6); + result = factory.createBlock(statements); + return result; + } + + StatementNode Statement() { + StatementNode result; + result = null; + if (la.kind == 7) { + result = WhileStatement(); + } else if (la.kind == 1) { + result = AssignmentStatement(); + } else if (la.kind == 12) { + result = OutputStatement(); + } else if (la.kind == 13) { + result = ReturnStatement(); + } else SynErr(26); + return result; + } + + StatementNode WhileStatement() { + StatementNode result; + Expect(7); + Expect(8); + ConditionNode condition = Expression(); + Expect(9); + StatementNode body = Block(); + result = factory.createWhile(condition, body); + return result; + } + + StatementNode AssignmentStatement() { + StatementNode result; + Expect(1); + String name = t.val; + Expect(10); + TypedNode rvalue = Expression(); + Expect(11); + result = factory.createAssignment(name, rvalue); + return result; + } + + StatementNode OutputStatement() { + StatementNode result; + List expressions = new ArrayList<>(); + Expect(12); + while (StartOf(2)) { + TypedNode value = Expression(); + expressions.add(value); + } + Expect(11); + result = factory.createPrint(expressions); + return result; + } + + StatementNode ReturnStatement() { + StatementNode result; + Expect(13); + TypedNode value = Expression(); + Expect(11); + result = factory.createReturn(value); + return result; + } + + TypedNode Expression() { + TypedNode result; + result = ValueExpression(); + if (StartOf(3)) { + switch (la.kind) { + case 14: { + Get(); + break; + } + case 15: { + Get(); + break; + } + case 16: { + Get(); + break; + } + case 17: { + Get(); + break; + } + case 18: { + Get(); + break; + } + case 19: { + Get(); + break; + } + } + String op = t.val; + TypedNode right = ValueExpression(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode ValueExpression() { + TypedNode result; + result = Term(); + while (la.kind == 20 || la.kind == 21) { + if (la.kind == 20) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Term(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Term() { + TypedNode result; + result = Factor(); + while (la.kind == 22 || la.kind == 23) { + if (la.kind == 22) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Factor(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Factor() { + TypedNode result; + result = null; + if (la.kind == 24) { + result = TimeRef(); + } else if (la.kind == 1) { + result = VariableRef(); + } else if (la.kind == 2) { + result = StringLiteral(); + } else if (la.kind == 3) { + result = NumericLiteral(); + } else if (la.kind == 8) { + Get(); + result = Expression(); + Expect(9); + } else SynErr(27); + return result; + } + + TypedNode TimeRef() { + TypedNode result; + Expect(24); + result = factory.createTime(); + return result; + } + + TypedNode VariableRef() { + TypedNode result; + Expect(1); + result = factory.createLocal(t.val); + return result; + } + + TypedNode StringLiteral() { + TypedNode result; + Expect(2); + result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); + return result; + } + + TypedNode NumericLiteral() { + TypedNode result; + Expect(3); + result = factory.createNumericLiteral(t.val); + return result; + } + + + + public void Parse() { + la = new Token(); + la.val = ""; + Get(); + SimpleLanguage(); + Expect(0); + + } + + private static final boolean[][] set = { + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x} + + }; + + public String ParseErrors() { + java.io.PrintStream oldStream = System.out; + + java.io.OutputStream out = new java.io.ByteArrayOutputStream(); + java.io.PrintStream newStream = new java.io.PrintStream(out); + + errors.errorStream = newStream; + + Parse(); + + String errorStream = out.toString(); + errors.errorStream = oldStream; + + return errorStream; + + } +} // end Parser + +class Errors { + + public int count = 0; // number of errors detected + public java.io.PrintStream errorStream = System.out; // error messages go to this stream + public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text + + protected void printMsg(int line, int column, String msg) { + StringBuffer b = new StringBuffer(errMsgFormat); + int pos = b.indexOf("{0}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, line); + } + pos = b.indexOf("{1}"); + if (pos >= 0) { + b.delete(pos, pos + 3); + b.insert(pos, column); + } + pos = b.indexOf("{2}"); + if (pos >= 0) + b.replace(pos, pos + 3, msg); + errorStream.println(b.toString()); + } + + public void SynErr(int line, int col, int n) { + String s; + switch (n) { + case 0: s = "EOF expected"; break; + case 1: s = "identifier expected"; break; + case 2: s = "stringLiteral expected"; break; + case 3: s = "numericLiteral expected"; break; + case 4: s = "\"function\" expected"; break; + case 5: s = "\"{\" expected"; break; + case 6: s = "\"}\" expected"; break; + case 7: s = "\"while\" expected"; break; + case 8: s = "\"(\" expected"; break; + case 9: s = "\")\" expected"; break; + case 10: s = "\"=\" expected"; break; + case 11: s = "\";\" expected"; break; + case 12: s = "\"print\" expected"; break; + case 13: s = "\"return\" expected"; break; + case 14: s = "\"<\" expected"; break; + case 15: s = "\">\" expected"; break; + case 16: s = "\"<=\" expected"; break; + case 17: s = "\">=\" expected"; break; + case 18: s = "\"==\" expected"; break; + case 19: s = "\"!=\" expected"; break; + case 20: s = "\"+\" expected"; break; + case 21: s = "\"-\" expected"; break; + case 22: s = "\"*\" expected"; break; + case 23: s = "\"/\" expected"; break; + case 24: s = "\"time\" expected"; break; + case 25: s = "??? expected"; break; + case 26: s = "invalid Statement"; break; + case 27: s = "invalid Factor"; break; + default: + s = "error " + n; + break; + } + printMsg(line, col, s); + count++; + } + + public void SemErr(int line, int col, String s) { + printMsg(line, col, s); + count++; + } + + public void SemErr(String s) { + errorStream.println(s); + count++; + } + + public void Warning(int line, int col, String s) { + printMsg(line, col, s); + } + + public void Warning(String s) { + errorStream.println(s); + } +} // Errors + +class FatalError extends RuntimeException { + + public static final long serialVersionUID = 1L; + + public FatalError(String s) { + super(s); + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,512 @@ +/*------------------------------------------------------------------------- +Compiler Generator Coco/R, +Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +extended by M. Loeberbauer & A. Woess, Univ. of Linz +ported from C# to Java by Wolfgang Ahorner +with improvements by Pat Terry, Rhodes University + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As an exception, it is allowed to write an extension of Coco/R that is +used as a plugin in non-free software. + +If not otherwise stated, any source code generated by Coco/R (other than +Coco/R itself) does not fall under the GNU General Public License. +------------------------------------------------------------------------*/ +-->begin +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.HashMap; + +// Checkstyle: stop +class Token { + + public int kind; // token kind + public int pos; // token position in bytes in the source text (starting at 0) + public int charPos; // token position in characters in the source text (starting at 0) + public int col; // token column (starting at 1) + public int line; // token line (starting at 1) + public String val; // token value + public Token next; // ML 2005-03-11 Peek tokens are kept in linked list +} + +// ----------------------------------------------------------------------------------- +// Buffer +// ----------------------------------------------------------------------------------- +class Buffer { + + // This Buffer supports the following cases: + // 1) seekable stream (file) + // a) whole stream in buffer + // b) part of stream in buffer + // 2) non seekable stream (network, console) + + public static final int EOF = Character.MAX_VALUE + 1; + private static final int MIN_BUFFER_LENGTH = 1024; // 1KB + private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB + private byte[] buf; // input buffer + private int bufStart; // position of first byte in buffer relative to input stream + private int bufLen; // length of buffer + private int fileLen; // length of input stream (may change if stream is no file) + private int bufPos; // current position in buffer + private RandomAccessFile file; // input stream (seekable) + private InputStream stream; // growing input stream (e.g.: console, network) + + public Buffer(InputStream s) { + stream = s; + fileLen = bufLen = bufStart = bufPos = 0; + buf = new byte[MIN_BUFFER_LENGTH]; + } + + public Buffer(String fileName) { + try { + file = new RandomAccessFile(fileName, "r"); + fileLen = (int) file.length(); + bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH); + buf = new byte[bufLen]; + bufStart = Integer.MAX_VALUE; // nothing in buffer so far + if (fileLen > 0) + setPos(0); // setup buffer to position 0 (start) + else + bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid + if (bufLen == fileLen) + Close(); + } catch (IOException e) { + throw new FatalError("Could not open file " + fileName); + } + } + + // don't use b after this call anymore + // called in UTF8Buffer constructor + protected Buffer(Buffer b) { + buf = b.buf; + bufStart = b.bufStart; + bufLen = b.bufLen; + fileLen = b.fileLen; + bufPos = b.bufPos; + file = b.file; + stream = b.stream; + // keep finalize from closing the file + b.file = null; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + Close(); + } + + protected void Close() { + if (file != null) { + try { + file.close(); + file = null; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } + } + + public int Read() { + if (bufPos < bufLen) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (getPos() < fileLen) { + setPos(getPos()); // shift buffer start to pos + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (stream != null && ReadNextStreamChunk() > 0) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else { + return EOF; + } + } + + public int Peek() { + int curPos = getPos(); + int ch = Read(); + setPos(curPos); + return ch; + } + + // beg .. begin, zero-based, inclusive, in byte + // end .. end, zero-based, exclusive, in byte + public String GetString(int beg, int end) { + int len = 0; + char[] buffer = new char[end - beg]; + int oldPos = getPos(); + setPos(beg); + while (getPos() < end) + buffer[len++] = (char) Read(); + setPos(oldPos); + return new String(buffer, 0, len); + } + + public int getPos() { + return bufPos + bufStart; + } + + public void setPos(int value) { + if (value >= fileLen && stream != null) { + // Wanted position is after buffer and the stream + // is not seek-able e.g. network or console, + // thus we have to read the stream manually till + // the wanted position is in sight. + while (value >= fileLen && ReadNextStreamChunk() > 0) { + // nothing to do... + } + } + + if (value < 0 || value > fileLen) { + throw new FatalError("buffer out of bounds access, position: " + value); + } + + if (value >= bufStart && value < bufStart + bufLen) { // already in buffer + bufPos = value - bufStart; + } else if (file != null) { // must be swapped in + try { + file.seek(value); + bufLen = file.read(buf); + bufStart = value; + bufPos = 0; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } else { + // set the position to the end of the file, Pos will return fileLen. + bufPos = fileLen - bufStart; + } + } + + // Read the next chunk of bytes from the stream, increases the buffer + // if needed and updates the fields fileLen and bufLen. + // Returns the number of bytes read. + private int ReadNextStreamChunk() { + int free = buf.length - bufLen; + if (free == 0) { + // in the case of a growing input stream + // we can neither seek in the stream, nor can we + // foresee the maximum length, thus we must adapt + // the buffer size on demand. + byte[] newBuf = new byte[bufLen * 2]; + System.arraycopy(buf, 0, newBuf, 0, bufLen); + buf = newBuf; + free = bufLen; + } + + int read; + try { + read = stream.read(buf, bufLen, free); + } catch (IOException ioex) { + throw new FatalError(ioex.getMessage()); + } + + if (read > 0) { + fileLen = bufLen = (bufLen + read); + return read; + } + // end of stream reached + return 0; + } +} + +// ----------------------------------------------------------------------------------- +// UTF8Buffer +// ----------------------------------------------------------------------------------- +class UTF8Buffer extends Buffer { + + UTF8Buffer(Buffer b) { + super(b); + } + + @Override + public int Read() { + int ch; + do { + ch = super.Read(); + // until we find a utf8 start (0xxxxxxx or 11xxxxxx) + } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF)); + if (ch < 128 || ch == EOF) { + // nothing to do, first 127 chars are the same in ascii and utf8 + // 0xxxxxxx or end of file character + } else if ((ch & 0xF0) == 0xF0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x07; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = super.Read(); + int c4 = ch & 0x3F; + ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; + } else if ((ch & 0xE0) == 0xE0) { + // 1110xxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x0F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = (((c1 << 6) | c2) << 6) | c3; + } else if ((ch & 0xC0) == 0xC0) { + // 110xxxxx 10xxxxxx + int c1 = ch & 0x1F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = (c1 << 6) | c2; + } + return ch; + } +} + +// ----------------------------------------------------------------------------------- +// StartStates -- maps characters to start states of tokens +// ----------------------------------------------------------------------------------- +class StartStates { + + private static class Elem { + + public int key, val; + public Elem next; + + public Elem(int key, int val) { + this.key = key; + this.val = val; + } + } + + private Elem[] tab = new Elem[128]; + + public void set(int key, int val) { + Elem e = new Elem(key, val); + int k = key % 128; + e.next = tab[k]; + tab[k] = e; + } + + public int state(int key) { + Elem e = tab[key % 128]; + while (e != null && e.key != key) + e = e.next; + return e == null ? 0 : e.val; + } +} + +// ----------------------------------------------------------------------------------- +// Scanner +// ----------------------------------------------------------------------------------- +@SuppressWarnings({"rawtypes", "unchecked"}) +public class Scanner { + + static final char EOL = '\n'; + static final int eofSym = 0; +-->declarations + + public Buffer buffer; // scanner buffer + + Token t; // current token + int ch; // current input character + int pos; // byte position of current character + int charPos; // position by unicode characters starting with 0 + int col; // column number of current character + int line; // line number of current character + int oldEols; // EOLs that appeared in a comment; + static final StartStates start; // maps initial token character to start state + static final Map literals; // maps literal strings to literal kinds + + Token tokens; // list of tokens already peeked (first token is a dummy) + Token pt; // current peek token + + char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged + int tlen; // length of current token + + static { + start = new StartStates(); + literals = new HashMap(); +-->initialization + } + + public Scanner(String fileName) { + buffer = new Buffer(fileName); + Init(); + } + + public Scanner(InputStream s) { + buffer = new Buffer(s); + Init(); + } + + void Init() { + pos = -1; + line = 1; + col = 0; + charPos = -1; + oldEols = 0; + NextCh(); + if (ch == 0xEF) { // check optional byte order mark for UTF-8 + NextCh(); + int ch1 = ch; + NextCh(); + int ch2 = ch; + if (ch1 != 0xBB || ch2 != 0xBF) { + throw new FatalError("Illegal byte order mark at start of file"); + } + buffer = new UTF8Buffer(buffer); + col = 0; + charPos = -1; + NextCh(); + } + pt = tokens = new Token(); // first token is a dummy + } + + void NextCh() { + if (oldEols > 0) { + ch = EOL; + oldEols--; + } else { + pos = buffer.getPos(); + // buffer reads unicode chars, if UTF8 has been detected + ch = buffer.Read(); + col++; + charPos++; + // replace isolated '\r' by '\n' in order to make + // eol handling uniform across Windows, Unix and Mac + if (ch == '\r' && buffer.Peek() != '\n') + ch = EOL; + if (ch == EOL) { + line++; + col = 0; + } + } +-->casing + } + + void AddCh() { + if (tlen >= tval.length) { + char[] newBuf = new char[2 * tval.length]; + System.arraycopy(tval, 0, newBuf, 0, tval.length); + tval = newBuf; + } + if (ch != Buffer.EOF) { +-->casing2 + NextCh(); + } + } + +-->comments + + void CheckLiteral() { + String val = t.val; +-->casing3 + Object kind = literals.get(val); + if (kind != null) { + t.kind = ((Integer) kind).intValue(); + } + } + + Token NextToken() { + while (ch == ' ' || +-->scan1 + ) NextCh(); +-->scan2 + int recKind = noSym; + int recEnd = pos; + t = new Token(); + t.pos = pos; + t.col = col; + t.line = line; + t.charPos = charPos; + int state = start.state(ch); + tlen = 0; + AddCh(); + + loop: for (;;) { + switch (state) { + case -1: { + t.kind = eofSym; + break loop; + } // NextCh already done + case 0: { + if (recKind != noSym) { + tlen = recEnd - t.pos; + SetScannerBehindT(); + } + t.kind = recKind; + break loop; + } // NextCh already done +-->scan3 + } + } + t.val = new String(tval, 0, tlen); + return t; + } + + private void SetScannerBehindT() { + buffer.setPos(t.pos); + NextCh(); + line = t.line; + col = t.col; + charPos = t.charPos; + for (int i = 0; i < tlen; i++) + NextCh(); + } + + // get the next token (possibly a token already seen during peeking) + public Token Scan() { + if (tokens.next == null) { + return NextToken(); + } else { + pt = tokens = tokens.next; + return tokens; + } + } + + // get the next token, ignore pragmas + public Token Peek() { + do { + if (pt.next == null) { + pt.next = NextToken(); + } + pt = pt.next; + } while (pt.kind > maxT); // skip pragmas + + return pt; + } + + // make sure that peeking starts at current scan position + public void ResetPeek() { + pt = tokens; + } + + // The following methods are used for the CLNG Editor and will be called with java.Reflection. + // If the editor won't be used these 3 functions are obsolete, + // otherwise changes within the signature of the methods will result in Syntax Highlighting not working properly +// anymore. + + // get the offset of the next Token + public int getPeekTokenOffset() { + return pt.pos; + } + + // get the String value of the Token + public String getPeekTokenVal() { + return pt.val; + } + + // get the Kind value of the Token + public int getPeekTokenKind() { + return pt.kind; + } + +} // end Scanner diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,636 @@ +/* + * 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. + */ + + // The content of this file is automatically generated. DO NOT EDIT. + +package com.oracle.truffle.sl.parser; + +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.HashMap; + +// Checkstyle: stop +class Token { + + public int kind; // token kind + public int pos; // token position in bytes in the source text (starting at 0) + public int charPos; // token position in characters in the source text (starting at 0) + public int col; // token column (starting at 1) + public int line; // token line (starting at 1) + public String val; // token value + public Token next; // ML 2005-03-11 Peek tokens are kept in linked list +} + +// ----------------------------------------------------------------------------------- +// Buffer +// ----------------------------------------------------------------------------------- +class Buffer { + + // This Buffer supports the following cases: + // 1) seekable stream (file) + // a) whole stream in buffer + // b) part of stream in buffer + // 2) non seekable stream (network, console) + + public static final int EOF = Character.MAX_VALUE + 1; + private static final int MIN_BUFFER_LENGTH = 1024; // 1KB + private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB + private byte[] buf; // input buffer + private int bufStart; // position of first byte in buffer relative to input stream + private int bufLen; // length of buffer + private int fileLen; // length of input stream (may change if stream is no file) + private int bufPos; // current position in buffer + private RandomAccessFile file; // input stream (seekable) + private InputStream stream; // growing input stream (e.g.: console, network) + + public Buffer(InputStream s) { + stream = s; + fileLen = bufLen = bufStart = bufPos = 0; + buf = new byte[MIN_BUFFER_LENGTH]; + } + + public Buffer(String fileName) { + try { + file = new RandomAccessFile(fileName, "r"); + fileLen = (int) file.length(); + bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH); + buf = new byte[bufLen]; + bufStart = Integer.MAX_VALUE; // nothing in buffer so far + if (fileLen > 0) + setPos(0); // setup buffer to position 0 (start) + else + bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid + if (bufLen == fileLen) + Close(); + } catch (IOException e) { + throw new FatalError("Could not open file " + fileName); + } + } + + // don't use b after this call anymore + // called in UTF8Buffer constructor + protected Buffer(Buffer b) { + buf = b.buf; + bufStart = b.bufStart; + bufLen = b.bufLen; + fileLen = b.fileLen; + bufPos = b.bufPos; + file = b.file; + stream = b.stream; + // keep finalize from closing the file + b.file = null; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + Close(); + } + + protected void Close() { + if (file != null) { + try { + file.close(); + file = null; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } + } + + public int Read() { + if (bufPos < bufLen) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (getPos() < fileLen) { + setPos(getPos()); // shift buffer start to pos + return buf[bufPos++] & 0xff; // mask out sign bits + } else if (stream != null && ReadNextStreamChunk() > 0) { + return buf[bufPos++] & 0xff; // mask out sign bits + } else { + return EOF; + } + } + + public int Peek() { + int curPos = getPos(); + int ch = Read(); + setPos(curPos); + return ch; + } + + // beg .. begin, zero-based, inclusive, in byte + // end .. end, zero-based, exclusive, in byte + public String GetString(int beg, int end) { + int len = 0; + char[] buffer = new char[end - beg]; + int oldPos = getPos(); + setPos(beg); + while (getPos() < end) + buffer[len++] = (char) Read(); + setPos(oldPos); + return new String(buffer, 0, len); + } + + public int getPos() { + return bufPos + bufStart; + } + + public void setPos(int value) { + if (value >= fileLen && stream != null) { + // Wanted position is after buffer and the stream + // is not seek-able e.g. network or console, + // thus we have to read the stream manually till + // the wanted position is in sight. + while (value >= fileLen && ReadNextStreamChunk() > 0) { + // nothing to do... + } + } + + if (value < 0 || value > fileLen) { + throw new FatalError("buffer out of bounds access, position: " + value); + } + + if (value >= bufStart && value < bufStart + bufLen) { // already in buffer + bufPos = value - bufStart; + } else if (file != null) { // must be swapped in + try { + file.seek(value); + bufLen = file.read(buf); + bufStart = value; + bufPos = 0; + } catch (IOException e) { + throw new FatalError(e.getMessage()); + } + } else { + // set the position to the end of the file, Pos will return fileLen. + bufPos = fileLen - bufStart; + } + } + + // Read the next chunk of bytes from the stream, increases the buffer + // if needed and updates the fields fileLen and bufLen. + // Returns the number of bytes read. + private int ReadNextStreamChunk() { + int free = buf.length - bufLen; + if (free == 0) { + // in the case of a growing input stream + // we can neither seek in the stream, nor can we + // foresee the maximum length, thus we must adapt + // the buffer size on demand. + byte[] newBuf = new byte[bufLen * 2]; + System.arraycopy(buf, 0, newBuf, 0, bufLen); + buf = newBuf; + free = bufLen; + } + + int read; + try { + read = stream.read(buf, bufLen, free); + } catch (IOException ioex) { + throw new FatalError(ioex.getMessage()); + } + + if (read > 0) { + fileLen = bufLen = (bufLen + read); + return read; + } + // end of stream reached + return 0; + } +} + +// ----------------------------------------------------------------------------------- +// UTF8Buffer +// ----------------------------------------------------------------------------------- +class UTF8Buffer extends Buffer { + + UTF8Buffer(Buffer b) { + super(b); + } + + @Override + public int Read() { + int ch; + do { + ch = super.Read(); + // until we find a utf8 start (0xxxxxxx or 11xxxxxx) + } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF)); + if (ch < 128 || ch == EOF) { + // nothing to do, first 127 chars are the same in ascii and utf8 + // 0xxxxxxx or end of file character + } else if ((ch & 0xF0) == 0xF0) { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x07; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = super.Read(); + int c4 = ch & 0x3F; + ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; + } else if ((ch & 0xE0) == 0xE0) { + // 1110xxxx 10xxxxxx 10xxxxxx + int c1 = ch & 0x0F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = super.Read(); + int c3 = ch & 0x3F; + ch = (((c1 << 6) | c2) << 6) | c3; + } else if ((ch & 0xC0) == 0xC0) { + // 110xxxxx 10xxxxxx + int c1 = ch & 0x1F; + ch = super.Read(); + int c2 = ch & 0x3F; + ch = (c1 << 6) | c2; + } + return ch; + } +} + +// ----------------------------------------------------------------------------------- +// StartStates -- maps characters to start states of tokens +// ----------------------------------------------------------------------------------- +class StartStates { + + private static class Elem { + + public int key, val; + public Elem next; + + public Elem(int key, int val) { + this.key = key; + this.val = val; + } + } + + private Elem[] tab = new Elem[128]; + + public void set(int key, int val) { + Elem e = new Elem(key, val); + int k = key % 128; + e.next = tab[k]; + tab[k] = e; + } + + public int state(int key) { + Elem e = tab[key % 128]; + while (e != null && e.key != key) + e = e.next; + return e == null ? 0 : e.val; + } +} + +// ----------------------------------------------------------------------------------- +// Scanner +// ----------------------------------------------------------------------------------- +@SuppressWarnings({"rawtypes", "unchecked"}) +public class Scanner { + + static final char EOL = '\n'; + static final int eofSym = 0; + static final int maxT = 25; + static final int noSym = 25; + + + public Buffer buffer; // scanner buffer + + Token t; // current token + int ch; // current input character + int pos; // byte position of current character + int charPos; // position by unicode characters starting with 0 + int col; // column number of current character + int line; // line number of current character + int oldEols; // EOLs that appeared in a comment; + static final StartStates start; // maps initial token character to start state + static final Map literals; // maps literal strings to literal kinds + + Token tokens; // list of tokens already peeked (first token is a dummy) + Token pt; // current peek token + + char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged + int tlen; // length of current token + + static { + start = new StartStates(); + literals = new HashMap(); + for (int i = 65; i <= 90; ++i) start.set(i, 1); + for (int i = 97; i <= 122; ++i) start.set(i, 1); + for (int i = 49; i <= 57; ++i) start.set(i, 4); + start.set(34, 2); + start.set(48, 5); + start.set(123, 6); + start.set(125, 7); + start.set(40, 8); + start.set(41, 9); + start.set(61, 20); + start.set(59, 10); + start.set(60, 21); + start.set(62, 22); + start.set(33, 14); + start.set(43, 16); + start.set(45, 17); + start.set(42, 18); + start.set(47, 19); + start.set(Buffer.EOF, -1); + literals.put("function", new Integer(4)); + literals.put("while", new Integer(7)); + literals.put("print", new Integer(12)); + literals.put("return", new Integer(13)); + literals.put("time", new Integer(24)); + + } + + public Scanner(String fileName) { + buffer = new Buffer(fileName); + Init(); + } + + public Scanner(InputStream s) { + buffer = new Buffer(s); + Init(); + } + + void Init() { + pos = -1; + line = 1; + col = 0; + charPos = -1; + oldEols = 0; + NextCh(); + if (ch == 0xEF) { // check optional byte order mark for UTF-8 + NextCh(); + int ch1 = ch; + NextCh(); + int ch2 = ch; + if (ch1 != 0xBB || ch2 != 0xBF) { + throw new FatalError("Illegal byte order mark at start of file"); + } + buffer = new UTF8Buffer(buffer); + col = 0; + charPos = -1; + NextCh(); + } + pt = tokens = new Token(); // first token is a dummy + } + + void NextCh() { + if (oldEols > 0) { + ch = EOL; + oldEols--; + } else { + pos = buffer.getPos(); + // buffer reads unicode chars, if UTF8 has been detected + ch = buffer.Read(); + col++; + charPos++; + // replace isolated '\r' by '\n' in order to make + // eol handling uniform across Windows, Unix and Mac + if (ch == '\r' && buffer.Peek() != '\n') + ch = EOL; + if (ch == EOL) { + line++; + col = 0; + } + } + + } + + void AddCh() { + if (tlen >= tval.length) { + char[] newBuf = new char[2 * tval.length]; + System.arraycopy(tval, 0, newBuf, 0, tval.length); + tval = newBuf; + } + if (ch != Buffer.EOF) { + tval[tlen++] = (char)ch; + + NextCh(); + } + } + + + boolean Comment0() { + int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos; + NextCh(); + if (ch == '/') { + NextCh(); + for(;;) { + if (ch == 10) { + level--; + if (level == 0) { oldEols = line - line0; NextCh(); return true; } + NextCh(); + } else if (ch == Buffer.EOF) return false; + else NextCh(); + } + } else { + buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0; + } + return false; + } + + boolean Comment1() { + int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos; + NextCh(); + if (ch == '*') { + NextCh(); + for(;;) { + if (ch == '*') { + NextCh(); + if (ch == '/') { + level--; + if (level == 0) { oldEols = line - line0; NextCh(); return true; } + NextCh(); + } + } else if (ch == Buffer.EOF) return false; + else NextCh(); + } + } else { + buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0; + } + return false; + } + + + void CheckLiteral() { + String val = t.val; + + Object kind = literals.get(val); + if (kind != null) { + t.kind = ((Integer) kind).intValue(); + } + } + + Token NextToken() { + while (ch == ' ' || + ch >= 9 && ch <= 10 || ch == 13 + ) NextCh(); + if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken(); + int recKind = noSym; + int recEnd = pos; + t = new Token(); + t.pos = pos; + t.col = col; + t.line = line; + t.charPos = charPos; + int state = start.state(ch); + tlen = 0; + AddCh(); + + loop: for (;;) { + switch (state) { + case -1: { + t.kind = eofSym; + break loop; + } // NextCh already done + case 0: { + if (recKind != noSym) { + tlen = recEnd - t.pos; + SetScannerBehindT(); + } + t.kind = recKind; + break loop; + } // NextCh already done + case 1: + recEnd = pos; recKind = 1; + if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} + else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;} + case 2: + if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;} + else if (ch == '"') {AddCh(); state = 3; break;} + else {state = 0; break;} + case 3: + {t.kind = 2; break loop;} + case 4: + recEnd = pos; recKind = 3; + if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;} + else {t.kind = 3; break loop;} + case 5: + {t.kind = 3; break loop;} + case 6: + {t.kind = 5; break loop;} + case 7: + {t.kind = 6; break loop;} + case 8: + {t.kind = 8; break loop;} + case 9: + {t.kind = 9; break loop;} + case 10: + {t.kind = 11; break loop;} + case 11: + {t.kind = 16; break loop;} + case 12: + {t.kind = 17; break loop;} + case 13: + {t.kind = 18; break loop;} + case 14: + if (ch == '=') {AddCh(); state = 15; break;} + else {state = 0; break;} + case 15: + {t.kind = 19; break loop;} + case 16: + {t.kind = 20; break loop;} + case 17: + {t.kind = 21; break loop;} + case 18: + {t.kind = 22; break loop;} + case 19: + {t.kind = 23; break loop;} + case 20: + recEnd = pos; recKind = 10; + if (ch == '=') {AddCh(); state = 13; break;} + else {t.kind = 10; break loop;} + case 21: + recEnd = pos; recKind = 14; + if (ch == '=') {AddCh(); state = 11; break;} + else {t.kind = 14; break loop;} + case 22: + recEnd = pos; recKind = 15; + if (ch == '=') {AddCh(); state = 12; break;} + else {t.kind = 15; break loop;} + + } + } + t.val = new String(tval, 0, tlen); + return t; + } + + private void SetScannerBehindT() { + buffer.setPos(t.pos); + NextCh(); + line = t.line; + col = t.col; + charPos = t.charPos; + for (int i = 0; i < tlen; i++) + NextCh(); + } + + // get the next token (possibly a token already seen during peeking) + public Token Scan() { + if (tokens.next == null) { + return NextToken(); + } else { + pt = tokens = tokens.next; + return tokens; + } + } + + // get the next token, ignore pragmas + public Token Peek() { + do { + if (pt.next == null) { + pt.next = NextToken(); + } + pt = pt.next; + } while (pt.kind > maxT); // skip pragmas + + return pt; + } + + // make sure that peeking starts at current scan position + public void ResetPeek() { + pt = tokens; + } + + // The following methods are used for the CLNG Editor and will be called with java.Reflection. + // If the editor won't be used these 3 functions are obsolete, + // otherwise changes within the signature of the methods will result in Syntax Highlighting not working properly +// anymore. + + // get the offset of the next Token + public int getPeekTokenOffset() { + return pt.pos; + } + + // get the String value of the Token + public String getPeekTokenVal() { + return pt.val; + } + + // get the Kind value of the Token + public int getPeekTokenKind() { + return pt.kind; + } + +} // end Scanner diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,158 @@ +COMPILER SimpleLanguage + +CHARACTERS + +letter = 'A'..'Z' + 'a'..'z'. +nonZeroDigit = "123456789". +digit = "0123456789". +cr = '\r'. +lf = '\n'. +tab = '\t'. +stringChar = ANY - "\"" - '\\' - cr - lf. + +TOKENS + +identifier = letter {letter | digit}. +stringLiteral = "\"" { stringChar } "\"". +numericLiteral = "0" | nonZeroDigit { digit }. + +PRAGMAS + +COMMENTS FROM "/*" TO "*/" +COMMENTS FROM "//" TO lf +IGNORE cr + lf + tab + +PRODUCTIONS + +SimpleLanguage += +Function +{ + Function +} +. + +Function += +"function" (. factory.startFunction(); .) +identifier (. String name = t.val; .) +Block (. factory.createFunction(body, name); .) +. + +Block += (. List statements = new ArrayList<>(); .) +"{" +{ + Statement (. statements.add(statement); .) +} +"}" (. result = factory.createBlock(statements); .) +. + +Statement += (. result = null; .) +( + WhileStatement +| + AssignmentStatement +| + OutputStatement +| + ReturnStatement +) +. + +WhileStatement += +"while" +"(" +Expression +")" +Block (. result = factory.createWhile(condition, body); .) +. + +AssignmentStatement += +identifier (. String name = t.val; .) +"=" +Expression +";" (. result = factory.createAssignment(name, rvalue); .) +. + +OutputStatement += (. List expressions = new ArrayList<>(); .) +"print" +{ + Expression (. expressions.add(value); .) +} +";" (. result = factory.createPrint(expressions); .) +. + +ReturnStatement += +"return" +Expression ";" (. result = factory.createReturn(value); .) +. + +Expression += +ValueExpression +[ + ("<" | ">" | "<=" | ">=" | "==" | "!=" ) (. String op = t.val; .) + ValueExpression (. result = factory.createBinary(op, result, right); .) +] +. + +ValueExpression += +Term +{ + ("+" | "-") (. String op = t.val; .) + Term (. result = factory.createBinary(op, result, right); .) +} +. + +Term += +Factor +{ + ("*" | "/") (. String op = t.val; .) + Factor (. result = factory.createBinary(op, result, right); .) +} +. + +Factor += (. result = null; .) +( + TimeRef +| + VariableRef +| + StringLiteral +| + NumericLiteral +| + "(" Expression ")" +) +. + +TimeRef += +"time" (. result = factory.createTime(); .) +. + +VariableRef += +identifier (. result = factory.createLocal(t.val); .) +. + +StringLiteral += +stringLiteral (. result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); .) +. + +NumericLiteral += +numericLiteral (. result = factory.createNumericLiteral(t.val); .) +. + +END SimpleLanguage. diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/tools/GraphPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/tools/GraphPrinter.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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.sl.tools; + +import com.oracle.truffle.api.nodes.*; + +public class GraphPrinter { + + public static void print(Node root) { + print(root, 0); + } + + private static void print(Node node, int level) { + for (int i = 0; i < level; i++) { + System.out.print(" "); + } + System.out.println(node == null ? "empty" : node.getClass().getSimpleName()); + if (node != null) { + for (Node child : node.getChildren()) { + print(child, level + 1); + } + } + } +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/types/FrameSlotNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/types/FrameSlotNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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.sl.types; + +import com.oracle.truffle.api.frame.*; + +public abstract class FrameSlotNode extends TypedNode implements FrameSlotTypeListener { + + protected final FrameSlot slot; + + public FrameSlotNode(FrameSlot slot) { + this.slot = slot; + slot.registerOneShotTypeListener(this); + } + + @Override + public void typeChanged(FrameSlot changedSlot, Class< ? > oldType) { + if (getParent() != null) { + specialize(changedSlot.getType()); + } + } + + protected abstract void specialize(Class< ? > clazz); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/types/TypedNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/types/TypedNode.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,51 @@ +/* + * 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.sl.types; + +import java.math.*; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; + +public abstract class TypedNode extends ConditionNode { + + @Override + public final boolean executeCondition(VirtualFrame frame) { + try { + return executeBoolean(frame); + } catch (UnexpectedResultException ex) { + throw new RuntimeException("Illegal type for condition: " + ex.getResult().getClass().getSimpleName()); + } + } + + public abstract boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException; + + public abstract int executeInteger(VirtualFrame frame) throws UnexpectedResultException; + + public abstract BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException; + + public abstract String executeString(VirtualFrame frame) throws UnexpectedResultException; + + public abstract Object executeGeneric(VirtualFrame frame); +} diff -r 46f945023189 -r 570d8e4c6dfb graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/types/Types.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/types/Types.java Mon Jan 07 13:04:04 2013 +0100 @@ -0,0 +1,78 @@ +/* + * 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.sl.types; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; + +@TypeSystem(types = {int.class, BigInteger.class, boolean.class, String.class}, nodeBaseClass = TypedNode.class, hasVoid = true) +public class Types { + + @TypeCheck + public boolean isInteger(Object value) { + return value instanceof Integer || (value instanceof BigInteger && ((BigInteger) value).bitLength() < Integer.SIZE); + } + + @TypeCast + public int asInteger(Object value) { + assert isInteger(value); + if (value instanceof Integer) { + return (int) value; + } else { + int result = ((BigInteger) value).intValue(); + assert BigInteger.valueOf(result).equals(value) : "Loosing precision"; + return result; + } + } + + @GuardCheck + public boolean isString(Object a, Object b) { + return a instanceof String || b instanceof String; + } + + @TypeCheck + public boolean isBigInteger(Object value) { + return value instanceof Integer || value instanceof BigInteger; + } + + @TypeCast + public BigInteger asBigInteger(Object value) { + if (value instanceof Integer) { + return BigInteger.valueOf((int) value); + } else { + return (BigInteger) value; + } + } + + @TypeCast + public BigInteger asBigInteger(int value) { + return BigInteger.valueOf(value); + } + + @TypeCheck + public boolean isBigInteger(@SuppressWarnings("unused") int value) { + return true; + } + +} diff -r 46f945023189 -r 570d8e4c6dfb mx/commands.py --- a/mx/commands.py Fri Dec 21 15:54:59 2012 +0100 +++ b/mx/commands.py Mon Jan 07 13:04:04 2013 +0100 @@ -396,7 +396,14 @@ log = open(logFile, 'w') ret = False while True: - line = stdout.readline().decode(sys.stdout.encoding) + + # encoding may be None on windows plattforms + if sys.stdout.encoding is None: + encoding = 'utf-8' + else: + encoding = sys.stdout.encoding + + line = stdout.readline().decode(encoding) if logFile: log.write(line.encode('utf-8')) line = line.strip() @@ -1068,6 +1075,20 @@ mx.abort('jacocoreport takes only one argument : an output directory') mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) +def jar(args): + parser = ArgumentParser(prog='mx jar'); + parser.add_argument('projects', nargs=REMAINDER, metavar='projects...') + args = parser.parse_args(args) + + if not args.projects: + mx.abort('Please specify at least one project to jar.') + + for pname in args.projects: + p = mx.project(pname, fatalIfMissing=True) + outputDir = p.output_dir() + targetJar = join(p.dir, p.name + '.jar') + mx.jar(targetJar, [outputDir]) + def site(args): """create a website containing javadoc and the project dependency graph""" @@ -1094,6 +1115,7 @@ 'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'], 'scaladacapo': [scaladacapo, '[[n] benchmark] [VM options|@Scala DaCapo options]'], 'specjvm2008': [specjvm2008, '[VM options|@specjvm2008 options]'], + 'jar': [jar, '[-options]'], #'example': [example, '[-v] example names...'], 'gate' : [gate, '[-options]'], 'gv' : [gv, ''], diff -r 46f945023189 -r 570d8e4c6dfb mx/projects --- a/mx/projects Fri Dec 21 15:54:59 2012 +0100 +++ b/mx/projects Mon Jan 07 13:04:04 2013 +0100 @@ -137,10 +137,17 @@ project@com.oracle.graal.alloc@checkstyle=com.oracle.graal.graph project@com.oracle.graal.alloc@javaCompliance=1.7 +# graal.word +project@com.oracle.graal.word@subDir=graal +project@com.oracle.graal.word@sourceDirs=src +project@com.oracle.graal.word@dependencies=com.oracle.graal.phases +project@com.oracle.graal.word@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.word@javaCompliance=1.7 + # graal.snippets project@com.oracle.graal.snippets@subDir=graal project@com.oracle.graal.snippets@sourceDirs=src -project@com.oracle.graal.snippets@dependencies=com.oracle.graal.compiler,com.oracle.graal.java +project@com.oracle.graal.snippets@dependencies=com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.word project@com.oracle.graal.snippets@checkstyle=com.oracle.graal.graph project@com.oracle.graal.snippets@javaCompliance=1.7 @@ -269,3 +276,32 @@ project@com.oracle.truffle.api.test@checkstyle=com.oracle.graal.graph project@com.oracle.truffle.api.test@javaCompliance=1.7 +# truffle.api.codegen +project@com.oracle.truffle.api.codegen@subDir=graal +project@com.oracle.truffle.api.codegen@sourceDirs=src +project@com.oracle.truffle.api.codegen@dependencies=com.oracle.truffle.api +project@com.oracle.truffle.api.codegen@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.api.codegen@javaCompliance=1.7 + +# truffle.codegen.processor +project@com.oracle.truffle.codegen.processor@subDir=graal +project@com.oracle.truffle.codegen.processor@sourceDirs=src +project@com.oracle.truffle.codegen.processor@dependencies=com.oracle.truffle.api.codegen +project@com.oracle.truffle.codegen.processor@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.codegen.processor@javaCompliance=1.7 + +# truffle.sl +project@com.oracle.truffle.sl@subDir=graal +project@com.oracle.truffle.sl@sourceDirs=src +project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.codegen +project@com.oracle.truffle.sl@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.sl@javaCompliance=1.7 +project@com.oracle.truffle.sl@annotationProcessors=com.oracle.truffle.codegen.processor + +# truffle.sl.test +project@com.oracle.truffle.sl.test@subDir=graal +project@com.oracle.truffle.sl.test@sourceDirs=src +project@com.oracle.truffle.sl.test@dependencies=com.oracle.truffle.sl,JUNIT +project@com.oracle.truffle.sl.test@checkstyle=com.oracle.graal.graph +project@com.oracle.truffle.sl.test@javaCompliance=1.7 + diff -r 46f945023189 -r 570d8e4c6dfb mxtool/mx.py --- a/mxtool/mx.py Fri Dec 21 15:54:59 2012 +0100 +++ b/mxtool/mx.py Mon Jan 07 13:04:04 2013 +0100 @@ -188,14 +188,17 @@ if not exists(s): os.mkdir(s) - def all_deps(self, deps, includeLibs, includeSelf=True): + def all_deps(self, deps, includeLibs, includeSelf=True, includeAnnotationProcessors=False): """ Add the transitive set of dependencies for this project, including libraries if 'includeLibs' is true, to the 'deps' list. """ + childDeps = list(self.deps) + if includeAnnotationProcessors and hasattr(self, 'annotationProcessors') and len(self.annotationProcessors) > 0: + childDeps = self.annotationProcessors + childDeps if self in deps: return deps - for name in self.deps: + for name in childDeps: assert name != self.name dep = _libs.get(name, None) if dep is not None: @@ -208,7 +211,7 @@ abort('project named ' + name + ' required by ' + self.name + ' is ignored') abort('dependency named ' + name + ' required by ' + self.name + ' is not found') if not dep in deps: - dep.all_deps(deps, includeLibs) + dep.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors) if not self in deps and includeSelf: deps.append(self) return deps @@ -464,7 +467,7 @@ srcDirs = pop_list(attrs, 'sourceDirs') deps = pop_list(attrs, 'dependencies') ap = pop_list(attrs, 'annotationProcessors') - deps += ap + #deps += ap javaCompliance = attrs.pop('javaCompliance', None) subDir = attrs.pop('subDir', None); if subDir is None: @@ -478,9 +481,6 @@ abort('javaCompliance property required for non-native project ' + name) if len(ap) > 0: p.annotationProcessors = ap - apc = pop_list(attrs, 'annotationProcessorClasses') - if len(apc) > 0: - p.annotationProcessorClasses = apc p.__dict__.update(attrs) self.projects.append(p) @@ -729,7 +729,7 @@ entryPath = zi.filename yield zf, entryPath -def sorted_deps(projectNames=None, includeLibs=False): +def sorted_deps(projectNames=None, includeLibs=False, includeAnnotationProcessors=False): """ Gets projects and libraries sorted such that dependencies are before the projects that depend on them. Unless 'includeLibs' is @@ -742,7 +742,7 @@ projects = [project(name) for name in projectNames] for p in projects: - p.all_deps(deps, includeLibs) + p.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors) return deps class ArgParser(ArgumentParser): @@ -1296,7 +1296,7 @@ if args.only is not None: sortedProjects = [project(name) for name in args.only.split(',')] else: - sortedProjects = sorted_deps(projects) + sortedProjects = sorted_deps(projects, includeAnnotationProcessors=True) for p in sortedProjects: if p.native: @@ -1380,7 +1380,9 @@ log('could not file .class directive in Jasmin source: ' + src) else: dst = join(outputDir, src[len(sourceDir) + 1:]) - if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) != os.path.getmtime(src)): + if not exists(dirname(dst)): + os.makedirs(dirname(dst)) + if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)): shutil.copyfile(src, dst) if not mustBuild: @@ -1410,18 +1412,12 @@ javacArgs += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(java().debug_port)] if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0: - annotationProcessors = [] - for apProject in p.annotationProcessors: - apClasses = project(apProject).annotationProcessorClasses - if len(apClasses) == 0: - abort("Project " + p + " specifies " + apProject + " as an annotation processor but " + apProject + " does not specifiy any annotation processor class") - annotationProcessors += apClasses - + processorPath = classpath(p.annotationProcessors, resolve=True) genDir = p.source_gen_dir(); if exists(genDir): shutil.rmtree(genDir) os.mkdir(genDir) - javacArgs += ['-processor', ",".join(annotationProcessors), "-s", genDir] + javacArgs += ['-processorpath', join(processorPath), '-s', genDir] else: javacArgs += ['-proc:none'] @@ -1442,7 +1438,7 @@ jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs') if not exists(jdtProperties): # Try to fix a missing properties file by running eclipseinit - eclipseinit([]) + eclipseinit([], buildProcessorJars=False) if not exists(jdtProperties): log('JDT properties file {0} not found'.format(jdtProperties)) else: @@ -1467,37 +1463,61 @@ return args return None -def processorjars(args): - hasProcessorJars = [] +def processorjars(): + projects = set([]) for p in sorted_deps(): - if hasattr(p, 'annotationProcessorClasses') and len(p.annotationProcessorClasses) > 0: - hasProcessorJars.append(p) + if _needsEclipseJarBuild(p): + projects.add(p) - if len(hasProcessorJars) <= 0: + if len(projects) <= 0: return - build(['--projects', ",".join(map(lambda p: p.name, hasProcessorJars))]) - - for p in hasProcessorJars: - spDir = join(p.output_dir(), 'META-INF', 'services') - if not exists(spDir): - os.makedirs(spDir) - spFile = join(spDir, 'javax.annotation.processing.Processor') - with open(spFile, 'w') as fp: - fp.writelines(p.annotationProcessorClasses) - created = False - for dep in p.all_deps([], False): - if created: - cmd = 'uf' - else: - cmd = 'cf' - created = True - jarCmd = [java().jar, cmd, join(p.dir, p.name + 'AnnotationProcessor.jar'), '-C', dep.output_dir(), '.'] - subprocess.check_call(jarCmd) - log('added ' + dep.name + ' to ' + p.name + '.jar'); + build(['--projects', ",".join(map(lambda p: p.name, projects))]) + + for p in projects: + targetJar = join(p.dir, p.name + '.jar') + jar(targetJar, [p.output_dir()]) +def jar(destFileName, dirs): + latestMod = _latestModification(dirs) + + if exists(destFileName): + mod = os.path.getmtime(destFileName) + if int(round(latestMod*1000)) == int(round(mod*1000)): + # nothing todo + return + + if latestMod is None and exists(destFileName): + return + + jarCmd = [java().jar, 'cf', destFileName] + + for directory in dirs: + jarCmd += ['-C', directory, '.'] + + subprocess.check_call(jarCmd) + log('Written jar file {0}'.format(destFileName)) + + atime = os.path.getatime(destFileName) + os.utime(destFileName, (atime, latestMod)) + +def _latestModification(directories): + latestMod = None + for directory in directories: + if not os.path.exists (directory): + continue + for root, _, files in os.walk(directory): + for names in files: + filepath = os.path.join(root, names) + mod = os.path.getmtime(filepath) + if latestMod is None: + latestMod = mod + elif mod > latestMod: + latestMod = mod + return latestMod + def canonicalizeprojects(args): """process all project files to canonicalize the dependencies @@ -1860,13 +1880,14 @@ os.makedirs(eclipseLaunches) return update_file(join(eclipseLaunches, name + '.launch'), launch) -def eclipseinit(args, suite=None): +def eclipseinit(args, suite=None, buildProcessorJars=True): """(re)generate Eclipse project configurations""" if suite is None: suite = _mainSuite - processorjars([]) + if buildProcessorJars: + processorjars() for p in projects(): if p.native: @@ -1884,6 +1905,12 @@ os.mkdir(srcDir) out.element('classpathentry', {'kind' : 'src', 'path' : src}) + if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0: + genDir = p.source_gen_dir(); + if not exists(genDir): + os.mkdir(genDir) + out.element('classpathentry', {'kind' : 'src', 'path' : 'src_gen'}) + # Every Java program depends on the JRE out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.jdt.launching.JRE_CONTAINER'}) @@ -1975,6 +2002,23 @@ out.element('name', data=buildCommand) out.element('arguments', data='') out.close('buildCommand') + + if (_needsEclipseJarBuild(p)): + out.open('buildCommand') + out.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder') + out.element('triggers', data='auto,full,incremental,') + out.open('arguments') + out.open('dictionary') + out.element('key', data = 'LaunchConfigHandle') + out.element('value', data = _genEclipseJarBuild(p)) + out.close('dictionary') + out.open('dictionary') + out.element('key', data = 'incclean') + out.element('value', data = 'true') + out.close('dictionary') + out.close('arguments') + out.close('buildCommand') + out.close('buildSpec') out.open('natures') out.element('nature', data='org.eclipse.jdt.core.javanature') @@ -2010,7 +2054,6 @@ out.element('factorypathentry', {'kind' : 'PLUGIN', 'id' : 'org.eclipse.jst.ws.annotations.core', 'enabled' : 'true', 'runInBatchMode' : 'false'}) for ap in p.annotationProcessors: apProject = project(ap) - out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + apProject.name + '/' + apProject.name + 'AnnotationProcessor.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'}) for dep in apProject.all_deps([], True): if dep.isLibrary(): if not hasattr(dep, 'eclipse.container') and not hasattr(dep, 'eclipse.project'): @@ -2022,11 +2065,65 @@ # safest to simply use absolute paths. path = join(suite.dir, path) out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'}) + else: + out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'}) out.close('factorypath') update_file(join(p.dir, '.factorypath'), out.xml(indent='\t', newl='\n')) make_eclipse_attach('localhost', '8000', deps=projects()) + +def _needsEclipseJarBuild(p): + processors = set([]) + + for otherProject in projects(): + if hasattr(otherProject, 'annotationProcessors') and len(otherProject.annotationProcessors) > 0: + for processorName in otherProject.annotationProcessors: + processors.add(project(processorName, fatalIfMissing=True)) + + if p in processors: + return True + + for otherProject in processors: + deps = otherProject.all_deps([], True) + if p in deps: + return True + + return False + +def _genEclipseJarBuild(p): + launchOut = XMLDoc(); + launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'}) + launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': '${project}'}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': 'false'}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': 'false'}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true'}) + + baseDir = dirname(dirname(os.path.abspath(__file__))) + + cmd = 'mx.sh' + if get_os() == 'windows': + cmd = 'mx.cmd' + launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': join(baseDir, cmd) }) + launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'auto,full,incremental'}) + launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': ''.join(['jar', ' ', p.name])}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED','value': 'true'}) + launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': baseDir}) + + + launchOut.close('launchConfiguration') + + externalToolDir = join(p.dir, '.externalToolBuilders') + + if not exists(externalToolDir): + os.makedirs(externalToolDir) + update_file(join(externalToolDir, 'Jar.launch'), launchOut.xml(indent='\t', newl='\n')) + + return "/.externalToolBuilders/Jar.launch" + + + + def netbeansinit(args, suite=None): """(re)generate NetBeans project configurations""" @@ -2063,9 +2160,10 @@ out.element('explicit-platform', {'explicit-source-supported' : 'true'}) out.open('source-roots') out.element('root', {'id' : 'src.dir'}) + if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0: + out.element('root', {'id' : 'src.ap-source-output.dir'}) out.close('source-roots') out.open('test-roots') - out.element('root', {'id' : 'test.src.dir'}) out.close('test-roots') out.close('data') @@ -2099,12 +2197,18 @@ out = StringIO.StringIO() jdkPlatform = 'JDK_' + java().version + annotationProcessorEnabled = "false" + annotationProcessorReferences = "" + annotationProcessorSrcFolder = "" + if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0: + annotationProcessorEnabled = "true" + annotationProcessorSrcFolder = "src.ap-source-output.dir=${build.generated.sources.dir}/ap-source-output" + content = """ -annotation.processing.enabled=false -annotation.processing.enabled.in.editor=false +annotation.processing.enabled=""" + annotationProcessorEnabled + """ +annotation.processing.enabled.in.editor=""" + annotationProcessorEnabled + """ annotation.processing.processors.list= annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output application.title=""" + p.name + """ application.vendor=mx build.classes.dir=${build.dir} @@ -2134,15 +2238,11 @@ # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=false -javac.processorpath=\\ - ${javac.classpath} javac.source=1.7 javac.target=1.7 javac.test.classpath=\\ ${javac.classpath}:\\ ${build.classes.dir} -javac.test.processorpath=\\ - ${javac.test.classpath} javadoc.additionalparam= javadoc.author=false javadoc.encoding=${source.encoding} @@ -2170,7 +2270,8 @@ run.test.classpath=\\ ${javac.test.classpath}:\\ ${build.test.classes.dir} -test.src.dir= +test.src.dir=./test +""" + annotationProcessorSrcFolder + """ source.encoding=UTF-8""".replace(':', os.pathsep).replace('/', os.sep) print >> out, content @@ -2188,7 +2289,19 @@ print >> out, 'src.' + src + '.dir=${' + ref + '}' javacClasspath = [] - for dep in p.all_deps([], True): + + deps = p.all_deps([], True) + annotationProcessorOnlyDeps = [] + if hasattr(p, 'annotationProcessors') and len(p.annotationProcessors) > 0: + for ap in p.annotationProcessors: + apProject = project(ap) + if not apProject in deps: + deps.append(apProject) + annotationProcessorOnlyDeps.append(apProject) + + annotationProcessorReferences = []; + + for dep in deps: if dep == p: continue; @@ -2208,11 +2321,16 @@ print >> out, 'project.' + n + '=' + relDepPath print >> out, ref + '=${project.' + n + '}/dist/' + dep.name + '.jar' - javacClasspath.append('${' + ref + '}') + if not dep in annotationProcessorOnlyDeps: + javacClasspath.append('${' + ref + '}') + else: + annotationProcessorReferences.append('${' + ref + '}') + annotationProcessorReferences += ":\\\n ${" + ref + "}" print >> out, 'javac.classpath=\\\n ' + (os.pathsep + '\\\n ').join(javacClasspath) - - + print >> out, 'javac.test.processorpath=${javac.test.classpath}\\\n ' + (os.pathsep + '\\\n ').join(annotationProcessorReferences) + print >> out, 'javac.processorpath=${javac.classpath}\\\n ' + (os.pathsep + '\\\n ').join(annotationProcessorReferences) + updated = update_file(join(p.dir, 'nbproject', 'project.properties'), out.getvalue()) or updated out.close() @@ -2223,7 +2341,6 @@ def ideclean(args, suite=None): """remove all Eclipse and NetBeans project configurations""" - def rm(path): if exists(path): os.remove(path) @@ -2233,10 +2350,17 @@ continue shutil.rmtree(join(p.dir, '.settings'), ignore_errors=True) + shutil.rmtree(join(p.dir, '.externalToolBuilders'), ignore_errors=True) shutil.rmtree(join(p.dir, 'nbproject'), ignore_errors=True) rm(join(p.dir, '.classpath')) rm(join(p.dir, '.project')) rm(join(p.dir, 'build.xml')) + rm(join(p.dir, 'eclipse-build.xml')) + try: + rm(join(p.dir, p.name + '.jar')) + except: + log("Error removing {0}".format(p.name + '.jar')) + def ideinit(args, suite=None): """(re)generate Eclipse and NetBeans project configurations""" diff -r 46f945023189 -r 570d8e4c6dfb src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Fri Dec 21 15:54:59 2012 +0100 +++ b/src/share/vm/runtime/arguments.cpp Mon Jan 07 13:04:04 2013 +0100 @@ -2249,6 +2249,7 @@ "com.oracle.graal.hotspot", "com.oracle.graal.asm", "com.oracle.graal.alloc", + "com.oracle.graal.word", "com.oracle.graal.snippets", "com.oracle.graal.compiler", "com.oracle.graal.loop",