# HG changeset patch # User Roland Schatz # Date 1396445218 -7200 # Node ID b14cb2d9253db187811e38825f327e5ca45a7708 # Parent 96f8e6b6a81aef455a6e319a88bc21114eabebe5 Make compression and uncompression explicit in the high level graph. diff -r 96f8e6b6a81a -r b14cb2d9253d CHANGELOG.md --- a/CHANGELOG.md Wed Apr 02 14:43:52 2014 +0200 +++ b/CHANGELOG.md Wed Apr 02 15:26:58 2014 +0200 @@ -2,6 +2,7 @@ ## `tip` ### Graal +* Explicit support for oop compression/uncompression in high level graph. * LIRGenerator refactoring. * ... diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java --- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Wed Apr 02 15:26:58 2014 +0200 @@ -80,11 +80,11 @@ /** * Moves an Object into a register. - * + * * Because Object references become stale after Garbage collection (GC) the technique used here * is to load a JNI global reference to that Object into the register. These JNI global * references get updated by the GC whenever the GC moves an Object. - * + * * @param a the destination register * @param obj the Object being moved */ @@ -112,11 +112,11 @@ } - public final void emitMov(Value dst, Value src) { - if (isRegister(dst) && isConstant(src) && src.getKind().getStackKind() == Kind.Object) { + public final void emitMov(Kind kind, Value dst, Value src) { + if (isRegister(dst) && isConstant(src) && kind.getStackKind() == Kind.Object) { mov(asRegister(dst), (asConstant(src)).asObject()); } else { - String argtype = getArgType(dst).substring(1); + String argtype = getArgTypeFromKind(kind).substring(1); emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";"); } } @@ -133,7 +133,7 @@ /** * Emits a memory barrier instruction. - * + * * @param barriers the kind of barrier to emit */ public final void emitMembar(int barriers) { @@ -189,16 +189,16 @@ storeImmediateImpl("f64", Double.toString(src), addr); } - public final void emitSpillLoad(Value dest, Value src) { - emitString("ld_spill_" + getArgType(dest) + " " + HSAIL.mapRegister(dest) + ", " + mapStackSlot(src, getArgSize(dest)) + ";"); + public final void emitSpillLoad(Kind kind, Value dest, Value src) { + emitString("ld_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(dest) + ", " + mapStackSlot(src, getArgSizeFromKind(kind)) + ";"); } public final void emitStore(Value src, HSAILAddress addr) { emitString("st_global_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapAddress(addr) + ";"); } - public final void emitSpillStore(Value src, Value dest) { - int sizestored = getArgSize(src); + public final void emitSpillStore(Kind kind, Value src, Value dest) { + int sizestored = getArgSizeFromKind(kind); if (maxDataTypeSize < sizestored) { maxDataTypeSize = sizestored; } @@ -206,7 +206,7 @@ if (maxStackOffset < stackoffset) { maxStackOffset = stackoffset; } - emitString("st_spill_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSize(src)) + ";"); + emitString("st_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSizeFromKind(kind)) + ";"); } /** @@ -226,7 +226,11 @@ } public int getArgSize(Value src) { - switch (src.getKind()) { + return getArgSizeFromKind(src.getKind()); + } + + private static int getArgSizeFromKind(Kind kind) { + switch (kind) { case Int: case Float: return 32; @@ -277,7 +281,11 @@ } public static final String getArgTypeForceUnsigned(Value src) { - switch (src.getKind()) { + return getArgTypeForceUnsignedKind(src.getKind()); + } + + public static final String getArgTypeForceUnsignedKind(Kind kind) { + switch (kind) { case Int: return "u32"; case Long: @@ -296,7 +304,7 @@ /** * Emits a compare instruction. - * + * * @param src0 - the first source register * @param src1 - the second source register * @param condition - the compare condition i.e., eq, ne, lt, gt @@ -307,8 +315,9 @@ public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) { // Formulate the prefix of the instruction. // if unordered is true, it should be ignored unless the src type is f32 or f64 - String unorderedPrefix = (getArgType(src1).startsWith("f") && unordered ? "u" : ""); - String prefix = "cmp_" + condition + unorderedPrefix + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : getArgType(src1)); + String argType = getArgTypeFromKind(src1.getKind().getStackKind()); + String unorderedPrefix = (argType.startsWith("f") && unordered ? "u" : ""); + String prefix = "cmp_" + condition + unorderedPrefix + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : argType); // Generate a comment for debugging purposes String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) && (asConstant(src1).asObject() == null) ? " // null test " : ""); // Emit the instruction. @@ -329,7 +338,7 @@ /** * Emits a convert instruction that uses unsigned prefix, regardless of the type of dest and * src. - * + * * @param dest the destination operand * @param src the source operand */ @@ -372,7 +381,7 @@ /** * Emits an instruction. - * + * * @param mnemonic the instruction mnemonic * @param dest the destination operand * @param sources the source operands @@ -384,20 +393,25 @@ /** * Emits an unsigned instruction. - * + * * @param mnemonic the instruction mnemonic * @param dest the destination argument * @param sources the source arguments - * + * */ public final void emitForceUnsigned(String mnemonic, Value dest, Value... sources) { String prefix = getArgTypeForceUnsigned(dest); emitTextFormattedInstruction(mnemonic + "_" + prefix, dest, sources); } + public final void emitForceUnsignedKind(String mnemonic, Kind kind, Value dest, Value... sources) { + String prefix = getArgTypeForceUnsignedKind(kind); + emitTextFormattedInstruction(mnemonic + "_" + prefix, dest, sources); + } + /** * Emits an instruction for a bitwise logical operation. - * + * * @param mnemonic the instruction mnemonic * @param dest the destination * @param sources the source operands @@ -410,7 +424,7 @@ /** * Central helper routine that emits a text formatted HSAIL instruction via call to * AbstractAssembler.emitString. All the emit routines in the assembler end up calling this one. - * + * * @param instr the full instruction mnenomics including any prefixes * @param dest the destination operand * @param sources the source operand @@ -442,7 +456,7 @@ /** * Emits a conditional move instruction. - * + * * @param dest the destination operand storing result of the move * @param trueReg the register that should be copied to dest if the condition is true * @param falseReg the register that should be copied to dest if the condition is false @@ -459,7 +473,7 @@ * shift. The compressed value could represent either a normal oop or a klass ptr. If the * compressed value is 0, the uncompressed must also be 0. We only emit this if base and shift * are not both zero. - * + * * @param result the register containing the compressed value on input and the uncompressed ptr * on output * @param base the amount to be added to the compressed value @@ -471,7 +485,7 @@ assert (!isConstant(result)); if (base == 0) { // we don't have to test for null if shl is the only operation - emitForceUnsigned("shl", result, result, Constant.forInt(shift)); + emitForceUnsignedKind("shl", Kind.Long, result, result, Constant.forInt(shift)); } else if (shift == 0) { // only use add if result is not starting as null (test only if testForNull is true) emitWithOptionalTestForNull(testForNull, "add", result, result, Constant.forLong(base)); @@ -486,7 +500,7 @@ * and shift. The compressed value could represent either a normal oop or a klass ptr. If the * ptr is 0, the compressed value must also be 0. We only emit this if base and shift are not * both zero. - * + * * @param result the register containing the 64-bit pointer on input and the compressed value on * output * @param base the amount to be subtracted from the 64-bit pointer @@ -502,7 +516,7 @@ } if (shift != 0) { // note that the shr can still be done even if the result is null - emitForceUnsigned("shr", result, result, Constant.forInt(shift)); + emitForceUnsignedKind("shr", Kind.Long, result, result, Constant.forInt(shift)); } } @@ -510,7 +524,7 @@ * Emits code for the requested mnemonic on the result and sources. In addition, if testForNull * is true, surrounds the instruction with code that will guarantee that if the result starts as * 0, it will remain 0. - * + * * @param testForNull true if we want to add the code to check for and preserve null * @param mnemonic the instruction to be applied (without size prefix) * @param result the register which is both an input and the final output @@ -528,7 +542,7 @@ /** * Emits an atomic_cas_global instruction. - * + * * @param result result operand that gets the original contents of the memory location * @param address the memory location * @param cmpValue the value that will be compared against the memory location @@ -542,7 +556,7 @@ /** * Emits an atomic_add_global instruction. - * + * * @param result result operand that gets the original contents of the memory location * @param address the memory location * @param deltaValue the amount to add @@ -553,7 +567,7 @@ /** * Emits a comment. Useful for debugging purposes. - * + * * @param comment */ public void emitComment(String comment) { @@ -588,7 +602,7 @@ // emitString(String.format("maxwaveid_u32 %s;", HSAIL.mapRegister(dest))); int hardCodedMaxWaveId = 36; emitComment("// Hard-coded maxwaveid=" + hardCodedMaxWaveId + " until it works"); - emitMov(dest, Constant.forInt(hardCodedMaxWaveId)); + emitMov(Kind.Int, dest, Constant.forInt(hardCodedMaxWaveId)); } public void emitMultiplyByWavesize(Value dest) { diff -r 96f8e6b6a81a -r b14cb2d9253d 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 Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Apr 02 15:26:58 2014 +0200 @@ -147,9 +147,9 @@ if (src instanceof AMD64AddressValue) { return new LeaOp(dst, (AMD64AddressValue) src); } else if (isRegister(src) || isStackSlot(dst)) { - return new MoveFromRegOp(dst, src); + return new MoveFromRegOp(dst.getKind(), dst, src); } else { - return new MoveToRegOp(dst, src); + return new MoveToRegOp(dst.getKind(), dst, src); } } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Wed Apr 02 15:26:58 2014 +0200 @@ -60,17 +60,11 @@ */ public abstract class HSAILLIRGenerator extends LIRGenerator { - public static class HSAILSpillMoveFactory implements LIR.SpillMoveFactory { + public class HSAILSpillMoveFactory implements LIR.SpillMoveFactory { @Override public LIRInstruction createMove(AllocatableValue dst, Value src) { - if (src instanceof HSAILAddressValue) { - return new LeaOp(dst, (HSAILAddressValue) src); - } else if (isRegister(src) || isStackSlot(dst)) { - return new MoveFromRegOp(dst, src); - } else { - return new MoveToRegOp(dst, src); - } + return HSAILLIRGenerator.this.createMove(dst, src); } } @@ -104,13 +98,19 @@ return result; } + protected HSAILLIRInstruction createMove(AllocatableValue dst, Value src) { + if (src instanceof HSAILAddressValue) { + return new LeaOp(dst, (HSAILAddressValue) src); + } else if (isRegister(src) || isStackSlot(dst)) { + return new MoveFromRegOp(dst.getKind(), dst, src); + } else { + return new MoveToRegOp(dst.getKind(), dst, src); + } + } + @Override public void emitMove(AllocatableValue dst, Value src) { - if (isRegister(src) || isStackSlot(dst)) { - append(new MoveFromRegOp(dst, src)); - } else { - append(new MoveToRegOp(dst, src)); - } + append(createMove(dst, src)); } public void emitData(AllocatableValue dst, byte[] data) { diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Wed Apr 02 15:26:58 2014 +0200 @@ -232,26 +232,26 @@ } @Override - public Variable emitLoad(Kind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, Access access) { PTXAddressValue loadAddress = asAddress(address); Variable result = newVariable(kind); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { state = state((DeoptimizingNode) access); } - append(new LoadOp(kind, result, loadAddress, state)); + append(new LoadOp((Kind) kind, result, loadAddress, state)); return result; } @Override - public void emitStore(Kind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { PTXAddressValue storeAddress = asAddress(address); Variable input = load(inputVal); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { state = state((DeoptimizingNode) access); } - append(new StoreOp(kind, storeAddress, input, state)); + append(new StoreOp((Kind) kind, storeAddress, input, state)); } @Override diff -r 96f8e6b6a81a -r b14cb2d9253d 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 Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Apr 02 15:26:58 2014 +0200 @@ -582,10 +582,15 @@ } public PlatformKind getIntegerKind(int bits, boolean unsigned) { - if (bits > 32) { + if (bits <= 8) { + return Kind.Byte; + } else if (bits <= 16) { + return Kind.Short; + } else if (bits <= 32) { + return Kind.Int; + } else { + assert bits <= 64; return Kind.Long; - } else { - return Kind.Int; } } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Wed Apr 02 15:26:58 2014 +0200 @@ -495,7 +495,7 @@ } protected PlatformKind getPhiKind(PhiNode phi) { - return phi.getKind(); + return gen.getPlatformKind(phi.stamp()); } private Value operandForPhi(PhiNode phi) { diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Wed Apr 02 15:26:58 2014 +0200 @@ -48,6 +48,7 @@ import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp; import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; +import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; import com.oracle.graal.nodes.*; @@ -103,7 +104,7 @@ dst = newVariable(Kind.Long); } - placeholder.replace(getResult().getLIR(), new MoveFromRegOp(dst, rbp.asValue(Kind.Long))); + placeholder.replace(getResult().getLIR(), new MoveFromRegOp(Kind.Long, dst, rbp.asValue(Kind.Long))); return dst; } } @@ -323,7 +324,7 @@ /** * Returns whether or not the input access should be (de)compressed. */ - private boolean isCompressedOperation(Kind kind, Access access) { + private boolean isCompressedOperation(PlatformKind kind, Access access) { return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops)); } @@ -338,10 +339,26 @@ } } + private static Kind getMemoryKind(PlatformKind kind) { + if (kind == NarrowOopStamp.NarrowOop) { + return Kind.Int; + } else { + return (Kind) kind; + } + } + + private static PlatformKind toStackKind(PlatformKind kind) { + if (kind instanceof Kind) { + return ((Kind) kind).getStackKind(); + } else { + return kind; + } + } + @Override - public Variable emitLoad(Kind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, Access access) { AMD64AddressValue loadAddress = asAddressValue(address); - Variable result = newVariable(kind.getStackKind()); + Variable result = newVariable(toStackKind(kind)); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { state = state((DeoptimizingNode) access); @@ -355,21 +372,21 @@ */ if (isCompressedOperation(kind, access)) { if (kind == Kind.Object) { - append(new LoadCompressedPointer(kind, result, getProviders().getRegisters().getHeapBaseRegister().asValue(), loadAddress, state, config.getOopEncoding())); + append(new LoadCompressedPointer(Kind.Object, result, getProviders().getRegisters().getHeapBaseRegister().asValue(), loadAddress, state, config.getOopEncoding())); } else if (kind == Kind.Long) { Variable scratch = config.getKlassEncoding().base != 0 ? newVariable(Kind.Long) : null; - append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, config.getKlassEncoding())); + append(new LoadCompressedPointer(Kind.Long, result, scratch, loadAddress, state, config.getKlassEncoding())); } else { throw GraalInternalError.shouldNotReachHere("can't handle: " + access); } } else { - append(new LoadOp(kind, result, loadAddress, state)); + append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); } return result; } @Override - public void emitStore(Kind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { AMD64AddressValue storeAddress = asAddressValue(address); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { @@ -381,18 +398,18 @@ if (canStoreConstant(c, isCompressed)) { if (isCompressed) { if (c.getKind() == Kind.Object) { - append(new StoreCompressedConstantOp(kind, storeAddress, c, state)); + append(new StoreCompressedConstantOp(Kind.Object, storeAddress, c, state)); } else if (c.getKind() == Kind.Long) { // It's always a good idea to directly store compressed constants since they // have to be materialized as 64 bits encoded otherwise. Constant value = compress(c, config.getKlassEncoding()); - append(new StoreCompressedConstantOp(kind, storeAddress, value, state)); + append(new StoreCompressedConstantOp(Kind.Long, storeAddress, value, state)); } else { throw GraalInternalError.shouldNotReachHere("can't handle: " + access); } return; } else { - append(new StoreConstantOp(kind, storeAddress, c, state)); + append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); return; } } @@ -403,7 +420,7 @@ if (input.getKind() == Kind.Object) { Variable scratch = newVariable(Kind.Long); Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister(); - append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.getOopEncoding(), heapBaseReg)); + append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, config.getOopEncoding(), heapBaseReg)); } else { // the input oop is already compressed append(new StoreOp(input.getKind(), storeAddress, input, state)); @@ -411,12 +428,12 @@ } else if (kind == Kind.Long) { Variable scratch = newVariable(Kind.Long); Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister(); - append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, config.getKlassEncoding(), heapBaseReg)); + append(new StoreCompressedPointer(Kind.Long, storeAddress, input, scratch, state, config.getKlassEncoding(), heapBaseReg)); } else { - append(new StoreOp(kind, storeAddress, input, state)); + append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); } } else { - append(new StoreOp(kind, storeAddress, input, state)); + append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); } } @@ -434,4 +451,17 @@ return result; } + @Override + protected AMD64LIRInstruction createMove(AllocatableValue dst, Value src) { + if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) { + if (isRegister(src) || isStackSlot(dst)) { + return new MoveFromRegOp(Kind.Int, dst, src); + } else { + return new MoveToRegOp(Kind.Int, dst, src); + } + } else { + return super.createMove(dst, src); + } + } + } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Wed Apr 02 15:26:58 2014 +0200 @@ -92,8 +92,8 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - AMD64Move.move(crb, masm, result, input); if (result.getPlatformKind() == NarrowOopStamp.NarrowOop) { + AMD64Move.move(Kind.Long, crb, masm, result, input); encodePointer(masm, asRegister(result), asRegister(baseRegister), encoding); } else { throw GraalInternalError.unimplemented(); @@ -118,8 +118,8 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - AMD64Move.move(crb, masm, result, input); if (result.getKind() == Kind.Object) { + AMD64Move.move(Kind.Int, crb, masm, result, input); decodePointer(masm, asRegister(result), asRegister(baseRegister), encoding); } else { throw GraalInternalError.unimplemented(); diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Wed Apr 02 15:26:58 2014 +0200 @@ -61,6 +61,7 @@ import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; @@ -671,7 +672,7 @@ asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64"); // Set deopt occurred flag - asm.emitMov(scratch32, Constant.forInt(1)); + asm.emitMov(Kind.Int, scratch32, Constant.forInt(1)); asm.emitStoreRelease(scratch32, deoptInfoAddr); asm.emitComment("// Determine next deopt save slot"); @@ -904,7 +905,8 @@ int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long); long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number); LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph); - ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forKind(Kind.Byte))); + ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8, false))); + numSRegs = SignExtendNode.convert(numSRegs, StampFactory.forKind(Kind.Byte)); location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4); } else { throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber); diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java Wed Apr 02 15:26:58 2014 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hsail.*; public class HSAILHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider { @@ -44,6 +43,6 @@ @Override protected RegisterConfig createRegisterConfig() { - return new HSAILRegisterConfig(); + return new HSAILHotSpotRegisterConfig(); } } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Wed Apr 02 15:26:58 2014 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp; @@ -41,6 +42,8 @@ import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp; import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer; import com.oracle.graal.lir.hsail.HSAILMove.LoadOp; +import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; +import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer; import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp; import com.oracle.graal.lir.hsail.HSAILMove.StoreOp; @@ -51,7 +54,7 @@ /** * The HotSpot specific portion of the HSAIL LIR generator. */ -public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator { +public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator implements HotSpotLIRGenerator { final HotSpotVMConfig config; @@ -101,32 +104,42 @@ /** * Returns whether or not the input access should be (de)compressed. */ - private boolean isCompressedOperation(Kind kind, Access access) { + private boolean isCompressedOperation(PlatformKind kind, Access access) { return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops)); } + private static Kind getMemoryKind(PlatformKind kind) { + if (kind == NarrowOopStamp.NarrowOop) { + return Kind.Int; + } else { + return (Kind) kind; + } + } + @Override - public Variable emitLoad(Kind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, Access access) { HSAILAddressValue loadAddress = asAddressValue(address); - Variable result = newVariable(kind.getStackKind()); + Variable result = newVariable(kind); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { state = state((DeoptimizingNode) access); } if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) { Variable scratch = newVariable(Kind.Long); - append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); + append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) { Variable scratch = newVariable(Kind.Long); - append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); + append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); + } else if (kind == NarrowOopStamp.NarrowOop) { + append(new LoadOp(Kind.Int, result, loadAddress, state)); } else { - append(new LoadOp(kind, result, loadAddress, state)); + append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); } return result; } @Override - public void emitStore(Kind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { HSAILAddressValue storeAddress = asAddressValue(address); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { @@ -147,7 +160,7 @@ } return; } else { - append(new StoreConstantOp(kind, storeAddress, c, state)); + append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); return; } } @@ -155,12 +168,14 @@ Variable input = load(inputVal); if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) { Variable scratch = newVariable(Kind.Long); - append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); + append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) { Variable scratch = newVariable(Kind.Long); - append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); + append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); + } else if (kind == NarrowOopStamp.NarrowOop) { + append(new StoreOp(Kind.Int, storeAddress, input, state)); } else { - append(new StoreOp(kind, storeAddress, input, state)); + append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); } } @@ -215,6 +230,19 @@ } @Override + protected HSAILLIRInstruction createMove(AllocatableValue dst, Value src) { + if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) { + if (isRegister(src) || isStackSlot(dst)) { + return new MoveFromRegOp(Kind.Int, dst, src); + } else { + return new MoveToRegOp(Kind.Int, dst, src); + } + } else { + return super.createMove(dst, src); + } + } + + @Override protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { // this version of emitForeignCall not used for now } @@ -229,4 +257,28 @@ throw GraalInternalError.shouldNotReachHere(); } } + + public void emitTailcall(Value[] args, Value address) { + throw GraalInternalError.shouldNotReachHere("NYI"); + } + + public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { + throw GraalInternalError.shouldNotReachHere("NYI"); + } + + public StackSlot getLockSlot(int lockDepth) { + throw GraalInternalError.shouldNotReachHere("NYI"); + } + + public Value emitCompress(Value pointer, CompressEncoding encoding) { + Variable result = newVariable(NarrowOopStamp.NarrowOop); + append(new HSAILMove.CompressPointer(result, newVariable(pointer.getPlatformKind()), asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment)); + return result; + } + + public Value emitUncompress(Value pointer, CompressEncoding encoding) { + Variable result = newVariable(Kind.Object); + append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment)); + return result; + } } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java Wed Apr 02 15:26:58 2014 +0200 @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.hotspot.hsail; + +import static com.oracle.graal.hsail.HSAIL.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.hsail.*; + +/** + * This class defines a higher level interface for the register allocator to be able to access info + * about the {@link HSAIL} register set. + * + * Note: In HSAIL, the number of registers of each type is actually a variable number that must + * satisfy the equation: Total num of registers = No. of S registers + 2 * (No. of D registers) + 4 + * * (No. of Q registers) = 128 In other words we can have up to 128S or 64 D or 32Q or a blend. + * + * For now we haven't implemented support for a variable sized register file. Instead we've fixed + * the number of registers of each type so that they satisfy the above equation. See {@link HSAIL} + * for more details. + */ +public class HSAILHotSpotRegisterConfig implements RegisterConfig { + + private final Register[] allocatable = {s0, s1, s2, s3, s4, s5, s6, /* s7, */s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, + d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15}; + + private final Register[] regBitness32 = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}; + private final Register[] regBitness64 = {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15}; + private final RegisterAttributes[] attributesMap = RegisterAttributes.createMap(this, HSAIL.allRegisters); + + @Override + public Register getReturnRegister(Kind kind) { + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + case Object: + return s0; + case Float: + case Double: + return d0; + case Void: + case Illegal: + return null; + default: + throw new UnsupportedOperationException("no return register for type " + kind); + } + } + + @Override + public Register getFrameRegister() { + // TODO Auto-generated method stub + return null; + } + + @Override + public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { + return callingConvention(regBitness32, regBitness64, returnType, parameterTypes, type, target, stackOnly); + } + + private CallingConvention callingConvention(Register[] generalParameterRegisters, Register[] longParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, + TargetDescription target, boolean stackOnly) { + AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; + + int currentRegs32 = 0; + int currentRegs64 = 0; + int currentStackOffset = 0; + + for (int i = 0; i < parameterTypes.length; i++) { + final Kind kind = parameterTypes[i].getKind(); + + switch (kind) { + case Byte: + case Boolean: + case Short: + case Char: + case Int: + case Float: + + if (!stackOnly && currentRegs32 < generalParameterRegisters.length) { + Register register = generalParameterRegisters[currentRegs32++]; + locations[i] = register.asValue(kind); + } + break; + case Long: + case Object: + case Double: + if (!stackOnly && currentRegs64 < longParameterRegisters.length) { + Register register = longParameterRegisters[currentRegs64++]; + locations[i] = register.asValue(kind); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + if (locations[i] == null) { + locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); + currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); + } + } + + Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); + AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind); + return new CallingConvention(currentStackOffset, returnLocation, locations); + } + + @Override + public Register[] getCallingConventionRegisters(Type type, Kind kind) { + throw new GraalInternalError("getCallingConventinoRegisters unimplemented"); + } + + @Override + public Register[] getAllocatableRegisters() { + return allocatable.clone(); + } + + @Override + public Register[] getAllocatableRegisters(PlatformKind kind) { + Kind primitiveKind; + if (kind == NarrowOopStamp.NarrowOop) { + primitiveKind = Kind.Int; + } else { + primitiveKind = (Kind) kind; + } + + switch (primitiveKind) { + case Int: + case Short: + case Byte: + case Float: + return regBitness32.clone(); + case Long: + case Double: + case Object: + return regBitness64.clone(); + + default: + throw new GraalInternalError("unknown register allocation"); + } + } + + @Override + public Register[] getCallerSaveRegisters() { + // TODO Auto-generated method stub + return new Register[0]; + } + + @Override + public boolean areAllAllocatableRegistersCallerSaved() { + return false; + } + + @Override + public CalleeSaveLayout getCalleeSaveLayout() { + return null; + } + + @Override + public RegisterAttributes[] getAttributesMap() { + return attributesMap.clone(); + } + + @Override + public Register getRegisterForRole(int id) { + throw new UnsupportedOperationException(); + } + + public HSAILHotSpotRegisterConfig() { + + } +} diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Apr 02 15:26:58 2014 +0200 @@ -147,9 +147,9 @@ } @Override - public Variable emitLoad(Kind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, Access access) { SPARCAddressValue loadAddress = asAddressValue(address); - Variable result = newVariable(kind.getStackKind()); + Variable result = newVariable(kind); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { state = state((DeoptimizingNode) access); @@ -168,16 +168,16 @@ // config.logKlassAlignment)); throw GraalInternalError.unimplemented(); } else { - append(new LoadOp(kind, result, loadAddress, state)); + append(new LoadOp((Kind) kind, result, loadAddress, state)); } } else { - append(new LoadOp(kind, result, loadAddress, state)); + append(new LoadOp((Kind) kind, result, loadAddress, state)); } return result; } @Override - public void emitStore(Kind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { SPARCAddressValue storeAddress = asAddressValue(address); LIRFrameState state = null; if (access instanceof DeoptimizingNode) { @@ -187,11 +187,11 @@ Constant c = asConstant(inputVal); if (canStoreConstant(c, isCompressCandidate(access))) { if (inputVal.getKind() == Kind.Object) { - append(new StoreConstantOp(kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(access))); + append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(access))); } else if (inputVal.getKind() == Kind.Long) { - append(new StoreConstantOp(kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(access))); + append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(access))); } else { - append(new StoreConstantOp(kind, storeAddress, c, state, false)); + append(new StoreConstantOp((Kind) kind, storeAddress, c, state, false)); } return; } @@ -216,10 +216,10 @@ // config.logKlassAlignment)); throw GraalInternalError.unimplemented(); } else { - append(new StoreOp(kind, storeAddress, input, state)); + append(new StoreOp((Kind) kind, storeAddress, input, state)); } } else { - append(new StoreOp(kind, storeAddress, input, state)); + append(new StoreOp((Kind) kind, storeAddress, input, state)); } } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Wed Apr 02 15:26:58 2014 +0200 @@ -42,6 +42,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; @@ -88,7 +89,7 @@ instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); newObjectSnippets = new NewObjectSnippets.Templates(providers, target); monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); boxingSnippets = new BoxingSnippets.Templates(providers, target); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); @@ -117,6 +118,10 @@ lowerUnsafeLoadNode((UnsafeLoadNode) n, tool); } else if (n instanceof UnsafeStoreNode) { lowerUnsafeStoreNode((UnsafeStoreNode) n); + } else if (n instanceof JavaReadNode) { + lowerJavaReadNode((JavaReadNode) n); + } else if (n instanceof JavaWriteNode) { + lowerJavaWriteNode((JavaWriteNode) n); } else if (n instanceof LoadHubNode) { lowerLoadHubNode((LoadHubNode) n); } else if (n instanceof LoadMethodNode) { @@ -255,14 +260,64 @@ } } + private Stamp loadStamp(Stamp stamp, Kind kind) { + return loadStamp(stamp, kind, true); + } + + private Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) { + switch (kind) { + case Boolean: + case Byte: + return StampTool.narrowingConversion(stamp, 8); + + case Char: + case Short: + return StampTool.narrowingConversion(stamp, 16); + + case Object: + if (compressible && runtime.getConfig().useCompressedOops) { + return new NarrowOopStamp((ObjectStamp) stamp, runtime.getConfig().getOopEncoding()); + } + } + return stamp; + } + + private ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) { + return implicitLoadConvert(graph, kind, value, true); + } + + private ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { + switch (kind) { + case Byte: + case Short: + return graph.unique(new SignExtendNode(value, 32)); + + case Boolean: + case Char: + return graph.unique(new ZeroExtendNode(value, 32)); + + case Object: + if (compressible && runtime.getConfig().useCompressedOops) { + return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding()); + } + } + return value; + } + private void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { StructuredGraph graph = loadField.graph(); HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object(); assert loadField.getKind() != Kind.Illegal; BarrierType barrierType = getFieldLoadBarrierType(field); - ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.getKind() == Kind.Object))); - graph.replaceFixedWithFixed(loadField, memoryRead); + + Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind()); + ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadStamp, barrierType, false)); + ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead); + + loadField.replaceAtUsages(readValue); + graph.replaceFixed(loadField, memoryRead); + memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); if (loadField.isVolatile()) { @@ -273,12 +328,34 @@ } } + private ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) { + return implicitStoreConvert(graph, kind, value, true); + } + + private ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { + switch (kind) { + case Boolean: + case Byte: + return graph.unique(new NarrowNode(value, 8)); + case Char: + case Short: + return graph.unique(new NarrowNode(value, 16)); + case Object: + if (compressible && runtime.getConfig().useCompressedOops) { + return CompressionNode.compress(value, runtime.getConfig().getOopEncoding()); + } + } + return value; + } + private void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) { StructuredGraph graph = storeField.graph(); HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object(); BarrierType barrierType = getFieldStoreBarrierType(storeField); - WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object)); + + ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value()); + WriteNode memoryWrite = graph.add(new WriteNode(object, value, createFieldLocation(graph, field, false), barrierType, false)); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); @@ -307,9 +384,15 @@ StructuredGraph graph = loadIndexed.graph(); Kind elementKind = loadIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object)); + + Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind); + ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadStamp, BarrierType.NONE, false)); + ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); + memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); - graph.replaceFixedWithFixed(loadIndexed, memoryRead); + + loadIndexed.replaceAtUsages(readValue); + graph.replaceFixed(loadIndexed, memoryRead); } private void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) { @@ -317,6 +400,7 @@ GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); Kind elementKind = storeIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false); + ValueNode value = storeIndexed.value(); ValueNode array = storeIndexed.array(); @@ -348,7 +432,7 @@ } } BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); - WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object)); + WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), arrayLocation, barrierType, false)); memoryWrite.setGuard(boundsCheck); memoryWrite.setStateAfter(storeIndexed.stateAfter()); graph.replaceFixedWithFixed(storeIndexed, memoryWrite); @@ -361,24 +445,30 @@ } } + private ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) { + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + Kind readKind = load.accessKind(); + LocationNode location = createLocation(load); + Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false)); + ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible); + load.replaceAtUsages(readValue); + return memoryRead; + } + private void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { StructuredGraph graph = load.graph(); if (load.getGuardingCondition() != null) { - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); - LocationNode location = createLocation(load); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible)); - load.replaceAtUsages(memoryRead); + ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode); graph.replaceFixedWithFixed(load, valueAnchorNode); graph.addAfterFixed(valueAnchorNode, memoryRead); } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { assert load.getKind() != Kind.Illegal; - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); if (addReadBarrier(load)) { unsafeLoadSnippets.lower(load, tool); } else { - LocationNode location = createLocation(load); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible)); + ReadNode memoryRead = createUnsafeRead(graph, load, null); // An unsafe read must not float outside its block otherwise // it may float above an explicit null check on its object. memoryRead.setGuard(AbstractBeginNode.prevBegin(load)); @@ -387,16 +477,46 @@ } } - private static void lowerUnsafeStoreNode(UnsafeStoreNode store) { + private void lowerUnsafeStoreNode(UnsafeStoreNode store) { StructuredGraph graph = store.graph(); LocationNode location = createLocation(store); ValueNode object = store.object(); BarrierType barrierType = getUnsafeStoreBarrierType(store); - WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().getKind() == Kind.Object)); + boolean compressible = store.value().getKind() == Kind.Object; + Kind valueKind = store.accessKind(); + ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible); + WriteNode write = graph.add(new WriteNode(object, value, location, barrierType, false)); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); } + private void lowerJavaReadNode(JavaReadNode read) { + StructuredGraph graph = read.graph(); + + Kind valueKind = read.location().getValueKind(); + Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible()); + ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false)); + ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible()); + + memoryRead.setGuard(read.getGuard()); + + read.replaceAtUsages(readValue); + graph.replaceFixed(read, memoryRead); + } + + private void lowerJavaWriteNode(JavaWriteNode write) { + StructuredGraph graph = write.graph(); + + Kind valueKind = write.location().getValueKind(); + ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible()); + + WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization())); + memoryWrite.setStateAfter(write.stateAfter()); + graph.replaceFixedWithFixed(write, memoryWrite); + + memoryWrite.setGuard(write.getGuard()); + } + private void lowerLoadHubNode(LoadHubNode loadHub) { StructuredGraph graph = loadHub.graph(); if (graph.getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { @@ -464,7 +584,7 @@ location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(entryKind) + i * getScalingFactor(entryKind), graph); barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE; } - WriteNode write = new WriteNode(newObject, value, location, barrierType, entryKind == Kind.Object); + WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false); graph.addAfterFixed(newObject, graph.add(write)); } valuePos++; @@ -487,9 +607,11 @@ WriteNode write; if (virtual instanceof VirtualInstanceNode) { VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; - write = new WriteNode(newObject, allocValue, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true), BarrierType.IMPRECISE, true); + write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), + true), BarrierType.IMPRECISE, false); } else { - write = new WriteNode(newObject, allocValue, createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true), BarrierType.PRECISE, true); + write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), + true), BarrierType.PRECISE, false); } graph.addBeforeFixed(commit, graph.add(write)); } @@ -569,10 +691,14 @@ } private static LocationNode createLocation(UnsafeAccessNode access) { - ValueNode offset = access.offset(); + return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind()); + } + + private static LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) { + ValueNode offset = offsetNode; if (offset.isConstant()) { long offsetValue = offset.asConstant().asLong(); - return ConstantLocationNode.create(access.getLocationIdentity(), access.accessKind(), offsetValue, access.graph()); + return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph()); } long displacement = 0; @@ -602,7 +728,7 @@ } } - return IndexedLocationNode.create(access.getLocationIdentity(), access.accessKind(), displacement, offset, access.graph(), indexScaling); + return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling); } private static boolean addReadBarrier(UnsafeLoadNode load) { diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Wed Apr 02 15:26:58 2014 +0200 @@ -42,9 +42,9 @@ public static Object lowerUnsafeLoad(Object object, long offset) { Object fixedObject = FixedValueAnchorNode.getObject(object); if (object instanceof java.lang.ref.Reference && referentOffset() == offset) { - return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.PRECISE, true); + return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.PRECISE); } else { - return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.NONE, true); + return Word.fromObject(fixedObject).readObject((int) offset, BarrierType.NONE); } } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Wed Apr 02 15:26:58 2014 +0200 @@ -31,8 +31,10 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.hotspot.HotSpotVMConfig.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; @@ -136,7 +138,7 @@ // If the previous value has to be loaded (before the write), the load is issued. // The load is always issued except the cases of CAS and referent field. if (probability(LIKELY_PROBABILITY, doLoad)) { - previousOop = (Word) Word.fromObject(field.readObject(0, BarrierType.NONE, true)); + previousOop = (Word) Word.fromObject(field.readObject(0, BarrierType.NONE)); if (trace) { log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue()); verifyOop(previousOop.toObject()); @@ -252,7 +254,7 @@ for (int i = startIndex; i < length; i++) { long address = dstAddr + header + (i * scale); - Pointer oop = Word.fromObject(Word.unsigned(address).readObject(0, BarrierType.NONE, true)); + Pointer oop = Word.fromObject(Word.unsigned(address).readObject(0, BarrierType.NONE)); verifyOop(oop.toObject()); if (oop.notEqual(0)) { if (indexValue != 0) { @@ -330,8 +332,11 @@ private final SnippetInfo g1ArrayRangePreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier"); private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier"); - public Templates(Providers providers, TargetDescription target) { + private final CompressEncoding oopEncoding; + + public Templates(Providers providers, TargetDescription target, CompressEncoding oopEncoding) { super(providers, target); + this.oopEncoding = oopEncoding; } public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) { @@ -357,7 +362,14 @@ public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) { Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", writeBarrierPre.getObject()); - args.add("expectedObject", writeBarrierPre.getExpectedObject()); + + ValueNode expected = writeBarrierPre.getExpectedObject(); + if (expected != null && expected.stamp() instanceof NarrowOopStamp) { + assert oopEncoding != null; + expected = CompressionNode.uncompress(expected, oopEncoding); + } + args.add("expectedObject", expected); + args.add("location", writeBarrierPre.getLocation()); args.addConst("doLoad", writeBarrierPre.doLoad()); args.addConst("nullCheck", writeBarrierPre.getNullCheck()); @@ -369,7 +381,14 @@ public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", readBarrier.getObject()); - args.add("expectedObject", readBarrier.getExpectedObject()); + + ValueNode expected = readBarrier.getExpectedObject(); + if (expected != null && expected.stamp() instanceof NarrowOopStamp) { + assert oopEncoding != null; + expected = CompressionNode.uncompress(expected, oopEncoding); + } + + args.add("expectedObject", expected); args.add("location", readBarrier.getLocation()); args.addConst("doLoad", readBarrier.doLoad()); args.addConst("nullCheck", false); @@ -379,13 +398,21 @@ } public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers, LoweringTool tool) { + StructuredGraph graph = writeBarrierPost.graph(); if (writeBarrierPost.alwaysNull()) { - writeBarrierPost.graph().removeFixed(writeBarrierPost); + graph.removeFixed(writeBarrierPost); return; } - Arguments args = new Arguments(g1PostWriteBarrier, writeBarrierPost.graph().getGuardsStage(), tool.getLoweringStage()); + Arguments args = new Arguments(g1PostWriteBarrier, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", writeBarrierPost.getObject()); - args.add("value", writeBarrierPost.getValue()); + + ValueNode value = writeBarrierPost.getValue(); + if (value.stamp() instanceof NarrowOopStamp) { + assert oopEncoding != null; + value = CompressionNode.uncompress(value, oopEncoding); + } + args.add("value", value); + args.add("location", writeBarrierPost.getLocation()); args.addConst("usePrecise", writeBarrierPost.usePrecise()); args.addConst("threadRegister", registers.getThreadRegister()); diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Wed Apr 02 15:26:58 2014 +0200 @@ -176,20 +176,7 @@ } public static String mapRegister(Value arg) { - Register reg; - int encoding = 0; - String regPrefix = null; - Kind kind = arg.getKind(); - if (kind == Kind.Double || kind == Kind.Long) { - regPrefix = "$d"; - } else if (kind == Kind.Int || kind == Kind.Float) { - regPrefix = "$s"; - } else { - regPrefix = "$d"; - } - reg = asRegister(arg); - encoding = reg.encoding(); - return new String(regPrefix + encoding); + return "$" + asRegister(arg).name; } @Override diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java Wed Apr 02 14:43:52 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2009, 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.hsail; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CallingConvention.Type; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; - -import static com.oracle.graal.hsail.HSAIL.*; - -/** - * This class defines a higher level interface for the register allocator to be able to access info - * about the {@link HSAIL} register set. - * - * Note: In HSAIL, the number of registers of each type is actually a variable number that must - * satisfy the equation: Total num of registers = No. of S registers + 2 * (No. of D registers) + 4 - * * (No. of Q registers) = 128 In other words we can have up to 128S or 64 D or 32Q or a blend. - * - * For now we haven't implemented support for a variable sized register file. Instead we've fixed - * the number of registers of each type so that they satisfy the above equation. See {@link HSAIL} - * for more details. - */ -public class HSAILRegisterConfig implements RegisterConfig { - - private final Register[] allocatable = {s0, s1, s2, s3, s4, s5, s6, /* s7, */s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, - d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15}; - - private final Register[] regBitness32 = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}; - private final Register[] regBitness64 = {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15}; - private final RegisterAttributes[] attributesMap = RegisterAttributes.createMap(this, HSAIL.allRegisters); - - @Override - public Register getReturnRegister(Kind kind) { - switch (kind) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - case Long: - case Object: - return s0; - case Float: - case Double: - return d0; - case Void: - case Illegal: - return null; - default: - throw new UnsupportedOperationException("no return register for type " + kind); - } - } - - @Override - public Register getFrameRegister() { - // TODO Auto-generated method stub - return null; - } - - @Override - public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { - return callingConvention(regBitness32, regBitness64, returnType, parameterTypes, type, target, stackOnly); - } - - private CallingConvention callingConvention(Register[] generalParameterRegisters, Register[] longParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, - TargetDescription target, boolean stackOnly) { - AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; - - int currentRegs32 = 0; - int currentRegs64 = 0; - int currentStackOffset = 0; - - for (int i = 0; i < parameterTypes.length; i++) { - final Kind kind = parameterTypes[i].getKind(); - - switch (kind) { - case Byte: - case Boolean: - case Short: - case Char: - case Int: - case Float: - - if (!stackOnly && currentRegs32 < generalParameterRegisters.length) { - Register register = generalParameterRegisters[currentRegs32++]; - locations[i] = register.asValue(kind); - } - break; - case Long: - case Object: - case Double: - if (!stackOnly && currentRegs64 < longParameterRegisters.length) { - Register register = longParameterRegisters[currentRegs64++]; - locations[i] = register.asValue(kind); - } - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - - if (locations[i] == null) { - locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); - } - } - - Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); - AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind); - return new CallingConvention(currentStackOffset, returnLocation, locations); - } - - @Override - public Register[] getCallingConventionRegisters(Type type, Kind kind) { - throw new GraalInternalError("getCallingConventinoRegisters unimplemented"); - } - - @Override - public Register[] getAllocatableRegisters() { - return allocatable.clone(); - } - - @Override - public Register[] getAllocatableRegisters(PlatformKind kind) { - Kind k = (Kind) kind; - switch (k) { - case Int: - case Short: - case Byte: - case Float: - return regBitness32.clone(); - case Long: - case Double: - case Object: - return regBitness64.clone(); - - default: - throw new GraalInternalError("unknown register allocation"); - } - } - - @Override - public Register[] getCallerSaveRegisters() { - // TODO Auto-generated method stub - return new Register[0]; - } - - @Override - public boolean areAllAllocatableRegistersCallerSaved() { - return false; - } - - @Override - public CalleeSaveLayout getCalleeSaveLayout() { - return null; - } - - @Override - public RegisterAttributes[] getAttributesMap() { - return attributesMap.clone(); - } - - @Override - public Register getRegisterForRole(int id) { - throw new UnsupportedOperationException(); - } - - public HSAILRegisterConfig() { - - } -} diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Wed Apr 02 15:26:58 2014 +0200 @@ -42,23 +42,38 @@ public class AMD64Move { + private abstract static class AbstractMoveOp extends AMD64LIRInstruction implements MoveOp { + + private Kind moveKind; + + public AbstractMoveOp(Kind moveKind) { + if (moveKind == Kind.Illegal) { + // unknown operand size, conservatively move the whole register + this.moveKind = Kind.Long; + } else { + this.moveKind = moveKind; + } + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + move(moveKind, crb, masm, getResult(), getInput()); + } + } + @Opcode("MOVE") - public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp { + public static class MoveToRegOp extends AbstractMoveOp { @Def({REG, HINT}) protected AllocatableValue result; @Use({REG, STACK, CONST}) protected Value input; - public MoveToRegOp(AllocatableValue result, Value input) { + public MoveToRegOp(Kind moveKind, AllocatableValue result, Value input) { + super(moveKind); this.result = result; this.input = input; } @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - move(crb, masm, getResult(), getInput()); - } - - @Override public Value getInput() { return input; } @@ -70,22 +85,18 @@ } @Opcode("MOVE") - public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp { + public static class MoveFromRegOp extends AbstractMoveOp { @Def({REG, STACK}) protected AllocatableValue result; @Use({REG, CONST, HINT}) protected Value input; - public MoveFromRegOp(AllocatableValue result, Value input) { + public MoveFromRegOp(Kind moveKind, AllocatableValue result, Value input) { + super(moveKind); this.result = result; this.input = input; } @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - move(crb, masm, getResult(), getInput()); - } - - @Override public Value getInput() { return input; } @@ -404,17 +415,21 @@ } public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { + move(result.getKind(), crb, masm, result, input); + } + + public static void move(Kind moveKind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { if (isRegister(input)) { if (isRegister(result)) { - reg2reg(masm, result, input); + reg2reg(moveKind, masm, result, input); } else if (isStackSlot(result)) { - reg2stack(crb, masm, result, input); + reg2stack(moveKind, crb, masm, result, input); } else { throw GraalInternalError.shouldNotReachHere(); } } else if (isStackSlot(input)) { if (isRegister(result)) { - stack2reg(crb, masm, result, input); + stack2reg(moveKind, crb, masm, result, input); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -431,11 +446,11 @@ } } - private static void reg2reg(AMD64MacroAssembler masm, Value result, Value input) { + private static void reg2reg(Kind kind, AMD64MacroAssembler masm, Value result, Value input) { if (asRegister(input).equals(asRegister(result))) { return; } - switch (input.getKind()) { + switch (kind.getStackKind()) { case Int: masm.movl(asRegister(result), asRegister(input)); break; @@ -456,9 +471,9 @@ } } - private static void reg2stack(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { + private static void reg2stack(Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { AMD64Address dest = (AMD64Address) crb.asAddress(result); - switch (input.getKind()) { + switch (kind) { case Boolean: case Byte: masm.movb(dest, asRegister(input)); @@ -487,9 +502,9 @@ } } - private static void stack2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { + private static void stack2reg(Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { AMD64Address src = (AMD64Address) crb.asAddress(input); - switch (input.getKind()) { + switch (kind) { case Boolean: masm.movzbl(asRegister(result), src); break; diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Wed Apr 02 15:26:58 2014 +0200 @@ -47,7 +47,7 @@ /** * This class represents the LIR instruction that the HSAIL backend generates for a switch * construct in Java. - * + * * The HSAIL backend compiles switch statements into a series of cascading compare and branch * instructions because this is the currently the recommended way to generate optimally * performing HSAIL code. Thus the execution path for both the TABLESWITCH and LOOKUPSWITCH @@ -85,12 +85,12 @@ /** * Generates the code for this switch op. - * + * * The keys for switch statements in Java bytecode for of type int. However, Graal also * generates a TypeSwitchNode (for method dispatch) which triggers the invocation of these * routines with keys of type Long or Object. Currently we only support the * IntegerSwitchNode so we throw an exception if the key isn't of type int. - * + * * @param crb the CompilationResultBuilder * @param masm the HSAIL assembler */ @@ -191,9 +191,9 @@ AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int); AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int); AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int); - masm.emitMov(actionAndReasonReg, actionAndReason); - masm.emitMov(codeBufferOffsetReg, Constant.forInt(codeBufferPos)); - masm.emitMov(dregOopMapReg, Constant.forInt(dregOopMap)); + masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); + masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); + masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap)); masm.emitJumpToLabelName(masm.getDeoptLabelName()); // now record the debuginfo diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Wed Apr 02 15:26:58 2014 +0200 @@ -48,23 +48,33 @@ return maxStackOffset + maxDatatypeSize; } + private abstract static class AbstractMoveOp extends HSAILLIRInstruction implements MoveOp { + + private Kind moveKind; + + public AbstractMoveOp(Kind moveKind) { + this.moveKind = moveKind; + } + + @Override + public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + move(moveKind, crb, masm, getResult(), getInput()); + } + } + @Opcode("MOVE") - public static class SpillMoveOp extends HSAILLIRInstruction implements MoveOp { + public static class SpillMoveOp extends AbstractMoveOp { @Def({REG, STACK}) protected AllocatableValue result; @Use({REG, STACK, CONST}) protected Value input; - public SpillMoveOp(AllocatableValue result, Value input) { + public SpillMoveOp(Kind moveKind, AllocatableValue result, Value input) { + super(moveKind); this.result = result; this.input = input; } @Override - public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - move(crb, masm, getResult(), getInput()); - } - - @Override public Value getInput() { return input; } @@ -76,22 +86,18 @@ } @Opcode("MOVE") - public static class MoveToRegOp extends HSAILLIRInstruction implements MoveOp { + public static class MoveToRegOp extends AbstractMoveOp { @Def({REG, HINT}) protected AllocatableValue result; @Use({REG, STACK, CONST}) protected Value input; - public MoveToRegOp(AllocatableValue result, Value input) { + public MoveToRegOp(Kind moveKind, AllocatableValue result, Value input) { + super(moveKind); this.result = result; this.input = input; } @Override - public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - move(crb, masm, getResult(), getInput()); - } - - @Override public Value getInput() { return input; } @@ -103,22 +109,18 @@ } @Opcode("MOVE") - public static class MoveFromRegOp extends HSAILLIRInstruction implements MoveOp { + public static class MoveFromRegOp extends AbstractMoveOp { @Def({REG, STACK}) protected AllocatableValue result; @Use({REG, CONST, HINT}) protected Value input; - public MoveFromRegOp(AllocatableValue result, Value input) { + public MoveFromRegOp(Kind moveKind, AllocatableValue result, Value input) { + super(moveKind); this.result = result; this.input = input; } @Override - public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - move(crb, masm, getResult(), getInput()); - } - - @Override public Value getInput() { return input; } @@ -293,7 +295,7 @@ @Override public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - masm.emitMov(scratch, input); + masm.emitMov(kind, scratch, input); boolean testForNull = (kind == Kind.Object); encodePointer(masm, scratch, base, shift, alignment, testForNull); if (state != null) { @@ -304,6 +306,59 @@ } } + public static class CompressPointer extends HSAILLIRInstruction { + + private final long base; + private final int shift; + private final int alignment; + + @Def({REG}) protected AllocatableValue result; + @Temp({REG, HINT}) protected AllocatableValue scratch; + @Use({REG}) protected AllocatableValue input; + + public CompressPointer(AllocatableValue result, AllocatableValue scratch, AllocatableValue input, long base, int shift, int alignment) { + this.result = result; + this.scratch = scratch; + this.input = input; + this.base = base; + this.shift = shift; + this.alignment = alignment; + } + + @Override + public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + masm.emitMov(Kind.Long, scratch, input); + boolean testForNull = (input.getKind() == Kind.Object); + encodePointer(masm, scratch, base, shift, alignment, testForNull); + masm.emitConvert(result, scratch, "u32", "u64"); + } + } + + public static class UncompressPointer extends HSAILLIRInstruction { + + private final long base; + private final int shift; + private final int alignment; + + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue input; + + public UncompressPointer(AllocatableValue result, AllocatableValue input, long base, int shift, int alignment) { + this.result = result; + this.input = input; + this.base = base; + this.shift = shift; + this.alignment = alignment; + } + + @Override + public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + masm.emitConvert(result, input, "u64", "u32"); + boolean testForNull = (result.getKind() == Kind.Object); + decodePointer(masm, result, base, shift, alignment, testForNull); + } + } + private static void encodePointer(HSAILAssembler masm, Value scratch, long base, int shift, int alignment, boolean testForNull) { if (base == 0 && shift == 0) { return; @@ -408,9 +463,9 @@ // assume any encoded or decoded value could be null boolean testForNull = true; // set up scratch registers to be encoded versions - masm.emitMov(scratchCmpValue64, cmpValue); + masm.emitMov(Kind.Long, scratchCmpValue64, cmpValue); encodePointer(masm, scratchCmpValue64, base, shift, alignment, testForNull); - masm.emitMov(scratchNewValue64, newValue); + masm.emitMov(Kind.Long, scratchNewValue64, newValue); encodePointer(masm, scratchNewValue64, base, shift, alignment, testForNull); // get encoded versions into 32-bit registers masm.emitConvertForceUnsigned(scratchCmpValue32, scratchCmpValue64); @@ -441,24 +496,24 @@ } @SuppressWarnings("unused") - public static void move(CompilationResultBuilder crb, HSAILAssembler masm, Value result, Value input) { + public static void move(Kind kind, CompilationResultBuilder crb, HSAILAssembler masm, Value result, Value input) { if (isRegister(input)) { if (isRegister(result)) { - masm.emitMov(result, input); + masm.emitMov(kind, result, input); } else if (isStackSlot(result)) { - masm.emitSpillStore(input, result); + masm.emitSpillStore(kind, input, result); } else { throw GraalInternalError.shouldNotReachHere(); } } else if (isStackSlot(input)) { if (isRegister(result)) { - masm.emitSpillLoad(result, input); + masm.emitSpillLoad(kind, result, input); } else { throw GraalInternalError.shouldNotReachHere(); } } else if (isConstant(input)) { if (isRegister(result)) { - masm.emitMov(result, input); + masm.emitMov(kind, result, input); } else { throw GraalInternalError.shouldNotReachHere(); } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Wed Apr 02 15:26:58 2014 +0200 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.extended; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess { + + @Input private ValueNode value; + @Input(notDataflow = true) private FrameState stateAfter; + private final boolean initialization; + + @Input private Node lastLocationAccess; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } + + public ValueNode value() { + return value; + } + + /** + * Returns whether this write is the initialization of the written location. If it is true, the + * old value of the memory location is either uninitialized or zero. If it is false, the memory + * location is guaranteed to contain a valid value or zero. + */ + public boolean isInitialization() { + return initialization; + } + + public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible) { + this(object, value, location, barrierType, compressible, false); + } + + public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { + super(object, location, StampFactory.forVoid(), barrierType, compressible); + this.value = value; + this.initialization = initialization; + } + + @Override + public LocationIdentity getLocationIdentity() { + return location().getLocationIdentity(); + } + + public MemoryNode getLastLocationAccess() { + return (MemoryNode) lastLocationAccess; + } + + public void setLastLocationAccess(MemoryNode lla) { + Node newLla = ValueNodeUtil.asNode(lla); + updateUsages(lastLocationAccess, newLla); + lastLocationAccess = newLla; + } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } +} diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Wed Apr 02 15:26:58 2014 +0200 @@ -62,7 +62,8 @@ @Override public void generate(NodeLIRBuiderTool gen) { Value address = location().generateAddress(gen, gen.operand(object())); - gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this)); + PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp()); + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this)); } @Override diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Wed Apr 02 15:26:58 2014 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.extended; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Read a raw memory location according to Java field or array read semantics. It will perform read + * barriers, implicit conversions and optionally oop uncompression. + */ +public final class JavaReadNode extends FixedAccessNode implements Lowerable { + + public JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) { + super(object, location, StampFactory.forKind(location.getValueKind()), barrierType, compressible); + } + + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } +} diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaWriteNode.java Wed Apr 02 15:26:58 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.extended; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Write a raw memory location according to Java field or array write semantics. It will perform + * write barriers, implicit conversions and optionally oop compression. + */ +public final class JavaWriteNode extends AbstractWriteNode implements Lowerable, StateSplit, MemoryAccess, MemoryCheckpoint.Single { + + public JavaWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { + super(object, value, location, barrierType, compressible, initialization); + } + + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } +} diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Wed Apr 02 15:26:58 2014 +0200 @@ -55,7 +55,8 @@ @Override public void generate(NodeLIRBuiderTool gen) { Value address = location().generateAddress(gen, gen.operand(object())); - gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this)); + PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp()); + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this)); } @Override diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed Apr 02 15:26:58 2014 +0200 @@ -23,60 +23,23 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.LocationNode.Location; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; /** * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}. */ -public final class WriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, MemoryAccess, Simplifiable, Virtualizable { - - @Input private ValueNode value; - @Input(notDataflow = true) private FrameState stateAfter; - private final boolean initialization; - - @Input private Node lastLocationAccess; - - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - public boolean hasSideEffect() { - return true; - } - - public ValueNode value() { - return value; - } - - /** - * Returns whether this write is the initialization of the written location. If it is true, the - * old value of the memory location is either uninitialized or zero. If it is false, the memory - * location is guaranteed to contain a valid value or zero. - */ - public boolean isInitialization() { - return initialization; - } +public final class WriteNode extends AbstractWriteNode implements LIRLowerable, Simplifiable, Virtualizable { public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible) { - this(object, value, location, barrierType, compressible, false); + super(object, value, location, barrierType, compressible); } public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, boolean compressible, boolean initialization) { - super(object, location, StampFactory.forVoid(), barrierType, compressible); - this.value = value; - this.initialization = initialization; + super(object, value, location, barrierType, compressible, initialization); } @Override @@ -90,7 +53,8 @@ } else { v = gen.operand(value()); } - gen.getLIRGeneratorTool().emitStore(location().getValueKind(), address, v, this); + PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(value().stamp()); + gen.getLIRGeneratorTool().emitStore(writeKind, address, v, this); } @Override @@ -104,21 +68,6 @@ public static native void writeMemory(Object object, Object value, Location location, @ConstantNodeParameter BarrierType barrierType, @ConstantNodeParameter boolean compressible); @Override - public LocationIdentity getLocationIdentity() { - return location().getLocationIdentity(); - } - - public MemoryNode getLastLocationAccess() { - return (MemoryNode) lastLocationAccess; - } - - public void setLastLocationAccess(MemoryNode lla) { - Node newLla = ValueNodeUtil.asNode(lla); - updateUsages(lastLocationAccess, newLla); - lastLocationAccess = newLla; - } - - @Override public void virtualize(VirtualizerTool tool) { if (location() instanceof ConstantLocationNode) { ConstantLocationNode constantLocation = (ConstantLocationNode) location(); @@ -133,12 +82,4 @@ } } } - - public MemoryCheckpoint asMemoryCheckpoint() { - return this; - } - - public MemoryPhiNode asMemoryPhi() { - return null; - } } diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Apr 02 15:26:58 2014 +0200 @@ -37,9 +37,9 @@ ForeignCallsProvider getForeignCalls(); - Value emitLoad(Kind kind, Value address, Access access); + Value emitLoad(PlatformKind kind, Value address, Access access); - void emitStore(Kind kind, Value address, Value input, Access access); + void emitStore(PlatformKind kind, Value address, Value input, Access access); void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting); diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Wed Apr 02 15:26:58 2014 +0200 @@ -101,7 +101,7 @@ } private static void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { - ReadNode read = (ReadNode) graph.start().next(); + JavaReadNode read = (JavaReadNode) graph.start().next(); Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind()); Assert.assertEquals(graph.getParameter(0), read.object()); @@ -124,7 +124,7 @@ } private static void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { - WriteNode write = (WriteNode) graph.start().next(); + JavaWriteNode write = (JavaWriteNode) graph.start().next(); Assert.assertEquals(graph.getParameter(2), write.value()); Assert.assertEquals(graph.getParameter(0), write.object()); Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Wed Apr 02 15:26:58 2014 +0200 @@ -109,7 +109,7 @@ private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { WordCastNode cast = (WordCastNode) graph.start().next(); - ReadNode read = (ReadNode) cast.next(); + JavaReadNode read = (JavaReadNode) cast.next(); Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind()); Assert.assertEquals(cast, read.object()); @@ -137,7 +137,7 @@ private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { WordCastNode cast = (WordCastNode) graph.start().next(); - WriteNode write = (WriteNode) cast.next(); + JavaWriteNode write = (JavaWriteNode) cast.next(); Assert.assertEquals(graph.getParameter(2), write.value()); Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Wed Apr 02 15:26:58 2014 +0200 @@ -611,8 +611,9 @@ Object readObject(WordBase offset); /** - * Reads the memory at address {@code (this + offset)}. This particular access can allow - * decompression and read barriers (G1 referent field). + * Reads the memory at address {@code (this + offset)}. This access will decompress the oop if + * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent + * field). *

* 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 @@ -620,10 +621,9 @@ * * @param offset the signed offset for the memory access * @param barrierType the type of the read barrier to be added - * @param compressible whether or not the object is a decompression candidate * @return the result of the memory access */ - Object readObject(WordBase offset, BarrierType barrierType, boolean compressible); + Object readObject(WordBase offset, BarrierType barrierType); /** * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in @@ -707,15 +707,15 @@ Object readObject(int offset); /** - * Reads the memory at address {@code (this + offset)}. This particular access can be - * parameterized to allow decompression and read barriers (G1 referent field). + * Reads the memory at address {@code (this + offset)}. This access will decompress the oop if + * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent + * field). * * @param offset the signed offset for the memory access * @param barrierType the type of the read barrier to be added - * @param compressible whether or not the object is a decompression candidate * @return the result of the memory access */ - Object readObject(int offset, BarrierType barrierType, boolean compressible); + Object readObject(int offset, BarrierType barrierType); /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Wed Apr 02 15:26:58 2014 +0200 @@ -909,7 +909,7 @@ public native Object readObject(WordBase offset); @Operation(opcode = Opcode.READ_HEAP) - public native Object readObject(WordBase offset, BarrierType barrierType, boolean compressible); + public native Object readObject(WordBase offset, BarrierType barrierType); @Override @Operation(opcode = Opcode.READ) @@ -966,8 +966,8 @@ } @Operation(opcode = Opcode.READ_HEAP) - public Object readObject(int offset, BarrierType barrierType, boolean compressible) { - return readObject(signed(offset), barrierType, compressible); + public Object readObject(int offset, BarrierType barrierType) { + return readObject(signed(offset), barrierType); } @Override diff -r 96f8e6b6a81a -r b14cb2d9253d graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Apr 02 14:43:52 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Apr 02 15:26:58 2014 +0200 @@ -214,16 +214,15 @@ } else { location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2)); } - replace(invoke, readOp(graph, arguments.get(0), invoke, location, StampFactory.forKind(readKind.getStackKind()), BarrierType.NONE, false)); + replace(invoke, readOp(graph, arguments.get(0), invoke, location, BarrierType.NONE, false)); break; } case READ_HEAP: { - assert arguments.size() == 4; + assert arguments.size() == 3; Kind readKind = asKind(callTargetNode.returnType()); LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject(); - boolean compressible = arguments.get(3).asConstant().asInt() != 0; - replace(invoke, readOp(graph, arguments.get(0), invoke, location, StampFactory.forKind(readKind.getStackKind()), barrierType, compressible)); + replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, true)); break; } case WRITE: @@ -370,8 +369,8 @@ return IndexedLocationNode.create(locationIdentity, readKind, 0, fromSigned(graph, offset), graph, 1); } - protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Stamp stamp, BarrierType barrierType, boolean compressible) { - ReadNode read = graph.add(new ReadNode(base, location, stamp, barrierType, compressible)); + protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) { + JavaReadNode read = graph.add(new JavaReadNode(base, location, barrierType, compressible)); graph.addBeforeFixed(invoke.asNode(), read); /* * The read must not float outside its block otherwise it may float above an explicit zero @@ -383,7 +382,7 @@ protected ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) { assert op == Opcode.WRITE || op == Opcode.INITIALIZE; - WriteNode write = graph.add(new WriteNode(base, value, location, BarrierType.NONE, false, op == Opcode.INITIALIZE)); + JavaWriteNode write = graph.add(new JavaWriteNode(base, value, location, BarrierType.NONE, false, op == Opcode.INITIALIZE)); write.setStateAfter(invoke.stateAfter()); graph.addBeforeFixed(invoke.asNode(), write); return write; diff -r 96f8e6b6a81a -r b14cb2d9253d mx/projects --- a/mx/projects Wed Apr 02 14:43:52 2014 +0200 +++ b/mx/projects Wed Apr 02 15:26:58 2014 +0200 @@ -583,7 +583,7 @@ # graal.hsail project@com.oracle.graal.hsail@subDir=graal project@com.oracle.graal.hsail@sourceDirs=src -project@com.oracle.graal.hsail@dependencies=com.oracle.graal.graph +project@com.oracle.graal.hsail@dependencies=com.oracle.graal.api.code project@com.oracle.graal.hsail@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hsail@javaCompliance=1.8 @@ -618,7 +618,7 @@ # graal.asm.hsail project@com.oracle.graal.asm.hsail@subDir=graal project@com.oracle.graal.asm.hsail@sourceDirs=src -project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm +project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm,com.oracle.graal.graph project@com.oracle.graal.asm.hsail@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.hsail@javaCompliance=1.8