# HG changeset patch # User Christian Wimmer # Date 1357330091 28800 # Node ID 2912b72d840ad46a1a35fc553e97c28d89293ecb # Parent 57edf6b07d3630a42ab17f500d0612f18db45f66 More complete and reusable Word type diff -r 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/UnsignedMath.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotCurrentRawThreadNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Fri Jan 04 12:08:11 2013 -0800 @@ -42,6 +42,11 @@ } @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(kind().toJavaClass()); + } + + @Override public String toString() { return type.toString(); } diff -r 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Fri Jan 04 12:08:11 2013 -0800 @@ -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}. @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Fri Jan 04 12:08:11 2013 -0800 @@ -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).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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +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 57edf6b07d36 -r 2912b72d840a 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 Wed Jan 02 18:52:33 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.word; + +import static com.oracle.graal.graph.UnsafeAccess.*; + +import java.lang.annotation.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +public abstract class Word implements Signed, Unsigned, Pointer { + /** + * Links a method to a canonical operation represented by an {@link Opcode} val. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface Operation { + Class node() default ValueNode.class; + boolean rightOperandIsInt() default false; + Opcode opcode() default Opcode.NODE_CLASS; + Condition condition() default Condition.EQ; + } + + /** + * The canonical {@link Operation} represented by a method in the {@link Word} class. + */ + public enum Opcode { + NODE_CLASS, + COMPARISON, + NOT, + READ, + READ_FINAL, + WRITE, + ZERO, + FROM_UNSIGNED, + FROM_SIGNED, + FROM_OBJECT, + TO_OBJECT, + TO_RAW_VALUE, + } + + private static Word box(long val) { + return HostedWord.box(val); + } + + protected abstract long unbox(); + + private static Word intParam(int val) { + return box(val); + } + + + /** + * The constant 0, i.e., the word with no bits set. There is no difference between a signed and unsigned zero. + * @return the constant 0. + */ + @Operation(opcode = Opcode.ZERO) + public static Word zero() { + return box(0L); + } + + /** + * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned 64-bit value (in contrast to the semantics of a Java long). + * @param val a 64 bit unsigned value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_UNSIGNED) + public static Word unsigned(long val) { + return box(val); + } + + /** + * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned 32-bit value (in contrast to the semantics of a Java int). + * @param val a 32 bit unsigned value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_UNSIGNED) + public static Word unsigned(int val) { + return box(val & 0xffffffffL); + } + + /** + * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed 64-bit value (unchanged semantics of a Java long). + * @param val a 64 bit signed value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_SIGNED) + public static Word signed(long val) { + return box(val); + } + + /** + * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed 32-bit value (unchanged semantics of a Java int). + * @param val a 32 bit signed value + * @return the value cast to Word + */ + @Operation(opcode = Opcode.FROM_SIGNED) + public static Word signed(int val) { + return box(val); + } + + @Override + @Operation(opcode = Opcode.TO_RAW_VALUE) + public long rawValue() { + return unbox(); + } + + @Operation(opcode = Opcode.FROM_OBJECT) + public static native Pointer fromObject(Object val); + + @Override + @Operation(opcode = Opcode.TO_OBJECT) + public native Object toObject(); + + + @Override + @Operation(node = IntegerAddNode.class) + public Word add(Signed val) { + return add((Word) val); + } + @Override + @Operation(node = IntegerAddNode.class) + public Word add(Unsigned val) { + return add((Word) val); + } + @Override + @Operation(node = IntegerAddNode.class) + public Word add(int val) { + return add(intParam(val)); + } + @Operation(node = IntegerAddNode.class) + public Word add(Word val) { + return box(unbox() + val.unbox()); + } + + @Override + @Operation(node = IntegerSubNode.class) + public Word subtract(Signed val) { + return subtract((Word) val); + } + @Override + @Operation(node = IntegerSubNode.class) + public Word subtract(Unsigned val) { + return subtract((Word) val); + } + @Override + @Operation(node = IntegerSubNode.class) + public Word subtract(int val) { + return subtract(intParam(val)); + } + @Operation(node = IntegerSubNode.class) + public Word subtract(Word val) { + return box(unbox() - val.unbox()); + } + + @Override + @Operation(node = IntegerMulNode.class) + public Word multiply(Signed val) { + return multiply((Word) val); + } + @Override + @Operation(node = IntegerMulNode.class) + public Word multiply(Unsigned val) { + return multiply((Word) val); + } + @Override + @Operation(node = IntegerMulNode.class) + public Word multiply(int val) { + return multiply(intParam(val)); + } + @Operation(node = IntegerMulNode.class) + public Word multiply(Word val) { + return box(unbox() * val.unbox()); + } + + @Override + @Operation(node = IntegerDivNode.class) + public Word signedDivide(Signed val) { + return signedDivide((Word) val); + } + @Override + @Operation(node = IntegerMulNode.class) + public Word signedDivide(int val) { + return signedDivide(intParam(val)); + } + @Operation(node = IntegerMulNode.class) + public Word signedDivide(Word val) { + return box(unbox() / val.unbox()); + } + + @Override + @Operation(node = UnsignedDivNode.class) + public Word unsignedDivide(Unsigned val) { + return unsignedDivide((Word) val); + } + @Override + @Operation(node = UnsignedDivNode.class) + public Word unsignedDivide(int val) { + return signedDivide(intParam(val)); + } + @Operation(node = UnsignedDivNode.class) + public Word unsignedDivide(Word val) { + return box(UnsignedMath.divide(unbox(), val.unbox())); + } + + @Override + @Operation(node = IntegerRemNode.class) + public Word signedRemainder(Signed val) { + return signedRemainder((Word) val); + } + @Override + @Operation(node = IntegerRemNode.class) + public Word signedRemainder(int val) { + return signedRemainder(intParam(val)); + } + @Operation(node = IntegerRemNode.class) + public Word signedRemainder(Word val) { + return box(unbox() % val.unbox()); + } + + @Override + @Operation(node = UnsignedRemNode.class) + public Word unsignedRemainder(Unsigned val) { + return unsignedRemainder((Word) val); + } + @Override + @Operation(node = UnsignedRemNode.class) + public Word unsignedRemainder(int val) { + return signedRemainder(intParam(val)); + } + @Operation(node = UnsignedRemNode.class) + public Word unsignedRemainder(Word val) { + return box(UnsignedMath.remainder(unbox(), val.unbox())); + } + + @Override + @Operation(node = LeftShiftNode.class, rightOperandIsInt = true) + public Word shiftLeft(Unsigned val) { + return shiftLeft((Word) val); + } + @Override + @Operation(node = LeftShiftNode.class, rightOperandIsInt = true) + public Word shiftLeft(int val) { + return shiftLeft(intParam(val)); + } + @Operation(node = LeftShiftNode.class, rightOperandIsInt = true) + public Word shiftLeft(Word val) { + return box(unbox() << val.unbox()); + } + + @Override + @Operation(node = RightShiftNode.class, rightOperandIsInt = true) + public Word signedShiftRight(Unsigned val) { + return signedShiftRight((Word) val); + } + @Override + @Operation(node = RightShiftNode.class, rightOperandIsInt = true) + public Word signedShiftRight(int val) { + return signedShiftRight(intParam(val)); + } + @Operation(node = RightShiftNode.class, rightOperandIsInt = true) + public Word signedShiftRight(Word val) { + return box(unbox() >> val.unbox()); + } + + @Override + @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true) + public Word unsignedShiftRight(Unsigned val) { + return unsignedShiftRight((Word) val); + } + @Override + @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true) + public Word unsignedShiftRight(int val) { + return unsignedShiftRight(intParam(val)); + } + @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true) + public Word unsignedShiftRight(Word val) { + return box(unbox() >>> val.unbox()); + } + + @Override + @Operation(node = AndNode.class) + public Word and(Signed val) { + return and((Word) val); + } + @Override + @Operation(node = AndNode.class) + public Word and(Unsigned val) { + return and((Word) val); + } + @Override + @Operation(node = AndNode.class) + public Word and(int val) { + return and(intParam(val)); + } + @Operation(node = AndNode.class) + public Word and(Word val) { + return box(unbox() & val.unbox()); + } + + @Override + @Operation(node = OrNode.class) + public Word or(Signed val) { + return or((Word) val); + } + @Override + @Operation(node = OrNode.class) + public Word or(Unsigned val) { + return or((Word) val); + } + @Override + @Operation(node = OrNode.class) + public Word or(int val) { + return or(intParam(val)); + } + @Operation(node = OrNode.class) + public Word or(Word val) { + return box(unbox() | val.unbox()); + } + + @Override + @Operation(node = XorNode.class) + public Word xor(Signed val) { + return xor((Word) val); + } + @Override + @Operation(node = XorNode.class) + public Word xor(Unsigned val) { + return xor((Word) val); + } + @Override + @Operation(node = XorNode.class) + public Word xor(int val) { + return xor(intParam(val)); + } + @Operation(node = XorNode.class) + public Word xor(Word val) { + return box(unbox() ^ val.unbox()); + } + + @Override + @Operation(opcode = Opcode.NOT) + public Word not() { + return box(~unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT) + public boolean lessThan(Signed val) { + return lessThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT) + public boolean lessThan(int val) { + return lessThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT) + public boolean lessThan(Word val) { + return unbox() < val.unbox(); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE) + public boolean lessOrEqual(Signed val) { + return lessOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE) + public boolean lessOrEqual(int val) { + return lessOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE) + public boolean lessOrEqual(Word val) { + return unbox() <= val.unbox(); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT) + public boolean greaterThan(Signed val) { + return greaterThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT) + public boolean greaterThan(int val) { + return greaterThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT) + public boolean greaterThan(Word val) { + return unbox() > val.unbox(); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE) + public boolean greaterOrEqual(Signed val) { + return greaterOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE) + public boolean greaterOrEqual(int val) { + return greaterOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE) + public boolean greaterOrEqual(Word val) { + return unbox() >= val.unbox(); + } + + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT) + public boolean belowThan(Unsigned val) { + return belowThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT) + public boolean belowThan(int val) { + return belowThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT) + public boolean belowThan(Word val) { + return UnsignedMath.belowThan(unbox(), val.unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE) + public boolean belowOrEqual(Unsigned val) { + return belowOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE) + public boolean belowOrEqual(int val) { + return belowOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE) + public boolean belowOrEqual(Word val) { + return UnsignedMath.belowOrEqual(unbox(), val.unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT) + public boolean aboveThan(Unsigned val) { + return aboveThan((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT) + public boolean aboveThan(int val) { + return aboveThan(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT) + public boolean aboveThan(Word val) { + return UnsignedMath.aboveThan(unbox(), val.unbox()); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE) + public boolean aboveOrEqual(Unsigned val) { + return aboveOrEqual((Word) val); + } + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE) + public boolean aboveOrEqual(int val) { + return aboveOrEqual(intParam(val)); + } + @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE) + public boolean aboveOrEqual(Word val) { + return UnsignedMath.aboveOrEqual(unbox(), val.unbox()); + } + + + @Override + @Operation(opcode = Opcode.READ) + public byte readByte(WordBase offset) { + return unsafe.getByte(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public char readChar(WordBase offset) { + return unsafe.getChar(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public short readShort(WordBase offset) { + return unsafe.getShort(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public int readInt(WordBase offset) { + return unsafe.getInt(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public long readLong(WordBase offset) { + return unsafe.getLong(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public float readFloat(WordBase offset) { + return unsafe.getFloat(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public double readDouble(WordBase offset) { + return unsafe.getDouble(add((Word) offset).unbox()); + } + @Override + @Operation(opcode = Opcode.READ) + public Word readWord(WordBase offset) { + return box(unsafe.getAddress(add((Word) offset).unbox())); + } + @Override + @Operation(opcode = Opcode.READ) + public native Object readObject(WordBase offset); + + @Override + @Operation(opcode = Opcode.READ) + public byte readByte(int offset) { + return readByte(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public char readChar(int offset) { + return readChar(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public short readShort(int offset) { + return readShort(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public int readInt(int offset) { + return readInt(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public long readLong(int offset) { + return readLong(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public float readFloat(int offset) { + return readFloat(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public double readDouble(int offset) { + return readDouble(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public Word readWord(int offset) { + return readWord(signed(offset)); + } + @Override + @Operation(opcode = Opcode.READ) + public Object readObject(int offset) { + return readObject(signed(offset)); + } + + @Override + @Operation(opcode = Opcode.READ_FINAL) + public byte readFinalByte(WordBase offset) { + return readByte(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public char readFinalChar(WordBase offset) { + return readChar(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public short readFinalShort(WordBase offset) { + return readShort(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public int readFinalInt(WordBase offset) { + return readInt(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public long readFinalLong(WordBase offset) { + return readLong(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public float readFinalFloat(WordBase offset) { + return readFloat(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public double readFinalDouble(WordBase offset) { + return readDouble(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public Word readFinalWord(WordBase offset) { + return readWord(offset); + } + @Override + @Operation(opcode = Opcode.READ_FINAL) + public Object readFinalObject(WordBase offset) { + return readObject(offset); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeByte(WordBase offset, byte val) { + unsafe.putByte(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeChar(WordBase offset, char val) { + unsafe.putChar(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeShort(WordBase offset, Short val) { + unsafe.putShort(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeInt(WordBase offset, int val) { + unsafe.putInt(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeLong(WordBase offset, long val) { + unsafe.putLong(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeFloat(WordBase offset, float val) { + unsafe.putFloat(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeDouble(WordBase offset, double val) { + unsafe.putDouble(add((Word) offset).unbox(), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeWord(WordBase offset, WordBase val) { + unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox()); + } + @Override + @Operation(opcode = Opcode.WRITE) + public native void writeObject(WordBase offset, Object val); + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeByte(int offset, byte val) { + writeByte(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeChar(int offset, char val) { + writeChar(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeShort(int offset, short val) { + writeShort(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeInt(int offset, int val) { + writeInt(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeLong(int offset, long val) { + writeLong(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeFloat(int offset, float val) { + writeFloat(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeDouble(int offset, double val) { + writeDouble(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeWord(int offset, WordBase val) { + writeWord(signed(offset), val); + } + @Override + @Operation(opcode = Opcode.WRITE) + public void writeObject(int offset, Object val) { + writeObject(signed(offset), val); + } +} + +final class HostedWord extends Word { + private static final int SMALL_FROM = -1; + private static final int SMALL_TO = 100; + + private static final HostedWord[] smallCache = new HostedWord[SMALL_TO - SMALL_FROM + 1]; + private static final ConcurrentHashMap cache = new ConcurrentHashMap<>(); + + static { + for (int i = SMALL_FROM; i <= SMALL_TO; i++) { + smallCache[i - SMALL_FROM] = new HostedWord(i); + } + } + + private final long rawValue; + + private HostedWord(long rawValue) { + this.rawValue = rawValue; + } + + protected static Word box(long val) { + if (val >= SMALL_FROM && val <= SMALL_TO) { + return smallCache[(int) val - SMALL_FROM]; + } + Long key = val; + HostedWord result = cache.get(key); + if (result != null) { + return result; + } + HostedWord newValue = new HostedWord(val); + HostedWord oldValue = cache.putIfAbsent(key, newValue); + return oldValue == null ? newValue : oldValue; + } + + @Override + protected long unbox() { + return rawValue; + } +} diff -r 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.word.phases; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.Operation; + +/** + * Transforms all uses of the {@link Word} class into unsigned operations on {@code int} or {@code long} values, + * depending on the word kind of the underlying platform. + */ +public class WordTypeRewriterPhase extends Phase { + + private final ResolvedJavaType wordBaseType; + private final ResolvedJavaType wordImplType; + private final Kind wordKind; + + public WordTypeRewriterPhase(MetaAccessProvider metaAccess, Kind wordKind) { + this.wordKind = wordKind; + this.wordBaseType = metaAccess.lookupJavaType(WordBase.class); + this.wordImplType = metaAccess.lookupJavaType(Word.class); + } + + public ResolvedJavaType getWordBaseType() { + return wordBaseType; + } + + public ResolvedJavaType getWordImplType() { + return wordImplType; + } + + @Override + protected void run(StructuredGraph graph) { + for (Node n : GraphOrder.forwardGraph(graph)) { + if (n instanceof ValueNode) { + ValueNode valueNode = (ValueNode) n; + if (isWord(valueNode)) { + changeToWord(valueNode); + } + } + } + + // Remove casts between different word types (which are by now no longer have kind Object) + for (CheckCastNode checkCastNode : graph.getNodes().filter(CheckCastNode.class).snapshot()) { + if (!checkCastNode.isDeleted() && checkCastNode.kind() == wordKind) { + checkCastNode.replaceAtUsages(checkCastNode.object()); + graph.removeFixed(checkCastNode); + } + } + + // Remove unnecessary/redundant unsafe casts + for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) { + if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) { + graph.replaceFloating(unsafeCastNode, unsafeCastNode.object()); + } + } + + // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words + for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { + ValueNode x = objectEqualsNode.x(); + ValueNode y = objectEqualsNode.y(); + if (x.kind() == wordKind || y.kind() == wordKind) { + assert x.kind() == wordKind; + assert y.kind() == wordKind; + graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y))); + } + } + + // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words + for (LoadIndexedNode load : graph.getNodes().filter(LoadIndexedNode.class).snapshot()) { + if (isWord(load)) { + load.setStamp(StampFactory.forKind(wordKind)); + } + } + + for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { + ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); + if (!callTargetNode.isStatic() && (callTargetNode.receiver().kind() == wordKind || isWord(callTargetNode.receiver()))) { + targetMethod = getWordImplType().resolveMethod(targetMethod); + } + Operation operation = targetMethod.getAnnotation(Word.Operation.class); + if (operation != null) { + NodeInputList arguments = callTargetNode.arguments(); + Invoke invoke = (Invoke) callTargetNode.usages().first(); + assert invoke != null : callTargetNode.targetMethod(); + + switch (operation.opcode()) { + case NODE_CLASS: + assert arguments.size() == 2; + ValueNode left = arguments.get(0); + ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1)); + replace(invoke, nodeClassOp(graph, operation.node(), left, right)); + break; + + case COMPARISON: + assert arguments.size() == 2; + replace(invoke, comparisonOp(graph, operation.condition(), arguments.get(0), fromSigned(graph, arguments.get(1)))); + break; + + case NOT: + assert arguments.size() == 1; + replace(invoke, graph.unique(new XorNode(wordKind, arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); + break; + + case READ: + assert arguments.size() == 2; + replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.ANY_LOCATION)); + break; + + case READ_FINAL: + assert arguments.size() == 2; + replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.FINAL_LOCATION)); + break; + + case WRITE: + assert arguments.size() == 3; + replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, LocationNode.ANY_LOCATION)); + break; + + case ZERO: + assert arguments.size() == 0; + replace(invoke, ConstantNode.forIntegerKind(wordKind, 0L, graph)); + break; + + case FROM_UNSIGNED: + assert arguments.size() == 1; + replace(invoke, fromUnsigned(graph, arguments.get(0))); + break; + + case FROM_SIGNED: + assert arguments.size() == 1; + replace(invoke, fromSigned(graph, arguments.get(0))); + break; + + case TO_RAW_VALUE: + assert arguments.size() == 1; + replace(invoke, toUnsigned(graph, arguments.get(0), Kind.Long)); + break; + + case FROM_OBJECT: + assert arguments.size() == 1; + replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), StampFactory.forKind(wordKind)))); + break; + + case TO_OBJECT: + assert arguments.size() == 1; + replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.node().stamp()))); + break; + + default: + throw new GraalInternalError("Unknown opcode: %s", operation.opcode()); + } + } + } + } + + private ValueNode fromUnsigned(StructuredGraph graph, ValueNode value) { + return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); + } + + private ValueNode fromSigned(StructuredGraph graph, ValueNode value) { + return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.I2L); + } + + private static ValueNode toUnsigned(StructuredGraph graph, ValueNode value, Kind toKind) { + return convert(graph, value, toKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); + } + + private static ValueNode convert(StructuredGraph graph, ValueNode value, Kind toKind, ConvertNode.Op longToIntOp, ConvertNode.Op intToLongOp) { + assert longToIntOp.from == Kind.Long && longToIntOp.to == Kind.Int; + assert intToLongOp.from == Kind.Int && intToLongOp.to == Kind.Long; + if (value.kind() == toKind) { + return value; + } + + if (toKind == Kind.Int) { + assert value.kind() == Kind.Long; + return graph.unique(new ConvertNode(longToIntOp, value)); + } else { + assert toKind == Kind.Long; + assert value.kind().getStackKind() == Kind.Int; + return graph.unique(new ConvertNode(intToLongOp, value)); + } + } + + private ValueNode nodeClassOp(StructuredGraph graph, Class nodeClass, ValueNode left, ValueNode right) { + try { + Constructor< ? extends ValueNode> constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class); + return graph.add(constructor.newInstance(wordKind, left, right)); + } catch (Throwable ex) { + throw new GraalInternalError(ex).addContext(nodeClass.getName()); + } + } + + private ValueNode comparisonOp(StructuredGraph graph, Condition condition, ValueNode left, ValueNode right) { + assert left.kind() == wordKind && right.kind() == wordKind; + + // mirroring gets the condition into canonical form + boolean mirror = condition.canonicalMirror(); + + ValueNode a = mirror ? right : left; + ValueNode b = mirror ? left : right; + + + CompareNode comparison; + if (condition == Condition.EQ || condition == Condition.NE) { + comparison = new IntegerEqualsNode(a, b); + } else if (condition.isUnsigned()) { + comparison = new IntegerBelowThanNode(a, b); + } else { + comparison = new IntegerLessThanNode(a, b); + } + MaterializeNode materialize = MaterializeNode.create(graph.unique(comparison)); + + ValueNode op; + if (condition.canonicalNegate()) { + op = (ValueNode) materialize.negate(); + } else { + op = materialize; + } + return op; + } + + private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Object locationIdentity) { + IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, offset, graph, false); + ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp())); + graph.addBeforeFixed(invoke.node(), read); + // The read must not float outside its block otherwise it may float above an explicit zero check on its base address + read.dependencies().add(BeginNode.prevBegin(invoke.node())); + return read; + } + + private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Object locationIdentity) { + IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, value.kind(), 0, offset, graph, false); + WriteNode write = graph.add(new WriteNode(base, value, location)); + graph.addBeforeFixed(invoke.node(), write); + return write; + } + + private static void replace(Invoke invoke, ValueNode value) { + FixedNode next = invoke.next(); + invoke.setNext(null); + invoke.node().replaceAtPredecessor(next); + invoke.node().replaceAtUsages(value); + GraphUtil.killCFG(invoke.node()); + } + + public boolean isWord(ValueNode node) { + node.inferStamp(); + if (node.stamp() == StampFactory.forWord()) { + return true; + } + if (node instanceof LoadIndexedNode) { + return isWord(((LoadIndexedNode) node).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 57edf6b07d36 -r 2912b72d840a 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 Fri Jan 04 12:08:11 2013 -0800 @@ -0,0 +1,155 @@ +/* + * 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) { + 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)) { + 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 57edf6b07d36 -r 2912b72d840a mx/projects --- a/mx/projects Wed Jan 02 18:52:33 2013 +0100 +++ b/mx/projects Fri Jan 04 12:08:11 2013 -0800 @@ -137,10 +137,17 @@ project@com.oracle.graal.alloc@checkstyle=com.oracle.graal.graph project@com.oracle.graal.alloc@javaCompliance=1.7 +# graal.word +project@com.oracle.graal.word@subDir=graal +project@com.oracle.graal.word@sourceDirs=src +project@com.oracle.graal.word@dependencies=com.oracle.graal.nodes,com.oracle.graal.phases +project@com.oracle.graal.word@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.word@javaCompliance=1.7 + # graal.snippets project@com.oracle.graal.snippets@subDir=graal project@com.oracle.graal.snippets@sourceDirs=src -project@com.oracle.graal.snippets@dependencies=com.oracle.graal.compiler,com.oracle.graal.java +project@com.oracle.graal.snippets@dependencies=com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.word project@com.oracle.graal.snippets@checkstyle=com.oracle.graal.graph project@com.oracle.graal.snippets@javaCompliance=1.7 diff -r 57edf6b07d36 -r 2912b72d840a src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Wed Jan 02 18:52:33 2013 +0100 +++ b/src/share/vm/runtime/arguments.cpp Fri Jan 04 12:08:11 2013 -0800 @@ -2249,6 +2249,7 @@ "com.oracle.graal.hotspot", "com.oracle.graal.asm", "com.oracle.graal.alloc", + "com.oracle.graal.word", "com.oracle.graal.snippets", "com.oracle.graal.compiler", "com.oracle.graal.loop",