# HG changeset patch # User Christian Wimmer # Date 1341020028 25200 # Node ID 141b15521a3953a6b22e967e29d57000162fd31b # Parent e1d5c642d022dc29d88bbdffa41164582a3b1cb2 use annotated fields for operands of LIR instructions diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java --- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java Fri Jun 29 18:33:48 2012 -0700 @@ -49,6 +49,7 @@ ValueProcedure useProc = new ValueProcedure() { @Override public Value doValue(Value value) { return use(value); } }; ValueProcedure defProc = new ValueProcedure() { @Override public Value doValue(Value value) { return def(value); } }; ValueProcedure setReferenceProc = new ValueProcedure() { @Override public Value doValue(Value value) { return setReference(value); } }; + StateProcedure finishProc = new StateProcedure() { @Override public void doState(LIRFrameState state) { state.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap); } }; Debug.log("==== start assign registers ===="); for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) { @@ -70,17 +71,8 @@ op.forEachState(useProc); op.forEachAlive(useProc); - if (op.info != null) { - Debug.log(" registerRefMap: %s frameRefMap: %s", curRegisterRefMap, curFrameRefMap); - op.info.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap); - - if (op instanceof LIRXirInstruction) { - LIRXirInstruction xir = (LIRXirInstruction) op; - if (xir.infoAfter != null) { - xir.infoAfter.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap); - } - } - } + // Build the reference map for the GC. + op.forEachState(finishProc); // Process input operands after assigning the reference map, so that input operands that are used // for the last time at this instruction are not part of the reference map. diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java --- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java Fri Jun 29 18:33:48 2012 -0700 @@ -341,20 +341,20 @@ } private Value use(Value value, OperandMode mode, EnumSet flags) { - assert mode == OperandMode.Input || mode == OperandMode.Alive; + assert mode == OperandMode.USE || mode == OperandMode.ALIVE; if (isVariable(value)) { // State values are not recorded beforehand because it does not matter if they are spilled. Still, it is necessary to record them as used now. recordUse(value); Location curLoc = curLocations.get(asVariable(value)); - if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.Stack)) { + if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.STACK)) { Debug.log(" use %s %s: use current stack slot %s", mode, value, curLoc.location); return curLoc; } if (isRegister(curLoc.location)) { int regNum = asRegister(curLoc.location).number; assert curInRegisterState[regNum] == curLoc; - if (mode == OperandMode.Input || curOutRegisterState[regNum] == curLoc) { + if (mode == OperandMode.USE || curOutRegisterState[regNum] == curLoc) { Debug.log(" use %s %s: use current register %s", mode, value, curLoc.location); return curLoc; } @@ -373,10 +373,10 @@ return value; } - private static final EnumSet SPILL_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + private static final EnumSet SPILL_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK); private Value def(Value value, OperandMode mode, EnumSet flags) { - assert mode == OperandMode.Temp || mode == OperandMode.Output; + assert mode == OperandMode.TEMP || mode == OperandMode.DEF; if (isVariable(value)) { Debug.log(" def %s %s", mode, value); assert curLocations.get(asVariable(value)) == null; @@ -396,7 +396,7 @@ if (in != null && in != out && isLocation(in) && curLocations.get(asLocation(in).variable) == in) { Debug.log(" %s was evicted by %s, need to allocate new location", in, out); Location oldLoc = asLocation(in); - Location newLoc = allocateRegister(oldLoc.variable, OperandMode.Alive, SPILL_FLAGS); + Location newLoc = allocateRegister(oldLoc.variable, OperandMode.ALIVE, SPILL_FLAGS); assert oldLoc != newLoc; moveResolver.add(oldLoc, newLoc); } @@ -417,7 +417,7 @@ Value phiInput = phiInputs[i]; if (isVariable(phiDefinition)) { - Location hintResult = processRegisterHint(asVariable(phiDefinition), OperandMode.Output, phiInput); + Location hintResult = processRegisterHint(asVariable(phiDefinition), OperandMode.DEF, phiInput); if (hintResult != null) { phiDefinitions[i] = hintResult; } @@ -444,7 +444,7 @@ } private Location allocateRegister(final Variable variable, final OperandMode mode, EnumSet flags) { - if (flags.contains(OperandFlag.RegisterHint)) { + if (flags.contains(OperandFlag.HINT)) { Value hintResult = curOp.forEachRegisterHint(variable, mode, new ValueProcedure() { @Override public Value doValue(Value registerHint) { @@ -476,7 +476,7 @@ } } - if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) { + if (flags.contains(OperandFlag.STACK) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) { return selectSpillSlot(variable); } @@ -509,11 +509,11 @@ private boolean isFree(Register reg, OperandMode mode) { switch (mode) { - case Input: return curInRegisterState[reg.number] == null; - case Alive: return curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null; - case Temp: return curOutRegisterState[reg.number] == null; - case Output: return curOutRegisterState[reg.number] == null; - default: throw GraalInternalError.shouldNotReachHere(); + case USE: return curInRegisterState[reg.number] == null; + case ALIVE: return curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null; + case TEMP: return curOutRegisterState[reg.number] == null; + case DEF: return curOutRegisterState[reg.number] == null; + default: throw GraalInternalError.shouldNotReachHere(); } } @@ -552,7 +552,7 @@ assert isFree(reg, mode); Location loc = new Location(variable, reg.asValue(variable.kind)); - if (mode == OperandMode.Input || mode == OperandMode.Alive) { + if (mode == OperandMode.USE || mode == OperandMode.ALIVE) { curInRegisterState[reg.number] = loc; } curOutRegisterState[reg.number] = loc; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java --- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java Fri Jun 29 18:33:48 2012 -0700 @@ -290,8 +290,8 @@ } private Value load(Value value, OperandMode mode, EnumSet flags) { - assert mode == OperandMode.Input || mode == OperandMode.Alive; - if (flags.contains(OperandFlag.Stack)) { + assert mode == OperandMode.USE || mode == OperandMode.ALIVE; + if (flags.contains(OperandFlag.STACK)) { return useSlot(value); } if (isVariable(value)) { @@ -301,7 +301,7 @@ // This variable has already been processed before. Debug.log(" found location %s", regLoc); } else { - regLoc = allocateRegister(asVariable(value), curInRegisterState, mode == OperandMode.Alive ? curOutRegisterState : null, mode, flags); + regLoc = allocateRegister(asVariable(value), curInRegisterState, mode == OperandMode.ALIVE ? curOutRegisterState : null, mode, flags); Location stackLoc = curStackLocations.get(asVariable(value)); assert stackLoc != null; moveResolver.add(stackLoc, regLoc); @@ -314,15 +314,15 @@ } private Value spill(Value value, OperandMode mode, EnumSet flags) { - assert mode == OperandMode.Temp || mode == OperandMode.Output; - if (flags.contains(OperandFlag.Stack)) { + assert mode == OperandMode.TEMP || mode == OperandMode.DEF; + if (flags.contains(OperandFlag.STACK)) { return defSlot(value); } if (isVariable(value)) { Debug.log(" spill %s", value); assert curStackLocations.get(asVariable(value)) == null; Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState, mode, flags); - if (mode == OperandMode.Output) { + if (mode == OperandMode.DEF) { Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind)); curStackLocations.put(stackLoc); moveResolver.add(regLoc, stackLoc); @@ -360,7 +360,7 @@ } private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet flags) { - if (flags.contains(OperandFlag.RegisterHint)) { + if (flags.contains(OperandFlag.HINT)) { Value result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() { @Override public Value doValue(Value registerHint) { diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java --- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java Fri Jun 29 18:33:48 2012 -0700 @@ -167,7 +167,7 @@ if (op.hasCall()) { intervals.get("call").ranges.add(new Range(curOpId, curOpId + 1)); } - if (op.info != null) { + if (op.hasState()) { intervals.get("st").ranges.add(new Range(curOpId, curOpId + 1)); } } @@ -228,7 +228,7 @@ private String useKind(EnumSet flags) { if (curUseKind != null) { return curUseKind; - } else if (flags.contains(OperandFlag.Stack)) { + } else if (flags.contains(OperandFlag.STACK)) { return "S"; } else { return "M"; @@ -242,7 +242,7 @@ interval.uses.add(new UsePosition(curOpId, useKind(flags))); } if (interval.lastTo == 0) { - interval.lastTo = curOpId + (mode == OperandMode.Alive ? 1 : 0); + interval.lastTo = curOpId + (mode == OperandMode.ALIVE ? 1 : 0); } } return value; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java --- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java Fri Jun 29 18:33:48 2012 -0700 @@ -189,7 +189,7 @@ private Value use(Value value, EnumSet flags) { if (!isConstant(value) && value != Value.IllegalValue && !isIgnoredRegister(value)) { Value actual = curInputState.get(key(value)); - if (actual == null && flags.contains(OperandFlag.Uninitialized)) { + if (actual == null && flags.contains(OperandFlag.UNINITIALIZED)) { // OK, since uninitialized values are allowed explicitly. } else if (value != actual) { Debug.log("Error in register allocation: %s != %s for key %s", value, actual, key(value)); diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java Fri Jun 29 18:33:48 2012 -0700 @@ -106,7 +106,7 @@ // block must have exactly one successor - return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null; + return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState(); } private void deleteEmptyBlocks(List code) { @@ -159,7 +159,7 @@ if (lastOp instanceof StandardOp.JumpOp) { StandardOp.JumpOp lastJump = (StandardOp.JumpOp) lastOp; - if (lastOp.info == null) { + if (!lastOp.hasState()) { if (lastJump.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel()) { // delete last branch instruction Util.truncate(instructions, instructions.size() - 1); @@ -169,7 +169,7 @@ if (prevOp instanceof StandardOp.BranchOp) { StandardOp.BranchOp prevBranch = (StandardOp.BranchOp) prevOp; - if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && prevOp.info == null) { + if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && !prevOp.hasState()) { // eliminate a conditional branch to the immediate successor prevBranch.negate(lastJump.destination()); Util.truncate(instructions, instructions.size() - 1); diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java Fri Jun 29 18:33:48 2012 -0700 @@ -79,8 +79,7 @@ /** * Determines if two operations are both {@linkplain MoveOp moves} - * that have the same {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination} - * operands and they have the same {@linkplain LIRInstruction#info debug info}. + * that have the same {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination} operands. * * @param op1 the first instruction to compare * @param op2 the second instruction to compare @@ -138,7 +137,7 @@ assert pred.suxAt(0) == block : "invalid control flow"; assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; - if (predInstructions.get(predInstructions.size() - 1).info != null) { + if (predInstructions.get(predInstructions.size() - 1).hasState()) { // can not optimize instructions that have debug info return; } @@ -195,13 +194,13 @@ assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; - if (instructions.get(instructions.size() - 1).info != null) { + if (instructions.get(instructions.size() - 1).hasState()) { // cannot optimize instructions when debug info is needed return; } LIRInstruction branch = instructions.get(instructions.size() - 2); - if (!(branch instanceof StandardOp.BranchOp) || branch.info != null) { + if (!(branch instanceof StandardOp.BranchOp) || branch.hasState()) { // not a valid case for optimization // currently, only blocks that end with two branches (conditional branch followed // by unconditional branch) are optimized diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Fri Jun 29 18:33:48 2012 -0700 @@ -759,7 +759,7 @@ int len = splitChildren.size(); // in outputMode, the end of the interval (opId == cur.to()) is not valid - int toOffset = (mode == LIRInstruction.OperandMode.Output ? 0 : 1); + int toOffset = (mode == LIRInstruction.OperandMode.DEF ? 0 : 1); int i; for (i = 0; i < len; i++) { @@ -905,7 +905,7 @@ } void addUsePos(int pos, RegisterPriority registerPriority) { - assert covers(pos, LIRInstruction.OperandMode.Input) : "use position not covered by live range"; + assert covers(pos, LIRInstruction.OperandMode.USE) : "use position not covered by live range"; // do not add use positions for precolored intervals because they are never used if (registerPriority != RegisterPriority.None && isVariable(operand)) { @@ -1063,7 +1063,7 @@ if (cur != Range.EndMarker) { assert cur.to != cur.next.from : "ranges not separated"; - if (mode == LIRInstruction.OperandMode.Output) { + if (mode == LIRInstruction.OperandMode.DEF) { return cur.from <= opId && opId < cur.to; } else { return cur.from <= opId && opId <= cur.to; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Jun 29 18:33:48 2012 -0700 @@ -22,11 +22,12 @@ */ package com.oracle.graal.compiler.alloc; -import static com.oracle.graal.alloc.util.LocationUtil.*; import static com.oracle.graal.api.code.CodeUtil.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRValueUtil.*; + import java.util.*; -import com.oracle.max.criutils.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; @@ -38,9 +39,13 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.StateProcedure; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; +import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.cfg.*; +import com.oracle.max.criutils.*; /** * An implementation of the linear scan register allocator algorithm described @@ -867,16 +872,13 @@ TTY.println(" used in block B%d", block.getId()); for (LIRInstruction ins : block.lir) { TTY.println(ins.id() + ": " + ins.toString()); - LIRDebugInfo info = ins.info; - if (info != null) { - info.forEachState(new ValueProcedure() { - @Override - public Value doValue(Value liveStateOperand) { - TTY.println(" operand=" + liveStateOperand); - return liveStateOperand; - } - }); - } + ins.forEachState(new ValueProcedure() { + @Override + public Value doValue(Value liveStateOperand) { + TTY.println(" operand=" + liveStateOperand); + return liveStateOperand; + } + }); } } if (blockData.get(block).liveKill.get(operandNum)) { @@ -1032,7 +1034,7 @@ * Determines the priority which with an instruction's input operand will be allocated a register. */ static RegisterPriority registerPriorityOfInputOperand(EnumSet flags) { - if (flags.contains(OperandFlag.Stack)) { + if (flags.contains(OperandFlag.STACK)) { return RegisterPriority.ShouldHaveRegister; } // all other operands require a register @@ -1068,7 +1070,7 @@ } void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet flags) { - if (flags.contains(OperandFlag.RegisterHint) && isVariableOrRegister(targetValue)) { + if (flags.contains(OperandFlag.HINT) && isVariableOrRegister(targetValue)) { op.forEachRegisterHint(targetValue, mode, new ValueProcedure() { @Override @@ -1401,21 +1403,21 @@ assert isVariable(operand) : "register number out of bounds"; assert intervalFor(operand) != null : "no interval found"; - return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.Output); + return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.DEF); } Interval intervalAtBlockEnd(Block block, Value operand) { assert isVariable(operand) : "register number out of bounds"; assert intervalFor(operand) != null : "no interval found"; - return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.Output); + return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.DEF); } Interval intervalAtOpId(Value operand, int opId) { assert isVariable(operand) : "register number out of bounds"; assert intervalFor(operand) != null : "no interval found"; - return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.Input); + return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.USE); } void resolveCollectMappings(Block fromBlock, Block toBlock, MoveResolver moveResolver) { @@ -1697,20 +1699,7 @@ } - private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) { - assert iw != null : "interval walker needed for debug information"; - computeDebugInfo(iw, op, op.info); - - if (op instanceof LIRXirInstruction) { - LIRXirInstruction xir = (LIRXirInstruction) op; - if (xir.infoAfter != null) { - computeDebugInfo(iw, op, xir.infoAfter); - } - } - } - - - private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRDebugInfo info) { + private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) { BitSet registerRefMap = op.hasCall() ? null : frameMap.initRegisterRefMap(); BitSet frameRefMap = frameMap.initFrameRefMap(); computeOopMap(iw, op, registerRefMap, frameRefMap); @@ -1719,7 +1708,7 @@ @Override public Value doValue(Value operand) { int tempOpId = op.id(); - OperandMode mode = OperandMode.Input; + OperandMode mode = OperandMode.USE; Block block = blockForId(tempOpId); if (block.numberOfSux() == 1 && tempOpId == block.getLastLirInstructionId()) { // generating debug information for the last instruction of a block. @@ -1731,7 +1720,7 @@ if (instr instanceof StandardOp.JumpOp) { if (blockData.get(block).liveOut.get(operandNumber(operand))) { tempOpId = block.suxAt(0).getFirstLirInstructionId(); - mode = OperandMode.Output; + mode = OperandMode.DEF; } } } @@ -1748,7 +1737,7 @@ info.finish(registerRefMap, frameRefMap, frameMap); } - private void assignLocations(List instructions, IntervalWalker iw) { + private void assignLocations(List instructions, final IntervalWalker iw) { int numInst = instructions.size(); boolean hasDead = false; @@ -1774,10 +1763,13 @@ op.forEachTemp(assignProc); op.forEachOutput(assignProc); - if (op.info != null) { - // compute reference map and debug information - computeDebugInfo(iw, op); - } + // compute reference map and debug information + op.forEachState(new StateProcedure() { + @Override + protected void doState(LIRFrameState state) { + computeDebugInfo(iw, op, state); + } + }); // remove useless moves if (op instanceof MoveOp) { @@ -2049,7 +2041,7 @@ for (int j = 0; j < instructions.size(); j++) { LIRInstruction op = instructions.get(j); - if (op.info != null) { + if (op.hasState()) { iw.walkBefore(op.id()); boolean checkLive = true; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Fri Jun 29 18:33:48 2012 -0700 @@ -867,8 +867,8 @@ return; } - Interval beginHint = registerHint.getSplitChildAtOpId(beginPos, LIRInstruction.OperandMode.Input, allocator); - Interval endHint = registerHint.getSplitChildAtOpId(endPos, LIRInstruction.OperandMode.Output, allocator); + Interval beginHint = registerHint.getSplitChildAtOpId(beginPos, LIRInstruction.OperandMode.USE, allocator); + Interval endHint = registerHint.getSplitChildAtOpId(endPos, LIRInstruction.OperandMode.DEF, allocator); if (beginHint == endHint || beginHint.to() != beginPos || endHint.from() != endPos) { // registerHint must be split : otherwise the re-writing of use positions does not work return; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Jun 29 18:33:48 2012 -0700 @@ -44,7 +44,7 @@ private HashMap virtualObjects = new HashMap<>(); - public LIRDebugInfo build(FrameState topState, LockScope locks, List pointerSlots, LabelRef exceptionEdge, long leafGraphId) { + public LIRFrameState build(FrameState topState, LockScope locks, List pointerSlots, LabelRef exceptionEdge, long leafGraphId) { assert virtualObjects.size() == 0; BytecodeFrame frame = computeFrameForState(topState, locks, leafGraphId); @@ -94,7 +94,7 @@ virtualObjects.clear(); } - return new LIRDebugInfo(frame, virtualObjectsArray, pointerSlots, exceptionEdge); + return new LIRFrameState(frame, virtualObjectsArray, pointerSlots, exceptionEdge); } private BytecodeFrame computeFrameForState(FrameState state, LockScope locks, long leafGraphId) { diff -r e1d5c642d022 -r 141b15521a39 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 Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Jun 29 18:33:48 2012 -0700 @@ -261,21 +261,21 @@ return LabelRef.forSuccessor(currentBlock, suxIndex); } - public LIRDebugInfo state() { + public LIRFrameState state() { assert lastState != null : "must have state before instruction"; return stateFor(lastState, -1); } - public LIRDebugInfo state(long leafGraphId) { + public LIRFrameState state(long leafGraphId) { assert lastState != null : "must have state before instruction"; return stateFor(lastState, leafGraphId); } - public LIRDebugInfo stateFor(FrameState state, long leafGraphId) { + public LIRFrameState stateFor(FrameState state, long leafGraphId) { return stateFor(state, null, null, leafGraphId); } - public LIRDebugInfo stateFor(FrameState state, List pointerSlots, LabelRef exceptionEdge, long leafGraphId) { + public LIRFrameState stateFor(FrameState state, List pointerSlots, LabelRef exceptionEdge, long leafGraphId) { return debugInfoBuilder.build(state, curLocks, pointerSlots, exceptionEdge, leafGraphId); } @@ -552,11 +552,11 @@ XirArgument obj = toXirArgument(x.object()); XirArgument lockAddress = lockData == null ? null : toXirArgument(emitLea(lockData)); - LIRDebugInfo stateBefore = state(); + LIRFrameState stateBefore = state(); // The state before the monitor enter is used for null checks, so it must not contain the newly locked object. curLocks = new LockScope(curLocks, x.stateAfter().inliningIdentifier(), x, lockData); // The state after the monitor enter is used for deoptimization, after the monitor has blocked, so it must contain the newly locked object. - LIRDebugInfo stateAfter = stateFor(x.stateAfter(), -1); + LIRFrameState stateAfter = stateFor(x.stateAfter(), -1); XirSnippet snippet = xir.genMonitorEnter(site(x, x.object()), obj, lockAddress); emitXir(snippet, x, stateBefore, stateAfter, true, null, null); @@ -576,7 +576,7 @@ XirArgument obj = toXirArgument(x.object()); XirArgument lockAddress = lockData == null ? null : toXirArgument(emitLea(lockData)); - LIRDebugInfo stateBefore = state(); + LIRFrameState stateBefore = state(); curLocks = curLocks.outer; XirSnippet snippet = xir.genMonitorExit(site(x, x.object()), obj, lockAddress); @@ -698,7 +698,7 @@ // False constants are handled within emitBranch. } else { // Fall back to a normal branch. - LIRDebugInfo info = state(leafGraphId); + LIRFrameState info = state(leafGraphId); LabelRef stubEntry = createDeoptStub(action, deoptReason, info, comp); if (negated) { emitBranch(comp, stubEntry, null, info); @@ -710,7 +710,7 @@ protected abstract void emitNullCheckGuard(ValueNode object, long leafGraphId); - public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { + public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) { if (node instanceof IsNullNode) { emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, info); } else if (node instanceof CompareNode) { @@ -726,7 +726,7 @@ } } - private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { + private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) { if (falseSuccessor != null) { emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info); if (trueSuccessor != null) { @@ -737,7 +737,7 @@ } } - public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRDebugInfo info) { + public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) { if (falseSuccessorBlock != null) { emitBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info); if (trueSuccessorBlock != null) { @@ -748,20 +748,20 @@ } } - private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { + private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) { XirArgument obj = toXirArgument(x.object()); XirSnippet snippet = xir.genInstanceOf(site(x, x.object()), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), x.profile()); emitXir(snippet, x, info, null, false, trueSuccessor, falseSuccessor); } - public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRDebugInfo info) { + public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) { LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock; if (block != null) { emitJump(block, info); } } - public void emitTypeBranch(IsTypeNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { + public void emitTypeBranch(IsTypeNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) { XirArgument thisClass = toXirArgument(x.objectClass()); XirArgument otherClass = toXirArgument(x.type().getEncoding(Representation.ObjectHub)); XirSnippet snippet = xir.genTypeBranch(site(x), thisClass, otherClass, x.type()); @@ -814,8 +814,8 @@ public abstract void emitLabel(Label label, boolean align); - public abstract void emitJump(LabelRef label, LIRDebugInfo info); - public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRDebugInfo info); + public abstract void emitJump(LabelRef label, LIRFrameState info); + public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info); public abstract Variable emitCMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); protected FrameState stateBeforeCallWithArguments(FrameState stateAfter, MethodCallTargetNode call, int bci) { @@ -882,7 +882,7 @@ if (!target().invokeSnippetAfterArguments) { // This is the version currently necessary for Maxine: since the invokeinterface-snippet uses a division, it // destroys rdx, which is also used to pass a parameter. Therefore, the snippet must be before the parameters are assigned to their locations. - LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId()); + LIRFrameState addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId()); destinationAddress = emitXir(snippet, x.node(), addrInfo, false); } @@ -895,11 +895,11 @@ if (target().invokeSnippetAfterArguments) { // This is the version currently active for HotSpot. - LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId()); + LIRFrameState addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId()); destinationAddress = emitXir(snippet, x.node(), addrInfo, false); } - LIRDebugInfo callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId()); + LIRFrameState callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId()); emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks); if (isLegal(resultOperand)) { @@ -907,7 +907,7 @@ } } - protected abstract void emitCall(Object targetMethod, Value result, List arguments, Value targetAddress, LIRDebugInfo info, Map marks); + protected abstract void emitCall(Object targetMethod, Value result, List arguments, Value targetAddress, LIRFrameState info, Map marks); private static Value toStackKind(Value value) { @@ -942,11 +942,11 @@ } - protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo); + protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo); @Override public Variable emitCall(@SuppressWarnings("hiding") Object target, Kind result, Kind[] arguments, boolean canTrap, Value... args) { - LIRDebugInfo info = canTrap ? state() : null; + LIRFrameState info = canTrap ? state() : null; Value physReg = resultOperandFor(result); @@ -984,7 +984,7 @@ frameMap.callsMethod(cc, RuntimeCall); List argList = visitInvokeArguments(cc, x.arguments()); - LIRDebugInfo info = null; + LIRFrameState info = null; FrameState stateAfter = x.stateAfter(); if (stateAfter != null) { // (cwimmer) I made the code that modifies the operand stack conditional. My scenario: runtime calls to, e.g., @@ -1192,11 +1192,11 @@ return variable; } - protected Value emitXir(XirSnippet snippet, ValueNode x, LIRDebugInfo info, boolean setInstructionResult) { + protected Value emitXir(XirSnippet snippet, ValueNode x, LIRFrameState info, boolean setInstructionResult) { return emitXir(snippet, x, info, null, setInstructionResult, null, null); } - protected Value emitXir(XirSnippet snippet, ValueNode instruction, LIRDebugInfo info, LIRDebugInfo infoAfter, boolean setInstructionResult, LabelRef trueSuccessor, LabelRef falseSuccessor) { + protected Value emitXir(XirSnippet snippet, ValueNode instruction, LIRFrameState info, LIRFrameState infoAfter, boolean setInstructionResult, LabelRef trueSuccessor, LabelRef falseSuccessor) { if (GraalOptions.PrintXirTemplates) { TTY.println("Emit XIR template " + snippet.template.name); } @@ -1304,9 +1304,9 @@ } protected abstract void emitXir(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, - LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor); + LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor); - protected final Value callRuntime(RuntimeCall runtimeCall, LIRDebugInfo info, Value... args) { + protected final Value callRuntime(RuntimeCall runtimeCall, LIRFrameState info, Value... args) { // get a result register Kind result = runtimeCall.resultKind; Kind[] arguments = runtimeCall.arguments; @@ -1336,7 +1336,7 @@ return physReg; } - protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRDebugInfo info, Value... args) { + protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRFrameState info, Value... args) { Value location = callRuntime(runtimeCall, info, args); return emitMove(location); } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Fri Jun 29 18:33:48 2012 -0700 @@ -35,12 +35,12 @@ public class AMD64DeoptimizationStub extends AMD64Code { public final Label label = new Label(); - public final LIRDebugInfo info; + public final LIRFrameState info; public final DeoptimizationAction action; public final DeoptimizationReason reason; public final Object deoptInfo; - public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo) { + public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { this.action = action; this.reason = reason; this.info = info; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Fri Jun 29 18:33:48 2012 -0700 @@ -213,12 +213,12 @@ } @Override - public void emitJump(LabelRef label, LIRDebugInfo info) { + public void emitJump(LabelRef label, LIRFrameState info) { append(new JumpOp(label, info)); } @Override - public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRDebugInfo info) { + public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) { boolean mirrored = emitCompare(left, right); Condition finalCondition = mirrored ? cond.mirror() : cond; switch (left.kind.stackKind()) { @@ -520,7 +520,7 @@ @Override public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { - LIRDebugInfo info = state(); + LIRFrameState info = state(); LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); append(new BranchOp(ConditionFlag.overflow, stubEntry, info)); } @@ -528,7 +528,7 @@ @Override public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo, long leafGraphId) { - LIRDebugInfo info = state(leafGraphId); + LIRFrameState info = state(leafGraphId); LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); append(new JumpOp(stubEntry, info)); } @@ -542,7 +542,7 @@ } @Override - protected void emitCall(Object targetMethod, Value result, List arguments, Value targetAddress, LIRDebugInfo info, Map marks) { + protected void emitCall(Object targetMethod, Value result, List arguments, Value targetAddress, LIRFrameState info, Map marks) { if (isConstant(targetAddress)) { append(new DirectCallOp(targetMethod, result, arguments.toArray(new Value[arguments.size()]), info, marks)); } else { @@ -557,7 +557,7 @@ @Override protected void emitXir(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, - LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) { + LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) { append(new AMD64XirOp(snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor)); } @@ -565,7 +565,7 @@ protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { // Making a copy of the switch value is necessary because jump table destroys the input value if (key.kind == Kind.Int) { - append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key)); + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.IllegalValue)); } else { assert key.kind == Kind.Object; append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object))); @@ -585,7 +585,7 @@ } @Override - protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo) { + protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate"; AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo); lir.stubs.add(stub); @@ -595,7 +595,7 @@ @Override protected void emitNullCheckGuard(ValueNode object, long leafGraphId) { Variable value = load(operand(object)); - LIRDebugInfo info = state(leafGraphId); + LIRFrameState info = state(leafGraphId); append(new NullCheckOp(value, info)); } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java Fri Jun 29 18:33:48 2012 -0700 @@ -46,8 +46,8 @@ public class AMD64XirOp extends LIRXirInstruction { public AMD64XirOp(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, - LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) { - super("XIR", snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor); + LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) { + super(snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor); } @Override @@ -165,7 +165,7 @@ Value pointer = operands[inst.x().index]; RegisterValue register = assureInRegister(tasm, masm, pointer); - AMD64Move.load(tasm, masm, result, new Address(inst.kind, register), (Boolean) inst.extra ? info : null); + AMD64Move.load(tasm, masm, result, new Address(inst.kind, register), (Boolean) inst.extra ? state : null); break; } @@ -174,7 +174,7 @@ Value pointer = operands[inst.x().index]; assert isRegister(pointer); - AMD64Move.store(tasm, masm, new Address(inst.kind, pointer), value, (Boolean) inst.extra ? info : null); + AMD64Move.store(tasm, masm, new Address(inst.kind, pointer), value, (Boolean) inst.extra ? state : null); break; } @@ -201,7 +201,7 @@ src = new Address(inst.kind, pointer, index, scale, displacement); } - AMD64Move.load(tasm, masm, result, src, canTrap ? info : null); + AMD64Move.load(tasm, masm, result, src, canTrap ? state : null); break; } @@ -245,7 +245,7 @@ dst = new Address(inst.kind, pointer, index, scale, displacement); } - AMD64Move.store(tasm, masm, dst, value, canTrap ? info : null); + AMD64Move.store(tasm, masm, dst, value, canTrap ? state : null); break; } @@ -271,8 +271,8 @@ RegisterValue pointerRegister = assureInRegister(tasm, masm, exchangedAddress); Address addr = new Address(tasm.target.wordKind, pointerRegister); - if ((Boolean) inst.extra && info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); + if ((Boolean) inst.extra && state != null) { + tasm.recordImplicitException(masm.codeBuffer.position(), state); } masm.cmpxchgq(asRegister(exchangedVal), addr); @@ -294,7 +294,7 @@ } RuntimeCallInformation runtimeCallInformation = (RuntimeCallInformation) inst.extra; - AMD64Call.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info); + AMD64Call.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? stateAfter : state); if (inst.result != null && inst.result.kind != Kind.Illegal && inst.result.kind != Kind.Void) { Register returnRegister = tasm.frameMap.registerConfig.getReturnRegister(inst.result.kind); @@ -386,12 +386,12 @@ break; } case Safepoint: { - assert info != null : "Must have debug info in order to create a safepoint."; - tasm.recordSafepoint(masm.codeBuffer.position(), info); + assert state != null : "Must have debug info in order to create a safepoint."; + tasm.recordSafepoint(masm.codeBuffer.position(), state); break; } case NullCheck: { - tasm.recordImplicitException(masm.codeBuffer.position(), info); + tasm.recordImplicitException(masm.codeBuffer.position(), state); Value pointer = operands[inst.x().index]; masm.nullCheck(asRegister(pointer)); break; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java Fri Jun 29 18:33:48 2012 -0700 @@ -32,9 +32,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.*; @@ -42,7 +41,6 @@ import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; import com.oracle.max.criutils.*; - public class MethodEntryCounters { protected static final class Counter implements Comparable { protected static ArrayList counters = new ArrayList<>(); @@ -64,23 +62,24 @@ } + @Opcode("ENTRY_COUNTER") protected static class AMD64MethodEntryOp extends AMD64LIRInstruction { + @Temp protected Value counterArr; + @Temp protected Value callerPc; + protected static int codeSize; protected final Counter counter; protected AMD64MethodEntryOp(Counter counter, Value counterArr, Value callerPc) { - super("ENTRY_COUNTER", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, new Value[] {counterArr, callerPc}); this.counter = counter; + this.counterArr = counterArr; + this.callerPc = callerPc; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { int start = masm.codeBuffer.position(); - - Value counterArr = temp(0); - Value callerPc = temp(1); - int off = Unsafe.getUnsafe().arrayBaseOffset(long[].class); int scale = Unsafe.getUnsafe().arrayIndexScale(long[].class); @@ -114,16 +113,6 @@ assert codeSize == 0 || codeSize == size; codeSize = size; } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Temp && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Temp && index == 1) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); - } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Fri Jun 29 18:33:48 2012 -0700 @@ -62,7 +62,7 @@ public void generate(LIRGenerator gen) { Variable result = gen.newVariable(Kind.Object); gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object)); - LIRDebugInfo info = gen.state(); + LIRFrameState info = gen.state(); AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info); gen.append(op); gen.setResult(this, result); diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Fri Jun 29 18:33:48 2012 -0700 @@ -72,6 +72,6 @@ Value entry = gen.emitLoad(new Address(Kind.Long, gen.operand(target), config.nmethodEntryOffset), false); - gen.append(new AMD64TailcallOp(argList, entry, cc.locations)); + gen.append(new AMD64TailcallOp(argList, entry)); } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Fri Jun 29 18:33:48 2012 -0700 @@ -45,7 +45,7 @@ @Override public void generate(LIRGenerator gen) { - LIRDebugInfo info = gen.state(); + LIRFrameState info = gen.state(); AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info); gen.append(op); } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java Fri Jun 29 18:33:48 2012 -0700 @@ -24,48 +24,45 @@ import static com.oracle.graal.api.code.ValueUtil.*; -import java.util.*; - import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.target.amd64.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; /** * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp. */ +@Opcode("NEW_INSTANCE") public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction { - public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRDebugInfo info) { - super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, new Value[]{AMD64.rax.asValue(Kind.Object)}); + @Def protected Value result; + @Use protected Value hub; + @Temp protected Value temp; + @State protected LIRFrameState state; + + public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) { + this.result = result; + this.hub = hub; + this.temp = AMD64.rax.asValue(Kind.Object); + this.state = state; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value hub = input(0); - // rdx: (in) hub // rax: (out) result - assert asRegister(hub) == AMD64.rdx; - AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, info); + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state); if (asRegister(result) != AMD64.rax) { masm.movq(asRegister(result), AMD64.rax); } } @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Temp) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + protected void verify() { + super.verify(); + assert asRegister(hub) == AMD64.rdx; } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java Fri Jun 29 18:33:48 2012 -0700 @@ -24,13 +24,10 @@ import static com.oracle.graal.api.code.ValueUtil.*; -import java.util.*; - -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.target.amd64.*; @@ -38,30 +35,26 @@ /** * A call to HotSpot's object pointer verification stub. */ +@Opcode("VERIFY_OOP") public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction { - public AMD64VerifyOopStubCallOp(Value object, LIRDebugInfo info) { - super("VERIFY_OOP", LIRInstruction.NO_OPERANDS, info, new Value[] {object}, NO_OPERANDS, NO_OPERANDS); + @Use protected Value object; + @State protected LIRFrameState state; + + public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) { + this.object = object; + this.state = state; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Register object = asRegister(input(0)); // r13: (in) object - if (object != AMD64.r13) { + if (asRegister(object) != AMD64.r13) { masm.push(AMD64.r13); - masm.movq(AMD64.r13, object); + masm.movq(AMD64.r13, asRegister(object)); } - AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, info); - if (object != AMD64.r13) { + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state); + if (asRegister(object) != AMD64.r13) { masm.pop(AMD64.r13); } } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); - } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java Fri Jun 29 18:33:48 2012 -0700 @@ -25,12 +25,10 @@ import static com.oracle.graal.hotspot.meta.HotSpotXirGenerator.*; import static com.oracle.max.asm.target.amd64.AMD64.*; -import java.util.*; - import com.oracle.graal.api.code.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.target.amd64.*; @@ -38,12 +36,14 @@ /** * Emits a safepoint poll. */ +@Opcode("SAFEPOINT") public class AMD64SafepointOp extends AMD64LIRInstruction { + @State protected LIRFrameState state; private final HotSpotVMConfig config; - public AMD64SafepointOp(LIRDebugInfo info, HotSpotVMConfig config) { - super("SAFEPOINT", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config) { + this.state = state; this.config = config; } @@ -54,17 +54,12 @@ if (config.isPollingPageFar) { asm.movq(scratch, config.safepointPollingAddress); tasm.recordMark(MARK_POLL_FAR); - tasm.recordSafepoint(pos, info); + tasm.recordSafepoint(pos, state); asm.movq(scratch, new Address(tasm.target.wordKind, scratch.asValue())); } else { tasm.recordMark(MARK_POLL_NEAR); - tasm.recordSafepoint(pos, info); + tasm.recordSafepoint(pos, state); asm.movq(scratch, new Address(tasm.target.wordKind, rip.asValue())); } } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - throw GraalInternalError.shouldNotReachHere(); - } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java Fri Jun 29 18:33:48 2012 -0700 @@ -26,33 +26,23 @@ import java.util.*; -import com.oracle.max.asm.target.amd64.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; /** * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance. */ +@Opcode("TAILCALL") public class AMD64TailcallOp extends AMD64LIRInstruction { - - public AMD64TailcallOp(List parameters, Value target, Value[] callingConvention) { - super("TAILCALL", LIRInstruction.NO_OPERANDS, null, toArray(parameters, target), LIRInstruction.NO_OPERANDS, callingConvention.clone()); - assert inputs.length == temps.length + 1; + @Use protected Value target; + @Alive protected Value[] parameters; - for (int i = 0; i < temps.length; i++) { - assert isRegister(temps[i]) : "too many parameters for tail call"; - assert sameRegister(temps[i], inputs[i]) : "inputs do not match calling convention"; - } - } - - private static Value[] toArray(List parameters, Value target) { - Value[] result = new Value[parameters.size() + 1]; - parameters.toArray(result); - result[parameters.size()] = target; - return result; + public AMD64TailcallOp(List parameters, Value target) { + this.target = target; + this.parameters = parameters.toArray(new Value[parameters.size()]); } @Override @@ -61,17 +51,7 @@ masm.leave(); // jump to the target method - masm.jmp(asRegister(inputs[inputs.length - 1])); + masm.jmp(asRegister(target)); masm.ensureUniquePC(); } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Temp) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); - } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Fri Jun 29 18:33:48 2012 -0700 @@ -61,7 +61,7 @@ @Override public void visitSafepointNode(SafepointNode i) { - LIRDebugInfo info = state(); + LIRFrameState info = state(); append(new AMD64SafepointOp(info, ((HotSpotRuntime) runtime).config)); } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Fri Jun 29 18:33:48 2012 -0700 @@ -23,16 +23,15 @@ package com.oracle.graal.lir.amd64; import static com.oracle.graal.api.code.ValueUtil.*; - -import java.util.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; public enum AMD64Arithmetic { IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, @@ -48,254 +47,183 @@ public static class Op1Reg extends AMD64LIRInstruction { - public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) { - super(opcode, new Value[] {result}, null, new Value[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value x = input(0); - - emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); - } + @Opcode private final AMD64Arithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG}) protected Value x; - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); - } - } - - public static class Op1Stack extends AMD64LIRInstruction { - public Op1Stack(AMD64Arithmetic opcode, Value result, Value x) { - super(opcode, new Value[] {result}, null, new Value[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) { + this.opcode = opcode; + this.result = result; + this.x = x; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value x = input(0); - - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw GraalInternalError.shouldNotReachHere(); + emit(tasm, masm, opcode, result, x, null); } } - public static class Op2Stack extends AMD64LIRInstruction { - public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) { - super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS); + public static class Op1Stack extends AMD64LIRInstruction { + @Opcode private final AMD64Arithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + + public Op1Stack(AMD64Arithmetic opcode, Value result, Value x) { + this.opcode = opcode; + this.result = result; + this.x = x; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value x = input(0); - Value y = alive(0); - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw GraalInternalError.shouldNotReachHere(); - } - - @Override - public void verify() { - Value result = output(0); - Value x = input(0); - Value y = alive(0); - - super.verify(); - assert differentRegisters(result, y) || sameRegister(x, y); - verifyKind((AMD64Arithmetic) code, result, x, y); + emit(tasm, masm, opcode, result); } } - public static class Op2Reg extends AMD64LIRInstruction { - public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) { - super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS); + public static class Op2Stack extends AMD64LIRInstruction { + @Opcode private final AMD64Arithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Alive({REG, STACK, CONST}) protected Value y; + + public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value x = input(0); - Value y = alive(0); - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw GraalInternalError.shouldNotReachHere(); + emit(tasm, masm, opcode, result, y, null); } @Override public void verify() { - Value result = output(0); - Value x = input(0); - Value y = alive(0); - super.verify(); assert differentRegisters(result, y) || sameRegister(x, y); - verifyKind((AMD64Arithmetic) code, result, x, y); + verifyKind(opcode, result, x, y); + } + } + + public static class Op2Reg extends AMD64LIRInstruction { + @Opcode private final AMD64Arithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Alive({REG, CONST}) protected Value y; + + public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, opcode, result, y, null); + } + + @Override + public void verify() { + super.verify(); + assert differentRegisters(result, y) || sameRegister(x, y); + verifyKind(opcode, result, x, y); } } public static class Op2RegCommutative extends AMD64LIRInstruction { + @Opcode private final AMD64Arithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Use({REG, CONST}) protected Value y; + public Op2RegCommutative(AMD64Arithmetic opcode, Value result, Value x, Value y) { - super(opcode, new Value[] {result}, null, new Value[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value x = input(0); - Value y = input(1); - if (sameRegister(result, y)) { - emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); + emit(tasm, masm, opcode, result, x, null); } else { AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + emit(tasm, masm, opcode, result, y, null); } } @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Input && index == 1) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw GraalInternalError.shouldNotReachHere(); - } - - @Override protected void verify() { - Value result = output(0); - Value x = input(0); - Value y = input(1); - super.verify(); - verifyKind((AMD64Arithmetic) code, result, x, y); + verifyKind(opcode, result, x, y); } } public static class ShiftOp extends AMD64LIRInstruction { + @Opcode private final AMD64Arithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Alive({REG, CONST}) protected Value y; + public ShiftOp(AMD64Arithmetic opcode, Value result, Value x, Value y) { - super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS); + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value x = input(0); - Value y = alive(0); - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw GraalInternalError.shouldNotReachHere(); + emit(tasm, masm, opcode, result, y, null); } @Override public void verify() { - Value result = output(0); - Value x = input(0); - Value y = alive(0); - super.verify(); assert isConstant(y) || asRegister(y) == AMD64.rcx; assert differentRegisters(result, y) || sameRegister(x, y); - verifyKind((AMD64Arithmetic) code, result, x, x); + verifyKind(opcode, result, x, x); assert y.kind.stackKind() == Kind.Int; } } public static class DivOp extends AMD64LIRInstruction { - public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRDebugInfo info) { - super(opcode, new Value[] {result}, info, new Value[] {x}, new Value[] {y}, new Value[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)}); + @Opcode private final AMD64Arithmetic opcode; + @Def protected Value result; + @Use protected Value x; + @Alive protected Value y; + @Temp protected Value temp; + @State protected LIRFrameState state; + + public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + this.temp = asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind); + this.state = state; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value result = output(0); - Value y = alive(0); - - emit(tasm, masm, (AMD64Arithmetic) code, result, y, info); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Temp && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + emit(tasm, masm, opcode, result, y, state); } @Override protected void verify() { - Value result = output(0); - Value x = input(0); - Value y = alive(0); - super.verify(); // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx assert asRegister(x) == AMD64.rax; assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue()); assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx); - verifyKind((AMD64Arithmetic) code, result, x, y); + verifyKind(opcode, result, x, y); } } @@ -313,7 +241,7 @@ } } - public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value dst, Value src, LIRDebugInfo info) { + public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value dst, Value src, LIRFrameState info) { int exceptionOffset = -1; if (isRegister(src)) { switch (opcode) { diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Jun 29 18:33:48 2012 -0700 @@ -23,27 +23,35 @@ package com.oracle.graal.lir.amd64; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import java.util.*; +import com.oracle.graal.api.code.CompilationResult.Mark; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.asm.*; public class AMD64Call { + @Opcode("CALL_DIRECT") public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { - private final Object targetMethod; - private final Map marks; + @Def({REG, ILLEGAL}) protected Value result; + @Use({REG, STACK}) protected Value[] parameters; + @State protected LIRFrameState state; - public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRDebugInfo info, Map marks) { - super("CALL_DIRECT", new Value[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + protected final Object targetMethod; + protected final Map marks; + + public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRFrameState state, Map marks) { this.targetMethod = targetMethod; + this.result = result; + this.parameters = parameters; + this.state = state; this.marks = marks; } @@ -53,57 +61,36 @@ if (marks != null) { marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); } - directCall(tasm, masm, targetMethod, info); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } else if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - } - throw GraalInternalError.shouldNotReachHere(); + directCall(tasm, masm, targetMethod, state); } } + @Opcode("CALL_INDIRECT") public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + @Def({REG, ILLEGAL}) protected Value result; + @Use({REG, STACK}) protected Value[] parameters; + @Use({REG}) protected Value targetAddress; + @State protected LIRFrameState state; + private final Object targetMethod; private final Map marks; - private static Value[] concat(Value[] parameters, Value targetAddress) { - Value[] result = Arrays.copyOf(parameters, parameters.length + 1); - result[result.length - 1] = targetAddress; - return result; - } - - public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRDebugInfo info, Map marks) { - super("CALL_INDIRECT", new Value[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRFrameState state, Map marks) { this.targetMethod = targetMethod; + this.result = result; + this.parameters = parameters; + this.targetAddress = targetAddress; + this.state = state; this.marks = marks; } - private Value targetAddress() { - return input(inputs.length - 1); - } - @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { callAlignment(tasm, masm); if (marks != null) { marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); } - indirectCall(tasm, masm, asRegister(targetAddress()), targetMethod, info); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } else if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - } - throw GraalInternalError.shouldNotReachHere(); + indirectCall(tasm, masm, asRegister(targetAddress), targetMethod, state); } } @@ -117,7 +104,7 @@ } } - public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) { + public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRFrameState info) { int before = masm.codeBuffer.position(); if (target instanceof RuntimeCall) { long maxOffset = tasm.runtime.getMaxCallTargetOffset((RuntimeCall) target); @@ -148,7 +135,7 @@ masm.ensureUniquePC(); } - public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object target, LIRDebugInfo info) { + public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object target, LIRFrameState info) { int before = masm.codeBuffer.position(); masm.call(dst); int after = masm.codeBuffer.position(); diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Fri Jun 29 18:33:48 2012 -0700 @@ -23,45 +23,34 @@ package com.oracle.graal.lir.amd64; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; public enum AMD64Compare { ICMP, LCMP, ACMP, FCMP, DCMP; public static class CompareOp extends AMD64LIRInstruction { + @Opcode private final AMD64Compare opcode; + @Use({REG}) protected Value x; + @Use({REG, STACK, CONST}) protected Value y; + public CompareOp(AMD64Compare opcode, Value x, Value y) { - super(opcode, LIRInstruction.NO_OPERANDS, null, new Value[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.opcode = opcode; + this.x = x; + this.y = y; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value x = input(0); - Value y = input(1); - emit(tasm, masm, (AMD64Compare) code, x, y); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Input && index == 1) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } - throw GraalInternalError.shouldNotReachHere(); + emit(tasm, masm, opcode, x, y); } @Override protected void verify() { - Value x = input(0); - Value y = input(1); - super.verify(); assert (name().startsWith("I") && x.kind == Kind.Int && y.kind.stackKind() == Kind.Int) || (name().startsWith("I") && x.kind == Kind.Jsr && y.kind == Kind.Jsr) diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Fri Jun 29 18:33:48 2012 -0700 @@ -23,27 +23,29 @@ package com.oracle.graal.lir.amd64; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import java.util.*; - +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Address.Scale; +import com.oracle.graal.api.code.CompilationResult.JumpTable; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.StandardOp.FallThroughOp; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.max.asm.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Address.*; -import com.oracle.graal.api.code.CompilationResult.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.FallThroughOp; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.calc.*; public class AMD64ControlFlow { public static class ReturnOp extends AMD64LIRInstruction { - public ReturnOp(Value input) { - super("RETURN", LIRInstruction.NO_OPERANDS, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + @Use({REG, ILLEGAL}) protected Value x; + + public ReturnOp(Value x) { + this.x = x; } @Override @@ -53,29 +55,22 @@ } masm.ret(0); } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - } - throw GraalInternalError.shouldNotReachHere(); - } } public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp { protected ConditionFlag condition; protected LabelRef destination; + @State protected LIRFrameState state; - public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) { + public BranchOp(Condition condition, LabelRef destination, LIRFrameState info) { this(intCond(condition), destination, info); } - public BranchOp(ConditionFlag condition, LabelRef destination, LIRDebugInfo info) { - super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + public BranchOp(ConditionFlag condition, LabelRef destination, LIRFrameState state) { this.condition = condition; this.destination = destination; + this.state = state; } @Override @@ -93,23 +88,13 @@ destination = newDestination; condition = condition.negate(); } - - @Override - public String operationString() { - return condition.operator + " [" + destination + "]"; - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - throw GraalInternalError.shouldNotReachHere(); - } } public static class FloatBranchOp extends BranchOp { protected boolean unorderedIsTrue; - public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRDebugInfo info) { + public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRFrameState info) { super(floatCond(condition), destination, info); this.unorderedIsTrue = unorderedIsTrue; } @@ -124,11 +109,6 @@ super.negate(newDestination); unorderedIsTrue = !unorderedIsTrue; } - - @Override - public String operationString() { - return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse"); - } } @@ -136,58 +116,41 @@ private final int lowKey; private final LabelRef defaultTarget; private final LabelRef[] targets; + @Alive protected Value index; + @Temp protected Value scratch; public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) { - super("TABLE_SWITCH", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new Value[] {index}, new Value[] {scratch}); this.lowKey = lowKey; this.defaultTarget = defaultTarget; this.targets = targets; + this.index = index; + this.scratch = scratch; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(alive(0)), asLongReg(temp(0))); - } - - @Override - public String operationString() { - StringBuilder buf = new StringBuilder(super.operationString()); - buf.append("\ndefault: [").append(defaultTarget).append(']'); - int key = lowKey; - for (LabelRef l : targets) { - buf.append("\ncase ").append(key).append(": [").append(l).append(']'); - key++; - } - return buf.toString(); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Temp && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch)); } } public static class SequentialSwitchOp extends AMD64LIRInstruction implements FallThroughOp { - private final Constant[] keyConstants; + @Use({CONST}) protected Constant[] keyConstants; private final LabelRef[] keyTargets; private LabelRef defaultTarget; + @Alive({REG}) protected Value key; + @Temp({REG, ILLEGAL}) protected Value scratch; - public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value... temp) { - super("SEQUENTIAL_SWITCH", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new Value[] {key}, temp); + public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { assert keyConstants.length == keyTargets.length; this.keyConstants = keyConstants; this.keyTargets = keyTargets; this.defaultTarget = defaultTarget; + this.key = key; + this.scratch = scratch; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Value key = alive(0); if (key.kind == Kind.Int) { Register intKey = asIntReg(key); for (int i = 0; i < keyConstants.length; i++) { @@ -196,7 +159,7 @@ } } else if (key.kind == Kind.Object) { Register intKey = asObjectReg(key); - Register temp = asObjectReg(temp(0)); + Register temp = asObjectReg(scratch); for (int i = 0; i < keyConstants.length; i++) { AMD64Move.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]); masm.cmpptr(intKey, temp); @@ -213,26 +176,6 @@ } @Override - public String operationString() { - StringBuilder buf = new StringBuilder(super.operationString()); - buf.append("\ndefault: [").append(defaultTarget).append(']'); - for (int i = 0; i < keyConstants.length; i++) { - buf.append("\ncase ").append(keyConstants[i]).append(": [").append(keyTargets[i]).append("]"); - } - return buf.toString(); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Temp && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); - } - - @Override public LabelRef fallThroughTarget() { return defaultTarget; } @@ -248,37 +191,34 @@ private LabelRef defaultTarget; private final int[] lowKeys; private final int[] highKeys; + @Alive protected Value key; public SwitchRangesOp(int[] lowKeys, int[] highKeys, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { - super("SWITCH_RANGES", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new Value[] {key}, LIRInstruction.NO_OPERANDS); - assert lowKeys.length == keyTargets.length; - assert highKeys.length == keyTargets.length; - assert key.kind == Kind.Int; this.lowKeys = lowKeys; this.highKeys = highKeys; this.keyTargets = keyTargets; this.defaultTarget = defaultTarget; + this.key = key; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Register key = asIntReg(alive(0)); for (int i = 0; i < lowKeys.length; i++) { int lowKey = lowKeys[i]; int highKey = highKeys[i]; if (lowKey == highKey) { - masm.cmpl(key, lowKey); + masm.cmpl(asIntReg(key), lowKey); masm.jcc(ConditionFlag.equal, keyTargets[i].label()); } else if (lowKey + 1 == highKey) { - masm.cmpl(key, lowKey); + masm.cmpl(asIntReg(key), lowKey); masm.jcc(ConditionFlag.equal, keyTargets[i].label()); - masm.cmpl(key, highKey); + masm.cmpl(asIntReg(key), highKey); masm.jcc(ConditionFlag.equal, keyTargets[i].label()); } else { Label skip = new Label(); - masm.cmpl(key, lowKey); + masm.cmpl(asIntReg(key), lowKey); masm.jcc(ConditionFlag.less, skip); - masm.cmpl(key, highKey); + masm.cmpl(asIntReg(key), highKey); masm.jcc(ConditionFlag.lessEqual, keyTargets[i].label()); masm.bind(skip); } @@ -291,23 +231,11 @@ } @Override - public String operationString() { - StringBuilder buf = new StringBuilder(super.operationString()); - buf.append("\ndefault: [").append(defaultTarget).append(']'); - for (int i = 0; i < lowKeys.length; i++) { - buf.append("\ncase ").append(lowKeys[i]).append(" - ").append(highKeys[i]).append(": [").append(keyTargets[i]).append("]"); - } - return buf.toString(); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Temp && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + protected void verify() { + super.verify(); + assert lowKeys.length == keyTargets.length; + assert highKeys.length == keyTargets.length; + assert key.kind == Kind.Int; } @Override @@ -322,68 +250,46 @@ } + @Opcode("CMOVE") public static class CondMoveOp extends AMD64LIRInstruction { + @Def({REG, HINT}) protected Value result; + @Alive({REG}) protected Value trueValue; + @Use({REG, STACK, CONST}) protected Value falseValue; private final ConditionFlag condition; public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) { - super("CMOVE", new Value[] {result}, null, new Value[] {falseValue}, new Value[] {trueValue}, LIRInstruction.NO_OPERANDS); + this.result = result; this.condition = intCond(condition); + this.trueValue = trueValue; + this.falseValue = falseValue; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0)); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw GraalInternalError.shouldNotReachHere(); - } - - @Override - public String operationString() { - return condition.toString() + " " + super.operationString(); + cmove(tasm, masm, result, false, condition, false, trueValue, falseValue); } } + @Opcode("CMOVE") public static class FloatCondMoveOp extends AMD64LIRInstruction { + @Def({REG}) protected Value result; + @Alive({REG}) protected Value trueValue; + @Alive({REG}) protected Value falseValue; private final ConditionFlag condition; private final boolean unorderedIsTrue; public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { - super("FLOAT_CMOVE", new Value[] {result}, null, LIRInstruction.NO_OPERANDS, new Value[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS); + this.result = result; this.condition = floatCond(condition); this.unorderedIsTrue = unorderedIsTrue; + this.trueValue = trueValue; + this.falseValue = falseValue; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - cmove(tasm, masm, output(0), true, condition, unorderedIsTrue, alive(0), alive(1)); - } - - @Override - public String operationString() { - return condition.toString() + " unordered=" + unorderedIsTrue + " " + super.operationString(); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Alive && index == 1) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue); } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java Fri Jun 29 18:33:48 2012 -0700 @@ -22,20 +22,14 @@ */ package com.oracle.graal.lir.amd64; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; /** * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method. */ public abstract class AMD64LIRInstruction extends LIRInstruction { - - public AMD64LIRInstruction(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps) { - super(opcode, outputs, info, inputs, alives, temps); - } - @Override public final void emitCode(TargetMethodAssembler tasm) { emitCode(tasm, (AMD64MacroAssembler) tasm.asm); diff -r e1d5c642d022 -r 141b15521a39 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 Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Jun 29 18:33:48 2012 -0700 @@ -23,25 +23,30 @@ package com.oracle.graal.lir.amd64; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static java.lang.Double.*; import static java.lang.Float.*; -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; public class AMD64Move { + @Opcode("MOVE") public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp { + @Def({REG, STACK}) protected Value result; + @Use({REG, STACK, CONST}) protected Value input; + public SpillMoveOp(Value result, Value input) { - super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.result = result; + this.input = input; } @Override @@ -51,28 +56,23 @@ @Override public Value getInput() { - return input(0); + return input; } @Override public Value getResult() { - return output(0); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw GraalInternalError.shouldNotReachHere(); + return result; } } + @Opcode("MOVE") public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp { + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value input; + public MoveToRegOp(Value result, Value input) { - super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.result = result; + this.input = input; } @Override @@ -82,28 +82,23 @@ @Override public Value getInput() { - return input(0); + return input; } @Override public Value getResult() { - return output(0); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw GraalInternalError.shouldNotReachHere(); + return result; } } + @Opcode("MOVE") public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp { + @Def({REG, STACK}) protected Value result; + @Use({REG, CONST, HINT}) protected Value input; + public MoveFromRegOp(Value result, Value input) { - super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.result = result; + this.input = input; } @Override @@ -113,87 +108,63 @@ @Override public Value getInput() { - return input(0); + return input; } @Override public Value getResult() { - return output(0); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.RegisterHint); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw GraalInternalError.shouldNotReachHere(); + return result; } } public static class LoadOp extends AMD64LIRInstruction { - public LoadOp(Value result, Value address, LIRDebugInfo info) { - super("LOAD", new Value[] {result}, info, new Value[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + @Def({REG}) protected Value result; + @Use({ADDR}) protected Value address; + @State protected LIRFrameState state; + + public LoadOp(Value result, Value address, LIRFrameState state) { + this.result = result; + this.address = address; + this.state = state; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - load(tasm, masm, output(0), (Address) input(0), info); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + load(tasm, masm, result, (Address) address, state); } } public static class StoreOp extends AMD64LIRInstruction { - public StoreOp(Value address, Value input, LIRDebugInfo info) { - super("STORE", LIRInstruction.NO_OPERANDS, info, new Value[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + @Use({ADDR}) protected Value address; + @Use({REG, CONST}) protected Value input; + @State protected LIRFrameState state; + + public StoreOp(Value address, Value input, LIRFrameState state) { + this.address = address; + this.input = input; + this.state = state; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - store(tasm, masm, (Address) input(0), input(1), info); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address); - } else if (mode == OperandMode.Input && index == 1) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } - throw GraalInternalError.shouldNotReachHere(); + store(tasm, masm, (Address) address, input, state); } } public static class LeaOp extends AMD64LIRInstruction { + @Def({REG}) protected Value result; + @Use({ADDR, STACK, UNINITIALIZED}) protected Value address; + public LeaOp(Value result, Value address) { - super("LEA", new Value[] {result}, null, new Value[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.result = result; + this.address = address; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0))); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address, OperandFlag.Stack, OperandFlag.Uninitialized); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + masm.leaq(asLongReg(result), tasm.asAddress(address)); } } @@ -202,7 +173,6 @@ private final int barriers; public MembarOp(final int barriers) { - super("MEMBAR", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); this.barriers = barriers; } @@ -210,57 +180,43 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { masm.membar(barriers); } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - throw GraalInternalError.shouldNotReachHere(); - } } public static class NullCheckOp extends AMD64LIRInstruction { - public NullCheckOp(Variable input, LIRDebugInfo info) { - super("NULL_CHECK", LIRInstruction.NO_OPERANDS, info, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + @Use protected Value input; + @State protected LIRFrameState state; + + public NullCheckOp(Variable input, LIRFrameState state) { + this.input = input; + this.state = state; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - masm.nullCheck(asRegister(input(0))); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + tasm.recordImplicitException(masm.codeBuffer.position(), state); + masm.nullCheck(asRegister(input)); } } + @Opcode("CAS") public static class CompareAndSwapOp extends AMD64LIRInstruction { + @Def protected Value result; + @Use({ADDR}) protected Value address; + @Use protected Value cmpValue; + @Use protected Value newValue; + public CompareAndSwapOp(Value result, Address address, Value cmpValue, Value newValue) { - super("CAS", new Value[] {result}, null, new Value[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.result = result; + this.address = address; + this.cmpValue = cmpValue; + this.newValue = newValue; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2)); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address); - } else if (mode == OperandMode.Input && index == 1) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Input && index == 2) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); + compareAndSwap(tasm, masm, result, (Address) address, cmpValue, newValue); } } @@ -404,7 +360,7 @@ } - public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRDebugInfo info) { + public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRFrameState info) { if (info != null) { tasm.recordImplicitException(masm.codeBuffer.position(), info); } @@ -422,7 +378,7 @@ } } - public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRDebugInfo info) { + public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRFrameState info) { if (info != null) { tasm.recordImplicitException(masm.codeBuffer.position(), info); } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Fri Jun 29 18:33:48 2012 -0700 @@ -108,7 +108,7 @@ public boolean hasDebugInfo() { for (Block b : linearScanOrder()) { for (LIRInstruction op : b.lir) { - if (op.info != null) { + if (op.hasState()) { return true; } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRDebugInfo.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRDebugInfo.java Thu Jun 28 17:39:06 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +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.lir; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; - -/** - * This class represents garbage collection and deoptimization information attached to a LIR instruction. - */ -public class LIRDebugInfo { - public final BytecodeFrame topFrame; - private final VirtualObject[] virtualObjects; - private final List pointerSlots; - public final LabelRef exceptionEdge; - private DebugInfo debugInfo; - - public LIRDebugInfo(BytecodeFrame topFrame, VirtualObject[] virtualObjects, List pointerSlots, LabelRef exceptionEdge) { - this.topFrame = topFrame; - this.virtualObjects = virtualObjects; - this.pointerSlots = pointerSlots; - this.exceptionEdge = exceptionEdge; - } - - public boolean hasDebugInfo() { - return debugInfo != null; - } - - public DebugInfo debugInfo() { - assert debugInfo != null : "debug info not allocated yet"; - return debugInfo; - } - - /** - * Iterates the frame state and calls the {@link ValueProcedure} for every variable. - * - * @param proc The procedure called for variables. - */ - public void forEachState(ValueProcedure proc) { - for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) { - processValues(cur.values, proc); - } - if (virtualObjects != null) { - for (VirtualObject obj : virtualObjects) { - processValues(obj.values(), proc); - } - } - } - - /** - * We filter out constant and illegal values ourself before calling the procedure, so {@link OperandFlag#Constant} and {@link OperandFlag#Illegal} need not be set. - */ - private static final EnumSet STATE_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - - private void processValues(Value[] values, ValueProcedure proc) { - for (int i = 0; i < values.length; i++) { - Value value = values[i]; - if (value instanceof MonitorValue) { - MonitorValue monitor = (MonitorValue) value; - if (processed(monitor.getOwner())) { - monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.Alive, STATE_FLAGS)); - } - - } else if (processed(value)) { - values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS); - } - } - } - - private boolean processed(Value value) { - if (isIllegal(value)) { - // Ignore dead local variables. - return false; - } else if (isConstant(value)) { - // Ignore constants, the register allocator does not need to see them. - return false; - } else if (isVirtualObject(value)) { - assert Arrays.asList(virtualObjects).contains(value); - return false; - } else { - return true; - } - } - - - public void finish(BitSet registerRefMap, BitSet frameRefMap, FrameMap frameMap) { - debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap); - - // Add additional stack slots for outgoing method parameters. - if (pointerSlots != null) { - for (StackSlot v : pointerSlots) { - frameMap.setReference(v, registerRefMap, frameRefMap); - } - } - } - - - @Override - public String toString() { - return debugInfo != null ? debugInfo.toString() : topFrame.toString(); - } -} diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Fri Jun 29 18:33:48 2012 -0700 @@ -0,0 +1,129 @@ +/* + * 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.lir; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +/** + * This class represents garbage collection and deoptimization information attached to a LIR instruction. + */ +public class LIRFrameState { + public final BytecodeFrame topFrame; + private final VirtualObject[] virtualObjects; + private final List pointerSlots; + public final LabelRef exceptionEdge; + private DebugInfo debugInfo; + + public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, List pointerSlots, LabelRef exceptionEdge) { + this.topFrame = topFrame; + this.virtualObjects = virtualObjects; + this.pointerSlots = pointerSlots; + this.exceptionEdge = exceptionEdge; + } + + public boolean hasDebugInfo() { + return debugInfo != null; + } + + public DebugInfo debugInfo() { + assert debugInfo != null : "debug info not allocated yet"; + return debugInfo; + } + + /** + * Iterates the frame state and calls the {@link ValueProcedure} for every variable. + * + * @param proc The procedure called for variables. + */ + public void forEachState(ValueProcedure proc) { + for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) { + processValues(cur.values, proc); + } + if (virtualObjects != null) { + for (VirtualObject obj : virtualObjects) { + processValues(obj.values(), proc); + } + } + } + + /** + * We filter out constant and illegal values ourself before calling the procedure, so {@link OperandFlag#CONST} and {@link OperandFlag#ILLEGAL} need not be set. + */ + private static final EnumSet STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK); + + private void processValues(Value[] values, ValueProcedure proc) { + for (int i = 0; i < values.length; i++) { + Value value = values[i]; + if (value instanceof MonitorValue) { + MonitorValue monitor = (MonitorValue) value; + if (processed(monitor.getOwner())) { + monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS)); + } + + } else if (processed(value)) { + values[i] = proc.doValue(value, OperandMode.ALIVE, STATE_FLAGS); + } + } + } + + private boolean processed(Value value) { + if (isIllegal(value)) { + // Ignore dead local variables. + return false; + } else if (isConstant(value)) { + // Ignore constants, the register allocator does not need to see them. + return false; + } else if (isVirtualObject(value)) { + assert Arrays.asList(virtualObjects).contains(value); + return false; + } else { + return true; + } + } + + + public void finish(BitSet registerRefMap, BitSet frameRefMap, FrameMap frameMap) { + debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap); + + // Add additional stack slots for outgoing method parameters. + if (pointerSlots != null) { + for (StackSlot v : pointerSlots) { + frameMap.setReference(v, registerRefMap, frameRefMap); + } + } + } + + + @Override + public String toString() { + return debugInfo != null ? debugInfo.toString() : topFrame.toString(); + } +} diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Fri Jun 29 18:33:48 2012 -0700 @@ -22,8 +22,10 @@ */ package com.oracle.graal.lir; -import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static com.oracle.graal.lir.LIRInstruction.OperandMode.*; +import java.lang.annotation.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -69,6 +71,11 @@ } + public abstract static class StateProcedure { + protected abstract void doState(LIRFrameState state); + } + + /** * Constants denoting how a LIR instruction uses an operand. */ @@ -79,28 +86,64 @@ * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not * modify the register. */ - Input, + USE, /** * The value must have been defined before. It is alive before the instruction and throughout the instruction. A * register assigned to it cannot be assigned to a Temp or Output operand. The value can be used again after the * instruction, so the instruction must not modify the register. */ - Alive, + ALIVE, /** * The value must not have been defined before, and must not be used after the instruction. The instruction can * do whatever it wants with the register assigned to it (or not use it at all). */ - Temp, + TEMP, /** * The value must not have been defined before. The instruction has to assign a value to the register. The * value can (and most likely will) be used after the instruction. */ - Output, + DEF, + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface Use { + OperandFlag[] value() default REG; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface Alive { + OperandFlag[] value() default REG; } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface Temp { + OperandFlag[] value() default REG; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface Def { + OperandFlag[] value() default REG; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface State { + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE, ElementType.FIELD}) + public static @interface Opcode { + String value() default ""; + } + + /** * Flags for an operand. */ @@ -108,83 +151,61 @@ /** * The value can be a {@link RegisterValue}. */ - Register, + REG, /** * The value can be a {@link StackSlot}. */ - Stack, + STACK, /** * The value can be a {@link Address}. */ - Address, + ADDR, /** * The value can be a {@link Constant}. */ - Constant, + CONST, /** * The value can be {@link Value#IllegalValue}. */ - Illegal, + ILLEGAL, /** * The register allocator should try to assign a certain register to improve code quality. * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints. */ - RegisterHint, + HINT, /** * The value can be uninitialized, e.g., a stack slot that has not written to before. This is only * used to avoid false positives in verification code. */ - Uninitialized, + UNINITIALIZED, } + /** * For validity checking of the operand flags defined by instruction subclasses. */ - private static final EnumMap> ALLOWED_FLAGS; + protected static final EnumMap> ALLOWED_FLAGS; static { ALLOWED_FLAGS = new EnumMap<>(OperandMode.class); - ALLOWED_FLAGS.put(OperandMode.Input, EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized)); - ALLOWED_FLAGS.put(OperandMode.Alive, EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized)); - ALLOWED_FLAGS.put(OperandMode.Temp, EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint)); - ALLOWED_FLAGS.put(OperandMode.Output, EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Illegal, OperandFlag.RegisterHint)); + ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED)); + ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED)); + ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, CONST, ILLEGAL, HINT)); + ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, ILLEGAL, HINT)); } /** - * The opcode of this instruction. - */ - protected final Object code; - - /** - * The output operands for this instruction (modified by the register allocator). + * The flags of the base and index value of an address. */ - protected Value[] outputs; - - /** - * The input operands for this instruction (modified by the register allocator). - */ - protected Value[] inputs; + protected static final EnumSet ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL); - /** - * The alive operands for this instruction (modified by the register allocator). - */ - protected Value[] alives; - - /** - * The temp operands for this instruction (modified by the register allocator). - */ - protected Value[] temps; - - /** - * Used to emit debug information. - */ - public final LIRDebugInfo info; + private final LIRInstructionClass instructionClass; /** * Instruction id for register allocation. @@ -192,22 +213,11 @@ private int id; /** - * Constructs a new LIR instruction that has input and temp operands. - * - * @param opcode the opcode of the new instruction - * @param outputs the operands that holds the operation results of this instruction. - * @param info the {@link LIRDebugInfo} info that is to be preserved for the instruction. This will be {@code null} when no debug info is required for the instruction. - * @param inputs the input operands for the instruction. - * @param temps the temp operands for the instruction. + * Constructs a new LIR instruction. */ - public LIRInstruction(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps) { - this.code = opcode; - this.outputs = outputs; - this.inputs = inputs; - this.alives = alives; - this.temps = temps; - this.info = info; - this.id = -1; + public LIRInstruction() { + instructionClass = LIRInstructionClass.get(getClass()); + id = -1; } public abstract void emitCode(TargetMethodAssembler tasm); @@ -222,100 +232,18 @@ } /** - * Gets an input operand of this instruction. - * - * @param index the index of the operand requested. - * @return the {@code index}'th input operand. - */ - protected final Value input(int index) { - return inputs[index]; - } - - /** - * Gets an alive operand of this instruction. - * - * @param index the index of the operand requested. - * @return the {@code index}'th alive operand. - */ - protected final Value alive(int index) { - return alives[index]; - } - - /** - * Gets a temp operand of this instruction. - * - * @param index the index of the operand requested. - * @return the {@code index}'th temp operand. - */ - protected final Value temp(int index) { - return temps[index]; - } - - /** - * Gets the result operand for this instruction. - * - * @return return the result operand - */ - protected final Value output(int index) { - return outputs[index]; - } - - /** * Gets the instruction name. */ - public String name() { - return code.toString(); + public final String name() { + return instructionClass.getOpcode(this); } - public boolean hasOperands() { - return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall(); - } - - private static final EnumSet ADDRESS_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - - private void forEach(Value[] values, OperandMode mode, ValueProcedure proc) { - for (int i = 0; i < values.length; i++) { - assert ALLOWED_FLAGS.get(mode).containsAll(flagsFor(mode, i)); - - Value value = values[i]; - if (isAddress(value)) { - assert flagsFor(mode, i).contains(OperandFlag.Address); - Address address = asAddress(value); - address.setBase(proc.doValue(address.getBase(), mode, ADDRESS_FLAGS)); - address.setIndex(proc.doValue(address.getIndex(), mode, ADDRESS_FLAGS)); - } else { - values[i] = proc.doValue(values[i], mode, flagsFor(mode, i)); - } - } + public final boolean hasOperands() { + return instructionClass.hasOperands() || hasState() || hasCall(); } - public final void forEachInput(ValueProcedure proc) { - forEach(inputs, OperandMode.Input, proc); - } - - public final void forEachAlive(ValueProcedure proc) { - forEach(alives, OperandMode.Alive, proc); - } - - public final void forEachTemp(ValueProcedure proc) { - forEach(temps, OperandMode.Temp, proc); - } - - public final void forEachOutput(ValueProcedure proc) { - forEach(outputs, OperandMode.Output, proc); - } - - public final void forEachState(ValueProcedure proc) { - if (info != null) { - info.forEachState(proc); - - if (this instanceof LIRXirInstruction) { - LIRXirInstruction xir = (LIRXirInstruction) this; - if (xir.infoAfter != null) { - xir.infoAfter.forEachState(proc); - } - } - } + public final boolean hasState() { + return instructionClass.hasState(this); } /** @@ -325,6 +253,31 @@ return this instanceof StandardOp.CallOp; } + + public final void forEachInput(ValueProcedure proc) { + instructionClass.forEachUse(this, proc); + } + + public final void forEachAlive(ValueProcedure proc) { + instructionClass.forEachAlive(this, proc); + } + + public final void forEachTemp(ValueProcedure proc) { + instructionClass.forEachTemp(this, proc); + } + + public final void forEachOutput(ValueProcedure proc) { + instructionClass.forEachDef(this, proc); + } + + public final void forEachState(ValueProcedure proc) { + instructionClass.forEachState(this, proc); + } + + public final void forEachState(StateProcedure proc) { + instructionClass.forEachState(this, proc); + } + /** * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be * assigned to the value. @@ -339,32 +292,9 @@ * @return The non-null value returned by the procedure, or null. */ public Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) { - Value[] hints; - if (mode == OperandMode.Input) { - hints = outputs; - } else if (mode == OperandMode.Output) { - hints = inputs; - } else { - return null; - } - - for (int i = 0; i < hints.length; i++) { - Value result = proc.doValue(hints[i], null, null); - if (result != null) { - return result; - } - } - return null; + return instructionClass.forEachRegisterHint(this, mode, proc); } - /** - * Used by the register allocator to decide which kind of location can be assigned to the operand. - * @param mode The kind of operand. - * @param index The index of the operand. - * @return The flags for the operand. - */ - // TODO (cwimmer) this method will go away when we have named operands, the flags will be specified as annotations instead. - protected abstract EnumSet flagsFor(OperandMode mode, int index); protected void verify() { } @@ -377,72 +307,8 @@ return " " + toString(); } - /** - * Gets the operation performed by this instruction in terms of its operands as a string. - */ - public String operationString() { - StringBuilder buf = new StringBuilder(); - String sep = ""; - if (outputs.length > 1) { - buf.append("("); - } - for (Value output : outputs) { - buf.append(sep).append(output); - sep = ", "; - } - if (outputs.length > 1) { - buf.append(")"); - } - if (outputs.length > 0) { - buf.append(" = "); - } - - if (inputs.length + alives.length != 1) { - buf.append("("); - } - sep = ""; - for (Value input : inputs) { - buf.append(sep).append(input); - sep = ", "; - } - for (Value input : alives) { - buf.append(sep).append(input).append(" ~"); - sep = ", "; - } - if (inputs.length + alives.length != 1) { - buf.append(")"); - } - - if (temps.length > 0) { - buf.append(" ["); - } - sep = ""; - for (Value temp : temps) { - buf.append(sep).append(temp); - sep = ", "; - } - if (temps.length > 0) { - buf.append("]"); - } - return buf.toString(); - } - - protected void appendDebugInfo(StringBuilder buf) { - if (info != null) { - buf.append(" [bci:"); - String sep = ""; - for (BytecodeFrame cur = info.topFrame; cur != null; cur = cur.caller()) { - buf.append(sep).append(cur.getBCI()); - sep = ","; - } - buf.append("]"); - } - } - @Override public String toString() { - StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString()); - appendDebugInfo(buf); - return buf.toString(); + return instructionClass.toString(this); } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Fri Jun 29 18:33:48 2012 -0700 @@ -0,0 +1,608 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir; +import static com.oracle.graal.api.code.ValueUtil.*; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.*; + +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.StateProcedure; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +public class LIRInstructionClass { + // TODO(cwimmer) factor out the common methods of this class and NodeClass into a base class. + + /** + * Interface used by {@link LIRInstructionClass#rescanAllFieldOffsets(CalcOffset)} to determine the offset (in bytes) of a field. + */ + public interface CalcOffset { + long getOffset(Field field); + } + + private static final Unsafe unsafe = getUnsafe(); + + private static Unsafe getUnsafe() { + try { + // this will only fail if graal is not part of the boot class path + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + // nothing to do + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + // currently we rely on being able to use Unsafe... + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } + + static class DefaultCalcOffset implements CalcOffset { + @Override + public long getOffset(Field field) { + return unsafe.objectFieldOffset(field); + } + } + + private static final Class INSTRUCTION_CLASS = LIRInstruction.class; + private static final Class VALUE_CLASS = Value.class; + private static final Class VALUE_ARRAY_CLASS = Value[].class; + private static final Class STATE_CLASS = LIRFrameState.class; + + + private static final ConcurrentHashMap, LIRInstructionClass> classes = new ConcurrentHashMap<>(); + + private final Class< ? > clazz; + private final int directUseCount; + private final long[] useOffsets; + private final EnumSet[] useFlags; + private final int directAliveCount; + private final long[] aliveOffsets; + private final EnumSet[] aliveFlags; + private final int directTempCount; + private final long[] tempOffsets; + private final EnumSet[] tempFlags; + private final int directDefCount; + private final long[] defOffsets; + private final EnumSet[] defFlags; + + private final long[] stateOffsets; + private final long[] dataOffsets; + + private final Map fieldNames; + private final Map> fieldTypes; + + private String opcodeConstant; + private long opcodeOffset; + + @SuppressWarnings("unchecked") + public LIRInstructionClass(Class clazz) { + assert INSTRUCTION_CLASS.isAssignableFrom(clazz); + this.clazz = clazz; + + FieldScanner scanner = new FieldScanner(new DefaultCalcOffset()); + scanner.scan(clazz); + + OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); + directUseCount = mode.scalarOffsets.size(); + useOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); + useFlags = arrayUsingSortedOffsets(mode.flags, useOffsets, new EnumSet[useOffsets.length]); + + mode = scanner.valueAnnotations.get(LIRInstruction.Alive.class); + directAliveCount = mode.scalarOffsets.size(); + aliveOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); + aliveFlags = arrayUsingSortedOffsets(mode.flags, aliveOffsets, new EnumSet[aliveOffsets.length]); + + mode = scanner.valueAnnotations.get(LIRInstruction.Temp.class); + directTempCount = mode.scalarOffsets.size(); + tempOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); + tempFlags = arrayUsingSortedOffsets(mode.flags, tempOffsets, new EnumSet[tempOffsets.length]); + + mode = scanner.valueAnnotations.get(LIRInstruction.Def.class); + directDefCount = mode.scalarOffsets.size(); + defOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); + defFlags = arrayUsingSortedOffsets(mode.flags, defOffsets, new EnumSet[defOffsets.length]); + + stateOffsets = sortedLongCopy(scanner.stateOffsets); + dataOffsets = sortedLongCopy(scanner.dataOffsets); + + fieldNames = scanner.fieldNames; + fieldTypes = scanner.fieldTypes; + + opcodeConstant = scanner.opcodeConstant; + opcodeOffset = scanner.opcodeOffset; + } + + public static void rescanAllFieldOffsets(CalcOffset calc) { + for (LIRInstructionClass nodeClass : classes.values()) { + nodeClass.rescanFieldOffsets(calc); + } + } + + private void rescanFieldOffsets(CalcOffset calc) { + FieldScanner scanner = new FieldScanner(calc); + scanner.scan(clazz); + + OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); + copyInto(useOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); + mode = scanner.valueAnnotations.get(LIRInstruction.Alive.class); + copyInto(aliveOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); + mode = scanner.valueAnnotations.get(LIRInstruction.Temp.class); + copyInto(tempOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); + mode = scanner.valueAnnotations.get(LIRInstruction.Def.class); + copyInto(defOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); + + copyInto(stateOffsets, sortedLongCopy(scanner.stateOffsets)); + copyInto(dataOffsets, sortedLongCopy(scanner.dataOffsets)); + + fieldNames.clear(); + fieldNames.putAll(scanner.fieldNames); + fieldTypes.clear(); + fieldTypes.putAll(scanner.fieldTypes); + + opcodeConstant = scanner.opcodeConstant; + opcodeOffset = scanner.opcodeOffset; + } + + private static void copyInto(long[] dest, long[] src) { + assert dest.length == src.length; + for (int i = 0; i < dest.length; i++) { + dest[i] = src[i]; + } + } + + public static final LIRInstructionClass get(Class c) { + LIRInstructionClass clazz = classes.get(c); + if (clazz != null) { + return clazz; + } + + // We can have a race of multiple threads creating the LIRInstructionClass at the same time. + // However, only one will be put into the map, and this is the one returned by all threads. + clazz = new LIRInstructionClass(c); + LIRInstructionClass oldClazz = classes.putIfAbsent(c, clazz); + if (oldClazz != null) { + return oldClazz; + } else { + return clazz; + } + } + + + private static class OperandModeAnnotation { + public final ArrayList scalarOffsets = new ArrayList<>(); + public final ArrayList arrayOffsets = new ArrayList<>(); + public final Map> flags = new HashMap<>(); + } + + private static class FieldScanner { + public final CalcOffset calc; + + public final Map, OperandModeAnnotation> valueAnnotations; + public final ArrayList stateOffsets = new ArrayList<>(); + public final ArrayList dataOffsets = new ArrayList<>(); + + public final Map fieldNames = new HashMap<>(); + public final Map> fieldTypes = new HashMap<>(); + + private String opcodeConstant; + private long opcodeOffset; + + public FieldScanner(CalcOffset calc) { + this.calc = calc; + + valueAnnotations = new HashMap<>(); + valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); //LIRInstruction.Use.class)); + valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); //LIRInstruction.Alive.class)); + valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); //LIRInstruction.Temp.class)); + valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); //LIRInstruction.Def.class)); + } + + private OperandModeAnnotation getOperandModeAnnotation(Field field) { + OperandModeAnnotation result = null; + for (Entry, OperandModeAnnotation> entry : valueAnnotations.entrySet()) { + Annotation annotation = field.getAnnotation(entry.getKey()); + if (annotation != null) { + assert result == null : "Field has two operand mode annotations: " + field; + result = entry.getValue(); + } + } + return result; + } + + private static EnumSet getFlags(Field field) { + EnumSet result = EnumSet.noneOf(OperandFlag.class); + // Unfortunately, annotations cannot have class hierarchies or implement interfaces, so we have to duplicate the code for every operand mode. + // Unfortunately, annotations cannot have an EnumSet property, so we have to convert from arrays to EnumSet manually. + if (field.isAnnotationPresent(LIRInstruction.Use.class)) { + result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Use.class).value())); + } else if (field.isAnnotationPresent(LIRInstruction.Alive.class)) { + result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Alive.class).value())); + } else if (field.isAnnotationPresent(LIRInstruction.Temp.class)) { + result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Temp.class).value())); + } else if (field.isAnnotationPresent(LIRInstruction.Def.class)) { + result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Def.class).value())); + } else { + GraalInternalError.shouldNotReachHere(); + } + return result; + } + + public void scan(Class clazz) { + if (clazz.getAnnotation(LIRInstruction.Opcode.class) != null) { + opcodeConstant = clazz.getAnnotation(LIRInstruction.Opcode.class).value(); + } + opcodeOffset = -1; + + Class currentClazz = clazz; + do { + for (Field field : currentClazz.getDeclaredFields()) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + + Class< ? > type = field.getType(); + long offset = calc.getOffset(field); + + if (VALUE_CLASS.isAssignableFrom(type)) { + assert Modifier.isProtected(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final or private because it is modified by register allocator: " + field; + OperandModeAnnotation annotation = getOperandModeAnnotation(field); + assert annotation != null : "Field must have operand mode annotation: " + field; + annotation.scalarOffsets.add(offset); + annotation.flags.put(offset, getFlags(field)); + } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) { + OperandModeAnnotation annotation = getOperandModeAnnotation(field); + assert annotation != null : "Field must have operand mode annotation: " + field; + annotation.arrayOffsets.add(offset); + annotation.flags.put(offset, getFlags(field)); + } else if (STATE_CLASS.isAssignableFrom(type)) { + assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; + assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field; + stateOffsets.add(offset); + } else { + assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; + assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field; + dataOffsets.add(offset); + } + fieldNames.put(offset, field.getName()); + fieldTypes.put(offset, type); + + if (field.getAnnotation(LIRInstruction.Opcode.class) != null) { + assert opcodeConstant == null && opcodeOffset == -1 : "Can have only one Opcode definition: " + clazz; + opcodeOffset = offset; + } + } + currentClazz = currentClazz.getSuperclass(); + } while (currentClazz != LIRInstruction.class); + + if (opcodeConstant == null && opcodeOffset == -1) { + opcodeConstant = clazz.getSimpleName(); + if (opcodeConstant.endsWith("Op")) { + opcodeConstant = opcodeConstant.substring(0, opcodeConstant.length() - 2); + } + } + } + } + + private static T[] arrayUsingSortedOffsets(Map map, long[] sortedOffsets, T[] result) { + for (int i = 0; i < sortedOffsets.length; i++) { + result[i] = map.get(sortedOffsets[i]); + } + return result; + } + + private static long[] sortedLongCopy(ArrayList list1) { + Collections.sort(list1); + long[] result = new long[list1.size()]; + for (int i = 0; i < list1.size(); i++) { + result[i] = list1.get(i); + } + return result; + } + + private static long[] sortedLongCopy(ArrayList list1, ArrayList list2) { + Collections.sort(list1); + Collections.sort(list2); + long[] result = new long[list1.size() + list2.size()]; + for (int i = 0; i < list1.size(); i++) { + result[i] = list1.get(i); + } + for (int i = 0; i < list2.size(); i++) { + result[list1.size() + i] = list2.get(i); + } + return result; + } + + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" use["); + for (int i = 0; i < useOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(useOffsets[i]); + } + str.append("] alive["); + for (int i = 0; i < aliveOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(aliveOffsets[i]); + } + str.append("] temp["); + for (int i = 0; i < tempOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(tempOffsets[i]); + } + str.append("] def["); + for (int i = 0; i < defOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(defOffsets[i]); + } + str.append("] state["); + for (int i = 0; i < stateOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(stateOffsets[i]); + } + str.append("] data["); + for (int i = 0; i < dataOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(dataOffsets[i]); + } + str.append("]"); + return str.toString(); + } + + + public final String getOpcode(LIRInstruction obj) { + if (opcodeConstant != null) { + return opcodeConstant; + } + assert opcodeOffset != -1; + return unsafe.getObject(obj, opcodeOffset).toString(); + } + + public final boolean hasOperands() { + return useOffsets.length > 0 || aliveOffsets.length > 0 || tempOffsets.length > 0 || defOffsets.length > 0; + } + + public final boolean hasState(LIRInstruction obj) { + for (int i = 0; i < stateOffsets.length; i++) { + if (getState(obj, stateOffsets[i]) != null) { + return true; + } + } + return false; + } + + public final void forEachUse(LIRInstruction obj, ValueProcedure proc) { + forEach(obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc); + } + + public final void forEachAlive(LIRInstruction obj, ValueProcedure proc) { + forEach(obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc); + } + + public final void forEachTemp(LIRInstruction obj, ValueProcedure proc) { + forEach(obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc); + } + + public final void forEachDef(LIRInstruction obj, ValueProcedure proc) { + forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc); + } + + public final void forEachState(LIRInstruction obj, ValueProcedure proc) { + for (int i = 0; i < stateOffsets.length; i++) { + LIRFrameState state = getState(obj, stateOffsets[i]); + if (state != null) { + state.forEachState(proc); + } + } + } + + public final void forEachState(LIRInstruction obj, StateProcedure proc) { + for (int i = 0; i < stateOffsets.length; i++) { + LIRFrameState state = getState(obj, stateOffsets[i]); + if (state != null) { + proc.doState(state); + } + } + } + + private static void forEach(LIRInstruction obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, ValueProcedure proc) { + for (int i = 0; i < offsets.length; i++) { + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); + + if (i < directCount) { + Value value = getValue(obj, offsets[i]); + if (isAddress(value)) { + doAddress(asAddress(value), mode, flags[i], proc); + } else { + setValue(obj, offsets[i], proc.doValue(value, mode, flags[i])); + } + } else { + Value[] values = getValueArray(obj, offsets[i]); + for (int j = 0; j < values.length; j++) { + Value value = values[j]; + if (isAddress(value)) { + doAddress(asAddress(value), mode, flags[i], proc); + } else { + values[j] = proc.doValue(value, mode, flags[i]); + } + } + } + } + } + + private static void doAddress(Address address, OperandMode mode, EnumSet flags, ValueProcedure proc) { + assert flags.contains(OperandFlag.ADDR); + address.setBase(proc.doValue(address.getBase(), mode, LIRInstruction.ADDRESS_FLAGS)); + address.setIndex(proc.doValue(address.getIndex(), mode, LIRInstruction.ADDRESS_FLAGS)); + } + + public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) { + int hintDirectCount = 0; + long[] hintOffsets = null; + if (mode == OperandMode.USE) { + hintDirectCount = directDefCount; + hintOffsets = defOffsets; + } else if (mode == OperandMode.DEF) { + hintDirectCount = directUseCount; + hintOffsets = useOffsets; + } else { + return null; + } + + for (int i = 0; i < hintOffsets.length; i++) { + if (i < hintDirectCount) { + Value hintValue = getValue(obj, hintOffsets[i]); + Value result = proc.doValue(hintValue, null, null); + if (result != null) { + return result; + } + } else { + Value[] hintValues = getValueArray(obj, hintOffsets[i]); + for (int j = 0; j < hintValues.length; j++) { + Value hintValue = hintValues[j]; + Value result = proc.doValue(hintValue, null, null); + if (result != null) { + return result; + } + } + } + } + return null; + } + + private static Value getValue(LIRInstruction obj, long offset) { + return (Value) unsafe.getObject(obj, offset); + } + + private static void setValue(LIRInstruction obj, long offset, Value value) { + unsafe.putObject(obj, offset, value); + } + + private static Value[] getValueArray(LIRInstruction obj, long offset) { + return (Value[]) unsafe.getObject(obj, offset); + } + + private static LIRFrameState getState(LIRInstruction obj, long offset) { + return (LIRFrameState) unsafe.getObject(obj, offset); + } + + + public String toString(LIRInstruction obj) { + StringBuilder result = new StringBuilder(); + + appendValues(result, obj, "", " = ", "(", ")", new String[] {""}, defOffsets); + result.append(getOpcode(obj).toUpperCase()); + appendValues(result, obj, " ", "", "(", ")", new String[] {"", "~"}, useOffsets, aliveOffsets); + appendValues(result, obj, " ", "", "{", "}", new String[] {""}, tempOffsets); + + for (int i = 0; i < dataOffsets.length; i++) { + if (dataOffsets[i] == opcodeOffset) { + continue; + } + result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i])); + } + + for (int i = 0; i < stateOffsets.length; i++) { + LIRFrameState state = getState(obj, stateOffsets[i]); + if (state != null) { + result.append(" ").append(fieldNames.get(stateOffsets[i])).append(" [bci:"); + String sep = ""; + for (BytecodeFrame cur = state.topFrame; cur != null; cur = cur.caller()) { + result.append(sep).append(cur.getBCI()); + sep = ", "; + } + result.append("]"); + } + } + + return result.toString(); + } + + private void appendValues(StringBuilder result, LIRInstruction obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]...moffsets) { + int total = 0; + for (long[] offsets : moffsets) { + total += offsets.length; + } + if (total == 0) { + return; + } + + result.append(start); + if (total > 1) { + result.append(startMultiple); + } + String sep = ""; + for (int i = 0; i < moffsets.length; i++) { + long[] offsets = moffsets[i]; + + for (int j = 0; j < offsets.length; j++) { + result.append(sep).append(prefix[i]); + long offset = offsets[j]; + if (total > 1) { + result.append(fieldNames.get(offset)).append(": "); + } + result.append(getFieldString(obj, offset)); + sep = ", "; + } + } + if (total > 1) { + result.append(endMultiple); + } + result.append(end); + } + + private String getFieldString(Object obj, long offset) { + Class type = fieldTypes.get(offset); + if (type == int.class) { + return String.valueOf(unsafe.getInt(obj, offset)); + } else if (type == long.class) { + return String.valueOf(unsafe.getLong(obj, offset)); + } else if (type == boolean.class) { + return String.valueOf(unsafe.getBoolean(obj, offset)); + } else if (type == float.class) { + return String.valueOf(unsafe.getFloat(obj, offset)); + } else if (type == double.class) { + return String.valueOf(unsafe.getDouble(obj, offset)); + } else if (!type.isPrimitive()) { + Object value = unsafe.getObject(obj, offset); + if (!type.isArray()) { + return String.valueOf(value); + } else if (type == int[].class) { + return Arrays.toString((int[]) value); + } else if (type == double[].class) { + return Arrays.toString((double[]) value); + } else if (!type.getComponentType().isPrimitive()) { + return Arrays.toString((Object[]) value); + } + } + assert false : "unhandled field type: " + type; + return ""; + } +} diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Fri Jun 29 18:33:48 2012 -0700 @@ -171,7 +171,7 @@ } else if (isAllocatableRegister(value)) { int regNum = asRegister(value).number; - if (mode == OperandMode.Alive) { + if (mode == OperandMode.ALIVE) { curRegistersDefined.set(regNum); } @@ -202,7 +202,7 @@ assert curInstruction != null; variableDefinitions[variableIdx] = curInstruction; assert !curVariablesLive.get(variableIdx); - if (mode == OperandMode.Output) { + if (mode == OperandMode.DEF) { curVariablesLive.set(variableIdx); } @@ -216,7 +216,7 @@ curRegistersDefined.set(regNum); if (beforeRegisterAllocation) { - if (mode == OperandMode.Output) { + if (mode == OperandMode.DEF) { curRegistersLive[regNum] = value; } else { curRegistersLive[regNum] = null; @@ -227,11 +227,11 @@ } private static Value allowed(Object op, Value value, OperandMode mode, EnumSet flags) { - if ((isVariable(value) && flags.contains(OperandFlag.Register)) || - (isRegister(value) && flags.contains(OperandFlag.Register)) || - (isStackSlot(value) && flags.contains(OperandFlag.Stack)) || - (isConstant(value) && flags.contains(OperandFlag.Constant) && mode != OperandMode.Output) || - (isIllegal(value) && flags.contains(OperandFlag.Illegal))) { + if ((isVariable(value) && flags.contains(OperandFlag.REG)) || + (isRegister(value) && flags.contains(OperandFlag.REG)) || + (isStackSlot(value) && flags.contains(OperandFlag.STACK)) || + (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || + (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) { return value; } TTY.println("instruction %s", op); diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java Fri Jun 29 18:33:48 2012 -0700 @@ -23,39 +23,47 @@ package com.oracle.graal.lir; import static com.oracle.graal.api.code.ValueUtil.*; - -import java.util.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import com.oracle.graal.api.meta.*; import com.oracle.max.cri.xir.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; public abstract class LIRXirInstruction extends LIRInstruction { + @Opcode protected final String opcode; + @Def({REG, ILLEGAL}) protected Value outputOperand; + @Alive({REG, CONST, ILLEGAL}) protected Value[] inputs; + @Temp({REG, CONST, ILLEGAL}) protected Value[] temps; + @State protected LIRFrameState state; + @State protected LIRFrameState stateAfter; - public final Value[] originalOperands; + // Defined as Object[] so that the magic processing of Value[] does not complain this field is not annotated. + public final Object[] originalOperands; + public final int outputOperandIndex; public final int[] inputOperandIndices; public final int[] tempOperandIndices; public final XirSnippet snippet; - public final LIRDebugInfo infoAfter; public final LabelRef trueSuccessor; public final LabelRef falseSuccessor; - public LIRXirInstruction(Object opcode, - XirSnippet snippet, + public LIRXirInstruction(XirSnippet snippet, Value[] originalOperands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, - LIRDebugInfo info, - LIRDebugInfo infoAfter, + LIRFrameState state, + LIRFrameState stateAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) { // Note that we register the XIR input operands as Alive, because the XIR specification allows that input operands // are used at any time, even when the temp operands and the actual output operands have already be assigned. - super(opcode, isLegal(outputOperand) ? new Value[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps); - this.infoAfter = infoAfter; + this.opcode = "XIR: " + snippet.template; + this.outputOperand = outputOperand; + this.inputs = inputs; + this.temps = temps; + this.state = state; + this.stateAfter = stateAfter; this.snippet = snippet; this.inputOperandIndices = inputOperandIndices; this.tempOperandIndices = tempOperandIndices; @@ -66,31 +74,16 @@ assert isLegal(outputOperand) || outputOperandIndex == -1; } - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Alive || mode == OperandMode.Temp) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); - } - public Value[] getOperands() { for (int i = 0; i < inputOperandIndices.length; i++) { - originalOperands[inputOperandIndices[i]] = alive(i); + originalOperands[inputOperandIndices[i]] = inputs[i]; } for (int i = 0; i < tempOperandIndices.length; i++) { - originalOperands[tempOperandIndices[i]] = temp(i); + originalOperands[tempOperandIndices[i]] = temps[i]; } if (outputOperandIndex != -1) { - originalOperands[outputOperandIndex] = output(0); + originalOperands[outputOperandIndex] = outputOperand; } - return originalOperands; - } - - @Override - public String name() { - return "XIR: " + snippet.template; + return (Value[]) originalOperands; } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Fri Jun 29 18:33:48 2012 -0700 @@ -22,12 +22,10 @@ */ package com.oracle.graal.lir; -import java.util.*; - +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.asm.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; /** * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR @@ -54,16 +52,11 @@ private final Label label; private final boolean align; - protected LabelOp(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps, Label label, boolean align) { - super(opcode, outputs, info, inputs, alives, temps); + public LabelOp(Label label, boolean align) { this.label = label; this.align = align; } - public LabelOp(Label label, boolean align) { - this("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align); - } - @Override public void emitCode(TargetMethodAssembler tasm) { if (align) { @@ -72,40 +65,25 @@ tasm.asm.bind(label); } - @Override - public String operationString() { - return label.toString() + " " + super.operationString(); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - throw GraalInternalError.shouldNotReachHere(); - } - public Label getLabel() { return label; } } public static class PhiLabelOp extends LabelOp { - public PhiLabelOp(Label label, boolean align, Value[] phiDefinitions) { - super("PHI_LABEL", phiDefinitions, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align); - } + @Def({REG, STACK}) protected Value[] phiDefinitions; - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw GraalInternalError.shouldNotReachHere(); + public PhiLabelOp(Label label, boolean align, Value[] phiDefinitions) { + super(label, align); + this.phiDefinitions = phiDefinitions; } public void markResolved() { - outputs = EMPTY; + phiDefinitions = EMPTY; } public Value[] getPhiDefinitions() { - return outputs; + return phiDefinitions; } } @@ -118,14 +96,11 @@ */ public static class JumpOp extends LIRInstruction { private final LabelRef destination; + @State protected LIRFrameState state; - protected JumpOp(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps, LabelRef destination) { - super(opcode, outputs, info, inputs, alives, temps); + public JumpOp(LabelRef destination, LIRFrameState state) { this.destination = destination; - } - - public JumpOp(LabelRef destination, LIRDebugInfo info) { - this("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, destination); + this.state = state; } @Override @@ -133,40 +108,25 @@ tasm.asm.jmp(destination.label()); } - @Override - public String operationString() { - return destination + " " + super.operationString(); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - throw GraalInternalError.shouldNotReachHere(); - } - public LabelRef destination() { return destination; } } public static class PhiJumpOp extends JumpOp { - public PhiJumpOp(LabelRef destination, Value[] phiInputs) { - super("PHI_JUMP", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, phiInputs, LIRInstruction.NO_OPERANDS, destination); - } + @Alive({REG, STACK, CONST}) protected Value[] phiInputs; - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Alive) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } - throw GraalInternalError.shouldNotReachHere(); + public PhiJumpOp(LabelRef destination, Value[] phiInputs) { + super(destination, null); + this.phiInputs = phiInputs; } public void markResolved() { - alives = EMPTY; + phiInputs = EMPTY; } public Value[] getPhiInputs() { - return alives; + return phiInputs; } } @@ -200,21 +160,15 @@ * In particular, it is not the actual method prologue. */ public static final class ParametersOp extends LIRInstruction { + @Def({REG, STACK}) protected Value[] params; + public ParametersOp(Value[] params) { - super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.params = params; } @Override public void emitCode(TargetMethodAssembler tasm) { // No code to emit. } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw GraalInternalError.shouldNotReachHere(); - } } } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Fri Jun 29 18:33:48 2012 -0700 @@ -159,7 +159,7 @@ return targetMethod; } - public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) { + public void recordExceptionHandlers(int pcOffset, LIRFrameState info) { if (info != null) { if (info.exceptionEdge != null) { if (exceptionInfoList == null) { @@ -170,7 +170,7 @@ } } - public void recordImplicitException(int pcOffset, LIRDebugInfo info) { + public void recordImplicitException(int pcOffset, LIRFrameState info) { // record an implicit exception point if (info != null) { assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset; @@ -180,21 +180,21 @@ } } - public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) { + public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) { DebugInfo debugInfo = info != null ? info.debugInfo() : null; assert lastSafepointPos < posAfter; lastSafepointPos = posAfter; targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true); } - public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) { + public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) { DebugInfo debugInfo = info != null ? info.debugInfo() : null; assert lastSafepointPos < posAfter; lastSafepointPos = posAfter; targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false); } - public void recordSafepoint(int pos, LIRDebugInfo info) { + public void recordSafepoint(int pos, LIRFrameState info) { // safepoints always need debug info DebugInfo debugInfo = info.debugInfo(); assert lastSafepointPos < pos; diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Jun 29 18:33:48 2012 -0700 @@ -432,18 +432,21 @@ LIRInstruction inst = lirInstructions.get(i); out.printf("nr %4d ", inst.id()).print(COLUMN_END); - if (inst.info != null) { + final StringBuilder stateString = new StringBuilder(); + inst.forEachState(new LIRInstruction.StateProcedure() { + @Override + protected void doState(LIRFrameState state) { + if (state.hasDebugInfo()) { + stateString.append(debugInfoToString(state.debugInfo().getBytecodePosition(), state.debugInfo().getRegisterRefMap(), state.debugInfo().getFrameRefMap(), target.arch)); + } else { + stateString.append(debugInfoToString(state.topFrame, null, null, target.arch)); + } + } + }); + if (stateString.length() > 0) { int level = out.indentationLevel(); out.adjustIndentation(-level); - String state; - if (inst.info.hasDebugInfo()) { - state = debugInfoToString(inst.info.debugInfo().getBytecodePosition(), inst.info.debugInfo().getRegisterRefMap(), inst.info.debugInfo().getFrameRefMap(), target.arch); - } else { - state = debugInfoToString(inst.info.topFrame, null, null, target.arch); - } - if (state != null) { - out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(state).print(HOVER_END).print(COLUMN_END); - } + out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(stateString.toString()).print(HOVER_END).print(COLUMN_END); out.adjustIndentation(level); } diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java Fri Jun 29 18:33:48 2012 -0700 @@ -66,12 +66,12 @@ Variable result = gen.newVariable(kind()); switch (operation()) { case ABS: gen.append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); break; - case SQRT: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SQRT, result, input)); break; - case LOG: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG, result, input)); break; - case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG10, result, input)); break; - case SIN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SIN, result, input)); break; - case COS: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.COS, result, input)); break; - case TAN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.TAN, result, input)); break; + case SQRT: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SQRT, result, input)); break; + case LOG: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG, result, input)); break; + case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10, result, input)); break; + case SIN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SIN, result, input)); break; + case COS: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.COS, result, input)); break; + case TAN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.TAN, result, input)); break; default: throw GraalInternalError.shouldNotReachHere(); } gen.setResult(this, result); diff -r e1d5c642d022 -r 141b15521a39 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java Thu Jun 28 17:39:06 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java Fri Jun 29 18:33:48 2012 -0700 @@ -24,32 +24,31 @@ import static com.oracle.graal.api.code.ValueUtil.*; -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; public class AMD64MathIntrinsicOp extends AMD64LIRInstruction { - public enum Opcode { + public enum IntrinsicOpcode { SQRT, SIN, COS, TAN, LOG, LOG10; } - public AMD64MathIntrinsicOp(Opcode opcode, Value result, Value input) { - super(opcode, new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + @Opcode private final IntrinsicOpcode opcode; + @Def protected Value result; + @Use protected Value input; + + public AMD64MathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) { + this.opcode = opcode; + this.result = result; + this.input = input; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Opcode opcode = (Opcode) code; - Value result = output(0); - Value input = input(0); - switch (opcode) { case SQRT: masm.sqrtsd(asDoubleReg(result), asDoubleReg(input)); break; case LOG: masm.flog(asDoubleReg(result), asDoubleReg(input), false); break; @@ -60,14 +59,4 @@ default: throw GraalInternalError.shouldNotReachHere(); } } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw GraalInternalError.shouldNotReachHere(); - } }