# 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 extends ValueNode> 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 extends ValueNode> 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 extends Node> 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 extends TypeMirror> 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 extends TypeMirror> 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 extends ExecutableElement> 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, P> 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, P> 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, P>) 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 extends CodeImport> 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 extends CodeImport> 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 extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+ if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) {
+ visitAnnotationValue(values.get(defaultElement));
+ } else {
+ Set extends ExecutableElement> 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 extends ExecutableElement> 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 extends AnnotationMirror> 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 extends ExecutableElement> 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 extends AnnotationMirror> 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 extends TemplateMethod> 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 extends TemplateMethod> 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