Mercurial > hg > graal-jvmci-8
changeset 22238:67b20ea8496c
Track base pointers of derived references in backend.
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64AddressNode.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64AddressNode.java Fri Jul 17 11:41:55 2015 +0200 @@ -66,7 +66,19 @@ AllocatableValue baseValue = base == null ? Value.ILLEGAL : tool.asAllocatable(gen.operand(base)); AllocatableValue indexValue = index == null ? Value.ILLEGAL : tool.asAllocatable(gen.operand(index)); - LIRKind kind = tool.getLIRKind(stamp()); + AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); + AllocatableValue indexReference; + if (scale.equals(Scale.Times1)) { + indexReference = LIRKind.derivedBaseFromValue(indexValue); + } else { + if (indexValue.getLIRKind().isValue()) { + indexReference = null; + } else { + indexReference = Value.ILLEGAL; + } + } + + LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference); gen.setResult(this, new AMD64AddressValue(kind, baseValue, indexValue, scale, displacement)); }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Jul 17 11:41:55 2015 +0200 @@ -662,29 +662,29 @@ return result; } - private Variable emitBinary(AMD64BinaryArithmetic op, OperandSize size, boolean commutative, Value a, Value b, boolean setFlags) { + private Variable emitBinary(LIRKind resultKind, AMD64BinaryArithmetic op, OperandSize size, boolean commutative, Value a, Value b, boolean setFlags) { if (isConstant(b)) { - return emitBinaryConst(op, size, commutative, asAllocatable(a), asConstant(b), setFlags); + return emitBinaryConst(resultKind, op, size, commutative, asAllocatable(a), asConstant(b), setFlags); } else if (commutative && isConstant(a)) { - return emitBinaryConst(op, size, commutative, asAllocatable(b), asConstant(a), setFlags); + return emitBinaryConst(resultKind, op, size, commutative, asAllocatable(b), asConstant(a), setFlags); } else { - return emitBinaryVar(op.getRMOpcode(size), size, commutative, asAllocatable(a), asAllocatable(b)); + return emitBinaryVar(resultKind, op.getRMOpcode(size), size, commutative, asAllocatable(a), asAllocatable(b)); } } - private Variable emitBinary(AMD64RMOp op, OperandSize size, boolean commutative, Value a, Value b) { + private Variable emitBinary(LIRKind resultKind, AMD64RMOp op, OperandSize size, boolean commutative, Value a, Value b) { if (isConstant(b)) { - return emitBinaryConst(op, size, asAllocatable(a), asConstant(b)); + return emitBinaryConst(resultKind, op, size, asAllocatable(a), asConstant(b)); } else if (commutative && isConstant(a)) { - return emitBinaryConst(op, size, asAllocatable(b), asConstant(a)); + return emitBinaryConst(resultKind, op, size, asAllocatable(b), asConstant(a)); } else { - return emitBinaryVar(op, size, commutative, asAllocatable(a), asAllocatable(b)); + return emitBinaryVar(resultKind, op, size, commutative, asAllocatable(a), asAllocatable(b)); } } - private Variable emitBinaryConst(AMD64BinaryArithmetic op, OperandSize size, boolean commutative, AllocatableValue a, JavaConstant b, boolean setFlags) { + private Variable emitBinaryConst(LIRKind resultKind, AMD64BinaryArithmetic op, OperandSize size, boolean commutative, AllocatableValue a, JavaConstant b, boolean setFlags) { if (NumUtil.isInt(b.asLong())) { - Variable result = newVariable(LIRKind.combine(a, b)); + Variable result = newVariable(resultKind); int constant = (int) b.asLong(); if (!setFlags) { @@ -698,7 +698,7 @@ append(new AMD64Binary.ConstOp(op, size, result, a, constant)); return result; } else { - return emitBinaryVar(op.getRMOpcode(size), size, commutative, a, asAllocatable(b)); + return emitBinaryVar(resultKind, op.getRMOpcode(size), size, commutative, a, asAllocatable(b)); } } @@ -721,14 +721,14 @@ return null; } - private Variable emitBinaryConst(AMD64RMOp op, OperandSize size, AllocatableValue a, JavaConstant b) { - Variable result = newVariable(LIRKind.combine(a, b)); + private Variable emitBinaryConst(LIRKind resultKind, AMD64RMOp op, OperandSize size, AllocatableValue a, JavaConstant b) { + Variable result = newVariable(resultKind); append(new AMD64Binary.DataOp(op, size, result, a, b)); return result; } - private Variable emitBinaryVar(AMD64RMOp op, OperandSize size, boolean commutative, AllocatableValue a, AllocatableValue b) { - Variable result = newVariable(LIRKind.combine(a, b)); + private Variable emitBinaryVar(LIRKind resultKind, AMD64RMOp op, OperandSize size, boolean commutative, AllocatableValue a, AllocatableValue b) { + Variable result = newVariable(resultKind); if (commutative) { append(new AMD64Binary.CommutativeOp(op, size, result, a, b)); } else { @@ -738,32 +738,32 @@ } @Override - public Variable emitAdd(Value a, Value b, boolean setFlags) { + public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) { switch (a.getKind().getStackKind()) { case Int: - return emitBinary(ADD, DWORD, true, a, b, setFlags); + return emitBinary(resultKind, ADD, DWORD, true, a, b, setFlags); case Long: - return emitBinary(ADD, QWORD, true, a, b, setFlags); + return emitBinary(resultKind, ADD, QWORD, true, a, b, setFlags); case Float: - return emitBinary(SSEOp.ADD, SS, true, a, b); + return emitBinary(resultKind, SSEOp.ADD, SS, true, a, b); case Double: - return emitBinary(SSEOp.ADD, SD, true, a, b); + return emitBinary(resultKind, SSEOp.ADD, SD, true, a, b); default: throw JVMCIError.shouldNotReachHere(); } } @Override - public Variable emitSub(Value a, Value b, boolean setFlags) { + public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) { switch (a.getKind().getStackKind()) { case Int: - return emitBinary(SUB, DWORD, false, a, b, setFlags); + return emitBinary(resultKind, SUB, DWORD, false, a, b, setFlags); case Long: - return emitBinary(SUB, QWORD, false, a, b, setFlags); + return emitBinary(resultKind, SUB, QWORD, false, a, b, setFlags); case Float: - return emitBinary(SSEOp.SUB, SS, false, a, b); + return emitBinary(resultKind, SSEOp.SUB, SS, false, a, b); case Double: - return emitBinary(SSEOp.SUB, SD, false, a, b); + return emitBinary(resultKind, SSEOp.SUB, SD, false, a, b); default: throw JVMCIError.shouldNotReachHere(); } @@ -783,7 +783,7 @@ append(new AMD64Binary.RMIOp(op, size, ret, a, imm)); return ret; } else { - return emitBinaryVar(AMD64RMOp.IMUL, size, true, a, asAllocatable(b)); + return emitBinaryVar(LIRKind.combine(a, b), AMD64RMOp.IMUL, size, true, a, asAllocatable(b)); } } @@ -793,7 +793,7 @@ } else if (isConstant(a)) { return emitIMULConst(size, asAllocatable(b), asConstant(a)); } else { - return emitBinaryVar(AMD64RMOp.IMUL, size, true, asAllocatable(a), asAllocatable(b)); + return emitBinaryVar(LIRKind.combine(a, b), AMD64RMOp.IMUL, size, true, asAllocatable(a), asAllocatable(b)); } } @@ -805,9 +805,9 @@ case Long: return emitIMUL(QWORD, a, b); case Float: - return emitBinary(SSEOp.MUL, SS, true, a, b); + return emitBinary(LIRKind.combine(a, b), SSEOp.MUL, SS, true, a, b); case Double: - return emitBinary(SSEOp.MUL, SD, true, a, b); + return emitBinary(LIRKind.combine(a, b), SSEOp.MUL, SD, true, a, b); default: throw JVMCIError.shouldNotReachHere(); } @@ -926,9 +926,9 @@ AMD64MulDivOp lop = emitIDIV(QWORD, a, b, state); return emitMove(lop.getQuotient()); case Float: - return emitBinary(SSEOp.DIV, SS, false, a, b); + return emitBinary(LIRKind.combine(a, b), SSEOp.DIV, SS, false, a, b); case Double: - return emitBinary(SSEOp.DIV, SD, false, a, b); + return emitBinary(LIRKind.combine(a, b), SSEOp.DIV, SD, false, a, b); default: throw JVMCIError.shouldNotReachHere(); } @@ -992,15 +992,16 @@ @Override public Variable emitAnd(Value a, Value b) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(AND, DWORD, true, a, b, false); + return emitBinary(resultKind, AND, DWORD, true, a, b, false); case Long: - return emitBinary(AND, QWORD, true, a, b, false); + return emitBinary(resultKind, AND, QWORD, true, a, b, false); case Float: - return emitBinary(SSEOp.AND, PS, true, a, b); + return emitBinary(resultKind, SSEOp.AND, PS, true, a, b); case Double: - return emitBinary(SSEOp.AND, PD, true, a, b); + return emitBinary(resultKind, SSEOp.AND, PD, true, a, b); default: throw JVMCIError.shouldNotReachHere(); } @@ -1008,15 +1009,16 @@ @Override public Variable emitOr(Value a, Value b) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(OR, DWORD, true, a, b, false); + return emitBinary(resultKind, OR, DWORD, true, a, b, false); case Long: - return emitBinary(OR, QWORD, true, a, b, false); + return emitBinary(resultKind, OR, QWORD, true, a, b, false); case Float: - return emitBinary(SSEOp.OR, PS, true, a, b); + return emitBinary(resultKind, SSEOp.OR, PS, true, a, b); case Double: - return emitBinary(SSEOp.OR, PD, true, a, b); + return emitBinary(resultKind, SSEOp.OR, PD, true, a, b); default: throw JVMCIError.shouldNotReachHere(); } @@ -1024,15 +1026,16 @@ @Override public Variable emitXor(Value a, Value b) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(XOR, DWORD, true, a, b, false); + return emitBinary(resultKind, XOR, DWORD, true, a, b, false); case Long: - return emitBinary(XOR, QWORD, true, a, b, false); + return emitBinary(resultKind, XOR, QWORD, true, a, b, false); case Float: - return emitBinary(SSEOp.XOR, PS, true, a, b); + return emitBinary(resultKind, SSEOp.XOR, PS, true, a, b); case Double: - return emitBinary(SSEOp.XOR, PD, true, a, b); + return emitBinary(resultKind, SSEOp.XOR, PD, true, a, b); default: throw JVMCIError.shouldNotReachHere(); }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCImmediateAddressNode.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCImmediateAddressNode.java Fri Jul 17 11:41:55 2015 +0200 @@ -57,6 +57,11 @@ AllocatableValue baseValue = tool.asAllocatable(gen.operand(base)); LIRKind kind = tool.getLIRKind(stamp()); + AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); + if (baseReference != null) { + kind = kind.makeDerivedReference(baseReference); + } + gen.setResult(this, new SPARCImmediateAddressValue(kind, baseValue, displacement)); }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCIndexedAddressNode.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCIndexedAddressNode.java Fri Jul 17 11:41:55 2015 +0200 @@ -55,7 +55,10 @@ AllocatableValue baseValue = tool.asAllocatable(gen.operand(base)); AllocatableValue indexValue = tool.asAllocatable(gen.operand(index)); - LIRKind kind = tool.getLIRKind(stamp()); + AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); + AllocatableValue indexReference = LIRKind.derivedBaseFromValue(indexValue); + + LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference); gen.setResult(this, new SPARCIndexedAddressValue(kind, baseValue, indexValue)); }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Fri Jul 17 11:41:55 2015 +0200 @@ -508,21 +508,21 @@ return result; } - private Variable emitBinary(SPARCArithmetic op, boolean commutative, Value a, Value b) { - return emitBinary(op, commutative, a, b, null); + private Variable emitBinary(LIRKind resultKind, SPARCArithmetic op, boolean commutative, Value a, Value b) { + return emitBinary(resultKind, op, commutative, a, b, null); } - private Variable emitBinary(SPARCArithmetic op, boolean commutative, Value a, Value b, LIRFrameState state) { + private Variable emitBinary(LIRKind resultKind, SPARCArithmetic op, boolean commutative, Value a, Value b, LIRFrameState state) { if (isConstant(b) && canInlineConstant(asConstant(b))) { - return emitBinaryConst(op, load(a), asConstant(b), state); + return emitBinaryConst(resultKind, op, load(a), asConstant(b), state); } else if (commutative && isConstant(a) && canInlineConstant(asConstant(a))) { - return emitBinaryConst(op, load(b), asConstant(a), state); + return emitBinaryConst(resultKind, op, load(b), asConstant(a), state); } else { - return emitBinaryVar(op, load(a), load(b), state); + return emitBinaryVar(resultKind, op, load(a), load(b), state); } } - private Variable emitBinaryConst(SPARCArithmetic op, AllocatableValue a, JavaConstant b, LIRFrameState state) { + private Variable emitBinaryConst(LIRKind resultKind, SPARCArithmetic op, AllocatableValue a, JavaConstant b, LIRFrameState state) { switch (op) { case IADD: case LADD: @@ -537,48 +537,48 @@ case IMUL: case LMUL: if (canInlineConstant(b)) { - Variable result = newVariable(LIRKind.combine(a, b)); + Variable result = newVariable(resultKind); append(new BinaryRegConst(op, result, a, b, state)); return result; } break; } - return emitBinaryVar(op, a, asAllocatable(b), state); + return emitBinaryVar(resultKind, op, a, asAllocatable(b), state); } - private Variable emitBinaryVar(SPARCArithmetic op, AllocatableValue a, AllocatableValue b, LIRFrameState state) { - Variable result = newVariable(LIRKind.combine(a, b)); + private Variable emitBinaryVar(LIRKind resultKind, SPARCArithmetic op, AllocatableValue a, AllocatableValue b, LIRFrameState state) { + Variable result = newVariable(resultKind); append(new BinaryRegReg(op, result, a, b, state)); return result; } @Override - public Variable emitAdd(Value a, Value b, boolean setFlags) { + public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) { switch (a.getKind().getStackKind()) { case Int: - return emitBinary(setFlags ? IADDCC : IADD, true, a, b); + return emitBinary(resultKind, setFlags ? IADDCC : IADD, true, a, b); case Long: - return emitBinary(setFlags ? LADDCC : LADD, true, a, b); + return emitBinary(resultKind, setFlags ? LADDCC : LADD, true, a, b); case Float: - return emitBinary(FADD, true, a, b); + return emitBinary(resultKind, FADD, true, a, b); case Double: - return emitBinary(DADD, true, a, b); + return emitBinary(resultKind, DADD, true, a, b); default: throw JVMCIError.shouldNotReachHere(); } } @Override - public Variable emitSub(Value a, Value b, boolean setFlags) { + public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) { switch (a.getKind().getStackKind()) { case Int: - return emitBinary(setFlags ? ISUBCC : ISUB, false, a, b); + return emitBinary(resultKind, setFlags ? ISUBCC : ISUB, false, a, b); case Long: - return emitBinary(setFlags ? LSUBCC : LSUB, false, a, b); + return emitBinary(resultKind, setFlags ? LSUBCC : LSUB, false, a, b); case Float: - return emitBinary(FSUB, false, a, b); + return emitBinary(resultKind, FSUB, false, a, b); case Double: - return emitBinary(DSUB, false, a, b); + return emitBinary(resultKind, DSUB, false, a, b); default: throw JVMCIError.shouldNotReachHere("missing: " + a.getKind()); } @@ -586,21 +586,22 @@ @Override public Variable emitMul(Value a, Value b, boolean setFlags) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(setFlags ? IMULCC : IMUL, true, a, b); + return emitBinary(resultKind, setFlags ? IMULCC : IMUL, true, a, b); case Long: if (setFlags) { Variable result = newVariable(LIRKind.combine(a, b)); append(new SPARCLMulccOp(result, load(a), load(b), this)); return result; } else { - return emitBinary(LMUL, true, a, b); + return emitBinary(resultKind, LMUL, true, a, b); } case Float: - return emitBinary(FMUL, true, a, b); + return emitBinary(resultKind, FMUL, true, a, b); case Double: - return emitBinary(DMUL, true, a, b); + return emitBinary(resultKind, DMUL, true, a, b); default: throw JVMCIError.shouldNotReachHere("missing: " + a.getKind()); } @@ -639,15 +640,16 @@ @Override public Value emitDiv(Value a, Value b, LIRFrameState state) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(IDIV, false, a, b, state); + return emitBinary(resultKind, IDIV, false, a, b, state); case Long: - return emitBinary(LDIV, false, a, b, state); + return emitBinary(resultKind, LDIV, false, a, b, state); case Float: - return emitBinary(FDIV, false, a, b, state); + return emitBinary(resultKind, FDIV, false, a, b, state); case Double: - return emitBinary(DDIV, false, a, b, state); + return emitBinary(resultKind, DDIV, false, a, b, state); default: throw JVMCIError.shouldNotReachHere("missing: " + a.getKind()); } @@ -729,16 +731,17 @@ default: throw JVMCIError.shouldNotReachHere(); } - return emitBinary(op, false, actualA, actualB, state); + return emitBinary(LIRKind.combine(actualA, actualB), op, false, actualA, actualB, state); } @Override public Variable emitAnd(Value a, Value b) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(IAND, true, a, b); + return emitBinary(resultKind, IAND, true, a, b); case Long: - return emitBinary(LAND, true, a, b); + return emitBinary(resultKind, LAND, true, a, b); default: throw JVMCIError.shouldNotReachHere("missing: " + a.getKind()); @@ -747,11 +750,12 @@ @Override public Variable emitOr(Value a, Value b) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(IOR, true, a, b); + return emitBinary(resultKind, IOR, true, a, b); case Long: - return emitBinary(LOR, true, a, b); + return emitBinary(resultKind, LOR, true, a, b); default: throw JVMCIError.shouldNotReachHere("missing: " + a.getKind()); } @@ -759,11 +763,12 @@ @Override public Variable emitXor(Value a, Value b) { + LIRKind resultKind = LIRKind.combine(a, b); switch (a.getKind().getStackKind()) { case Int: - return emitBinary(IXOR, true, a, b); + return emitBinary(resultKind, IXOR, true, a, b); case Long: - return emitBinary(LXOR, true, a, b); + return emitBinary(resultKind, LXOR, true, a, b); default: throw JVMCIError.shouldNotReachHere(); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMapBuilder.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMapBuilder.java Fri Jul 17 11:41:55 2015 +0200 @@ -87,10 +87,18 @@ if (kind.isUnknownReference()) { throw JVMCIError.unimplemented("derived references not yet implemented"); } else { + Location base = null; + if (kind.isDerivedReference()) { + Variable baseVariable = (Variable) kind.getDerivedReferenceBase(); + Value baseValue = state.getLiveBasePointers().get(baseVariable.index); + assert baseValue.getPlatformKind().getVectorLength() == 1 && baseValue.getLIRKind().isReference(0) && !baseValue.getLIRKind().isDerivedReference(); + base = toLocation(baseValue, 0); + } + for (int i = 0; i < kind.getPlatformKind().getVectorLength(); i++) { if (kind.isReference(i)) { objects[idx] = toLocation(obj, i * bytes); - derivedBase[idx] = null; + derivedBase[idx] = base; sizeInBytes[idx] = bytes; idx++; }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Fri Jul 17 11:41:55 2015 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.dfa.*; import com.oracle.graal.lir.framemap.*; /** @@ -44,6 +45,8 @@ public final LabelRef exceptionEdge; protected DebugInfo debugInfo; + private ValueSet liveBasePointers; + public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) { this.topFrame = topFrame; this.virtualObjects = virtualObjects; @@ -73,6 +76,9 @@ processValues(inst, obj.getValues(), proc); } } + if (liveBasePointers != null) { + liveBasePointers.forEach(inst, OperandMode.ALIVE, STATE_FLAGS, proc); + } } /** @@ -89,6 +95,9 @@ processValues(inst, obj.getValues(), proc); } } + if (liveBasePointers != null) { + liveBasePointers.forEach(inst, OperandMode.ALIVE, STATE_FLAGS, proc); + } } /** @@ -172,6 +181,14 @@ debugInfo = new DebugInfo(topFrame, virtualObjects); } + public ValueSet getLiveBasePointers() { + return liveBasePointers; + } + + public void setLiveBasePointers(ValueSet liveBasePointers) { + this.liveBasePointers = liveBasePointers; + } + @Override public String toString() { return debugInfo != null ? debugInfo.toString() : topFrame != null ? topFrame.toString() : "<empty>";
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarker.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarker.java Fri Jul 17 11:41:55 2015 +0200 @@ -120,7 +120,7 @@ op.visitEachTemp(defConsumer); op.visitEachOutput(defConsumer); - if (op.destroysCallerSavedRegisters()) { + if (frameMap != null && op.destroysCallerSavedRegisters()) { for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/MarkBasePointersPhase.java Fri Jul 17 11:41:55 2015 +0200 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 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.lir.dfa; + +import java.util.*; + +import jdk.internal.jvmci.code.*; +import jdk.internal.jvmci.meta.*; + +import com.oracle.graal.compiler.common.alloc.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; +import com.oracle.graal.lir.phases.*; + +/** + * Record all derived reference base pointers in a frame state. + */ +public final class MarkBasePointersPhase extends AllocationPhase { + + @Override + protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { + new Marker<B>(lirGenRes.getLIR(), null).build(); + } + + private static final class Marker<T extends AbstractBlockBase<T>> extends LocationMarker<T, Marker<T>.BasePointersSet> { + + private final class BasePointersSet extends LiveValueSet<Marker<T>.BasePointersSet> { + + private final ValueSet variables; + + public BasePointersSet() { + variables = new ValueSet(); + } + + private BasePointersSet(BasePointersSet s) { + variables = new ValueSet(s.variables); + } + + @Override + public Marker<T>.BasePointersSet copy() { + return new BasePointersSet(this); + } + + @Override + public void put(Value v) { + Variable base = (Variable) v.getLIRKind().getDerivedReferenceBase(); + variables.put(base.index, base); + } + + @Override + public void putAll(BasePointersSet v) { + variables.putAll(v.variables); + } + + @Override + public void remove(Value v) { + Variable base = (Variable) v.getLIRKind().getDerivedReferenceBase(); + variables.put(base.index, null); + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object obj) { + if (obj instanceof Marker.BasePointersSet) { + BasePointersSet other = (BasePointersSet) obj; + return variables.equals(other.variables); + } else { + return false; + } + } + + @Override + public int hashCode() { + throw new UnsupportedOperationException(); + } + } + + private Marker(LIR lir, FrameMap frameMap) { + super(lir, frameMap); + } + + @Override + protected Marker<T>.BasePointersSet newLiveValueSet() { + return new BasePointersSet(); + } + + @Override + protected boolean shouldProcessValue(Value operand) { + return operand.getLIRKind().isDerivedReference(); + } + + @Override + protected void processState(LIRInstruction op, LIRFrameState info, BasePointersSet values) { + info.setLiveBasePointers(new ValueSet(values.variables)); + } + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/ValueSet.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/ValueSet.java Fri Jul 17 11:41:55 2015 +0200 @@ -26,9 +26,12 @@ import jdk.internal.jvmci.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.framemap.*; -final class ValueSet { +public final class ValueSet { private Value[] values; ValueSet() { @@ -48,6 +51,10 @@ System.arraycopy(other.values, 0, values, 0, values.length); } + public Value get(int index) { + return values[index]; + } + void put(int index, Value value) { if (value != null && value.getLIRKind().isValue()) { return; @@ -123,6 +130,22 @@ } } + public void forEach(LIRInstruction inst, OperandMode mode, EnumSet<OperandFlag> flags, InstructionValueProcedure proc) { + for (int i = 0; i < values.length; i++) { + if (values[i] != null) { + values[i] = proc.doValue(inst, values[i], mode, flags); + } + } + } + + public void forEach(LIRInstruction inst, OperandMode mode, EnumSet<OperandFlag> flags, InstructionValueConsumer consumer) { + for (Value v : values) { + if (v != null) { + consumer.visitValue(inst, v, mode, flags); + } + } + } + @Override public int hashCode() { throw new UnsupportedOperationException();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Fri Jul 17 11:41:55 2015 +0200 @@ -420,4 +420,90 @@ public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) { throw JVMCIError.unimplemented(); } + + // automatic derived reference handling + + protected abstract Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags); + + public final Variable emitAdd(Value aVal, Value bVal, boolean setFlags) { + LIRKind resultKind; + Value a = aVal; + Value b = bVal; + + if (a.getKind().isNumericInteger()) { + LIRKind aKind = a.getLIRKind(); + LIRKind bKind = b.getLIRKind(); + assert a.getPlatformKind() == b.getPlatformKind(); + + if (aKind.isUnknownReference()) { + resultKind = aKind; + } else if (bKind.isUnknownReference()) { + resultKind = bKind; + } else if (aKind.isValue() && bKind.isValue()) { + resultKind = aKind; + } else if (aKind.isValue()) { + if (bKind.isDerivedReference()) { + resultKind = bKind; + } else { + AllocatableValue allocatable = asAllocatable(b); + resultKind = bKind.makeDerivedReference(allocatable); + b = allocatable; + } + } else if (bKind.isValue()) { + if (aKind.isDerivedReference()) { + resultKind = aKind; + } else { + AllocatableValue allocatable = asAllocatable(a); + resultKind = aKind.makeDerivedReference(allocatable); + a = allocatable; + } + } else { + resultKind = aKind.makeUnknownReference(); + } + } else { + resultKind = LIRKind.combine(a, b); + } + + return emitAdd(resultKind, a, b, setFlags); + } + + protected abstract Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags); + + public final Variable emitSub(Value aVal, Value bVal, boolean setFlags) { + LIRKind resultKind; + Value a = aVal; + Value b = bVal; + + if (a.getKind().isNumericInteger()) { + LIRKind aKind = a.getLIRKind(); + LIRKind bKind = b.getLIRKind(); + assert a.getPlatformKind() == b.getPlatformKind(); + + if (aKind.isUnknownReference()) { + resultKind = aKind; + } else if (bKind.isUnknownReference()) { + resultKind = bKind; + } + + if (aKind.isValue() && bKind.isValue()) { + resultKind = aKind; + } else if (bKind.isValue()) { + if (aKind.isDerivedReference()) { + resultKind = aKind; + } else { + AllocatableValue allocatable = asAllocatable(a); + resultKind = aKind.makeDerivedReference(allocatable); + a = allocatable; + } + } else if (aKind.isDerivedReference() && bKind.isDerivedReference() && aKind.getDerivedReferenceBase().equals(bKind.getDerivedReferenceBase())) { + resultKind = LIRKind.value(a.getPlatformKind()); + } else { + resultKind = aKind.makeUnknownReference(); + } + } else { + resultKind = LIRKind.combine(a, b); + } + + return emitSub(resultKind, a, b, setFlags); + } }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationStage.java Thu Jul 16 17:44:54 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationStage.java Fri Jul 17 11:41:55 2015 +0200 @@ -29,6 +29,7 @@ public class AllocationStage extends LIRPhaseSuite<AllocationContext> { public AllocationStage() { + appendPhase(new MarkBasePointersPhase()); appendPhase(new LinearScanPhase()); // build frame map
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DerivedOopTest.java Fri Jul 17 11:41:55 2015 +0200 @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 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.replacements.test; + +import java.util.*; + +import jdk.internal.jvmci.meta.*; + +import org.junit.*; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.nodes.*; + +/** + * Tests for derived oops in reference maps. + */ +public class DerivedOopTest extends GraalCompilerTest implements Snippets { + + private static class Pointers { + public long basePointer; + public long internalPointer; + + public long delta() { + return internalPointer - basePointer; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Pointers)) { + return false; + } + + Pointers other = (Pointers) obj; + return this.delta() == other.delta(); + } + + @Override + public int hashCode() { + return (int) delta(); + } + } + + private static class Result { + public Pointers beforeGC; + public Pointers afterGC; + + public Result() { + beforeGC = new Pointers(); + afterGC = new Pointers(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((afterGC == null) ? 0 : afterGC.hashCode()); + result = prime * result + ((beforeGC == null) ? 0 : beforeGC.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Result)) { + return false; + } + Result other = (Result) obj; + return Objects.equals(this.beforeGC, other.beforeGC) && Objects.equals(this.afterGC, other.afterGC); + } + } + + @Test + public void testFieldOffset() { + Result r = new Result(); + test("fieldOffsetSnippet", r, 16L); + + Assert.assertEquals(r.beforeGC.delta(), r.afterGC.delta()); + } + + static long getRawPointer(Object obj) { + // fake implementation for interpreter + return obj.hashCode(); + } + + static long getRawPointerIntrinsic(Object obj) { + return Word.fromObject(obj).rawValue(); + } + + public static Result fieldOffsetSnippet(Result obj, long offset) { + long internalPointer = getRawPointer(obj) + offset; + + // make sure the internal pointer is computed before the safepoint + GraalDirectives.blackhole(internalPointer); + + obj.beforeGC.basePointer = getRawPointer(obj); + obj.beforeGC.internalPointer = internalPointer; + + System.gc(); + + obj.afterGC.basePointer = getRawPointer(obj); + obj.afterGC.internalPointer = internalPointer; + + return obj; + } + + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins plugins = super.getDefaultGraphBuilderPlugins(); + Registration r = new Registration(plugins.getInvocationPlugins(), DerivedOopTest.class); + + ResolvedJavaMethod intrinsic = getResolvedJavaMethod("getRawPointerIntrinsic"); + r.register1("getRawPointer", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + b.intrinsify(targetMethod, intrinsic, new ValueNode[]{arg}); + return true; + } + }); + + return plugins; + } + + @Override + protected boolean checkHighTierGraph(StructuredGraph graph) { + assert graph.getNodes().filter(WordCastNode.class).count() > 0 : "DerivedOopTest.toLong should be intrinsified"; + return super.checkHighTierGraph(graph); + } +}
--- a/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/LIRKind.java Thu Jul 16 17:44:54 2015 +0200 +++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/LIRKind.java Fri Jul 17 11:41:55 2015 +0200 @@ -27,7 +27,7 @@ /** * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the * low level representation of the value, and a {@link #referenceMask} that describes the location - * of object references in the value. + * of object references in the value, and optionally a {@link #derivedReferenceBase}. * * <h2>Constructing {@link LIRKind} instances</h2> * @@ -65,11 +65,16 @@ private final PlatformKind platformKind; private final int referenceMask; + private AllocatableValue derivedReferenceBase; + private static final int UNKNOWN_REFERENCE = -1; - private LIRKind(PlatformKind platformKind, int referenceMask) { + private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) { this.platformKind = platformKind; this.referenceMask = referenceMask; + this.derivedReferenceBase = derivedReferenceBase; + + assert derivedReferenceBase == null || !derivedReferenceBase.getLIRKind().isDerivedReference() : "derived reference can't have another derived reference as base"; } /** @@ -79,7 +84,7 @@ */ public static LIRKind value(PlatformKind platformKind) { assert platformKind != Kind.Object : "Object should always be used as reference type"; - return new LIRKind(platformKind, 0); + return new LIRKind(platformKind, 0, null); } /** @@ -87,9 +92,16 @@ * reference. */ public static LIRKind reference(PlatformKind platformKind) { + return derivedReference(platformKind, null); + } + + /** + * Create a {@link LIRKind} of type {@code platformKind} that contains a derived reference. + */ + public static LIRKind derivedReference(PlatformKind platformKind, AllocatableValue base) { int length = platformKind.getVectorLength(); assert 0 < length && length < 32 : "vector of " + length + " references not supported"; - return new LIRKind(platformKind, (1 << length) - 1); + return new LIRKind(platformKind, (1 << length) - 1, base); } /** @@ -99,7 +111,25 @@ * used instead to automatically propagate this information. */ public static LIRKind unknownReference(PlatformKind platformKind) { - return new LIRKind(platformKind, UNKNOWN_REFERENCE); + return new LIRKind(platformKind, UNKNOWN_REFERENCE, null); + } + + /** + * Create a derived reference. + * + * @param base An {@link AllocatableValue} containing the base pointer of the derived reference. + */ + public LIRKind makeDerivedReference(AllocatableValue base) { + assert !isUnknownReference() && derivedReferenceBase == null; + if (Value.ILLEGAL.equals(base)) { + return makeUnknownReference(); + } else { + if (isValue()) { + return derivedReference(platformKind, base); + } else { + return new LIRKind(platformKind, referenceMask, base); + } + } } /** @@ -143,6 +173,42 @@ } /** + * Helper method to construct derived reference kinds. Returns the base value of a reference or + * derived reference. For values it returns {@code null}, and for unknown references it returns + * {@link Value#ILLEGAL}. + */ + public static AllocatableValue derivedBaseFromValue(AllocatableValue value) { + LIRKind kind = value.getLIRKind(); + if (kind.isValue()) { + return null; + } else if (kind.isDerivedReference()) { + return kind.getDerivedReferenceBase(); + } else if (kind.isUnknownReference()) { + return Value.ILLEGAL; + } else { + // kind is a reference + return value; + } + } + + /** + * Helper method to construct derived reference kinds. If one of {@code base1} or {@code base2} + * are set, it creates a derived reference using it as the base. If both are set, the result is + * an unknown reference. + */ + public static LIRKind combineDerived(LIRKind kind, AllocatableValue base1, AllocatableValue base2) { + if (base1 == null && base2 == null) { + return kind; + } else if (base1 == null) { + return kind.makeDerivedReference(base2); + } else if (base2 == null) { + return kind.makeDerivedReference(base1); + } else { + return kind.makeUnknownReference(); + } + } + + /** * @see #merge(Value...) */ public static LIRKind merge(Iterable<LIRKind> kinds) { @@ -211,13 +277,13 @@ return unknownReference(newPlatformKind); } else if (referenceMask == 0) { // value type - return new LIRKind(newPlatformKind, 0); + return LIRKind.value(newPlatformKind); } else { // reference type int newLength = Math.min(32, newPlatformKind.getVectorLength()); int newReferenceMask = referenceMask & (0xFFFFFFFF >>> (32 - newLength)); assert newReferenceMask != UNKNOWN_REFERENCE; - return new LIRKind(newPlatformKind, newReferenceMask); + return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase); } } @@ -230,7 +296,7 @@ return unknownReference(newPlatformKind); } else if (referenceMask == 0) { // value type - return new LIRKind(newPlatformKind, 0); + return LIRKind.value(newPlatformKind); } else { // reference type int oldLength = platformKind.getVectorLength(); @@ -244,7 +310,7 @@ } assert newReferenceMask != UNKNOWN_REFERENCE; - return new LIRKind(newPlatformKind, newReferenceMask); + return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase); } } @@ -253,7 +319,7 @@ * {@link LIRKind#unknownReference}. */ public LIRKind makeUnknownReference() { - return new LIRKind(platformKind, UNKNOWN_REFERENCE); + return new LIRKind(platformKind, UNKNOWN_REFERENCE, null); } /** @@ -264,6 +330,28 @@ } /** + * Check whether this value is a derived reference. + */ + public boolean isDerivedReference() { + return getDerivedReferenceBase() != null; + } + + /** + * Get the base value of a derived reference. + */ + public AllocatableValue getDerivedReferenceBase() { + return derivedReferenceBase; + } + + /** + * Change the base value of a derived reference. This must be called on derived references only. + */ + public void setDerivedReferenceBase(AllocatableValue derivedReferenceBase) { + assert isDerivedReference(); + this.derivedReferenceBase = derivedReferenceBase; + } + + /** * Check whether this value is derived from a reference in a non-linear way. If this returns * {@code true}, this value must not be live at safepoints. */