# HG changeset patch # User Gilles Duboscq # Date 1341246025 -7200 # Node ID a8c6104ef526daa830e54f65d0e211b5b2e6720b # Parent c84c75339af1cb99ad9ae11c24fde7ff93898d3f# Parent dba56a3344ba1505670942997511e359a6d8df29 Merge diff -r c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java Mon Jul 02 18:20:25 2012 +0200 @@ -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 c84c75339af1 -r a8c6104ef526 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 Mon Jul 02 16:53:12 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java Mon Jul 02 18:20:25 2012 +0200 @@ -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(); - } } diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/build.xml Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project com.oracle.graal.visualizer.logviewer. + + diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/manifest.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/manifest.mf Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.oracle.graal.visualizer.logviewer +OpenIDE-Module-Layer: com/oracle/graal/visualizer/logviewer/layer.xml +OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/logviewer/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/nbproject/build-impl.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/build-impl.xml Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/nbproject/genfiles.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/genfiles.properties Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=979ec129 +build.xml.script.CRC32=1c914106 +build.xml.stylesheet.CRC32=a56c6a5b@2.47.2 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=979ec129 +nbproject/build-impl.xml.script.CRC32=712ab216 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.2 diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/nbproject/project.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/project.properties Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/nbproject/project.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/project.xml Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,146 @@ + + + org.netbeans.modules.apisupport.project + + + com.oracle.graal.visualizer.logviewer + + + + com.oracle.graal.visualizer.editor + + + + 1.0 + + + + com.oracle.graal.visualizer.sharedactions + + + + 1.0 + + + + com.sun.hotspot.igv.data + + + + 1.0 + + + + org.eclipse.draw2d + + + + 1.0 + + + + org.jdesktop.layout + + + + 1 + 1.19.1 + + + + org.netbeans.api.visual + + + + 2.30.1 + + + + org.netbeans.modules.options.api + + + + 1 + 1.24.1 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.40.1 + + + + org.openide.actions + + + + 6.24.1 + + + + org.openide.awt + + + + 7.39.1 + + + + org.openide.dialogs + + + + 7.23.1 + + + + org.openide.loaders + + + + 7.32.1 + + + + org.openide.nodes + + + + 7.25.1 + + + + org.openide.util + + + + 8.19.1 + + + + org.openide.util.lookup + + + + 8.11.1 + + + + org.openide.windows + + + + 6.39.1 + + + + + com.oracle.graal.visualizer.logviewer + + + + diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/nbproject/suite.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/suite.properties Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/.. diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,1 @@ +com.oracle.graal.visualizer.logviewer.LogCompilationViewerFactory \ No newline at end of file diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/Bundle.properties Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=LogViewer diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewer.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer; + +import com.oracle.graal.visualizer.logviewer.scene.LogScene; +import com.oracle.graal.visualizer.editor.CompilationViewer; +import com.sun.hotspot.igv.data.InputGraph; +import java.awt.Component; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; + +class LogCompilationViewer implements CompilationViewer { + + private LogScene scene; + + public LogCompilationViewer() { + this.scene = new LogScene(); + } + + @Override + public Lookup getLookup() { + return Lookups.fixed(); + } + + @Override + public Component getComponent() { + return scene; + } +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewerFactory.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer; + +import com.oracle.graal.visualizer.editor.CompilationViewer; +import com.oracle.graal.visualizer.editor.SplitCompilationViewerFactory; +import com.sun.hotspot.igv.data.InputGraph; + +public class LogCompilationViewerFactory extends SplitCompilationViewerFactory { + + @Override + public String getName() { + return "Log"; + } + + @Override + protected CompilationViewer createViewer(InputGraph graph) { + return new LogCompilationViewer(); + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/layer.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/layer.xml Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogLine.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model; + +public class LogLine { + + private final int lineNum; + private final CharSequence text; + private final Method method; + private final Scope scope; + private final Node node; + + LogLine(int lineNum, CharSequence text, Method method, Scope scope, Node node) { + this.lineNum = lineNum; + this.text = text; + this.method = method; + this.scope = scope; + this.node = node; + } + + /** + * Returns the number of the line in the log file + * @return file line number + */ + public int getLineNumber() { + return lineNum; + } + + /** + * Returns the text of the log line + * @return log line text + */ + public String getText() { + return text.toString(); + } + + /** + * Returns the parent method + * @return the parent method + */ + public Method getMethod() { + return method; + } + + /** + * Returns the parent scope + * @return the parent scope + */ + public Scope getScope() { + return scope; + } + + /** + * Returns the parent node + * @return the parent node (or null if the log is not in a node's context) + */ + public Node getNode() { + return node; + } + + /** + * The string representation of a log line is the text of it. + */ + @Override + public String toString() { + return getText(); + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogModel.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.NoSuchElementException; + +public class LogModel { + + private List methods = new ArrayList<>(); + private List logs = new ArrayList<>(); + + void add(Method method) { + methods.add(method); + } + + /** + * Returns a list of all methods within the log model. + * @return list of methods + */ + public List getMethods() { + return Collections.unmodifiableList(methods); + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs + * @return list of log lines + */ + public List getLogs() { + return Collections.unmodifiableList(logs); + } + + /** + * Returns a list of logs which are before and after a specific log line (and the line itself). + * @param log reference log line + * @param pre number of lines before the reference line + * @param post number of lines after the reference line + * @return list of log lines (size: pre + post + 1) + */ + public List range(LogLine log, int pre, int post) { + if(log == null) throw new NoSuchElementException(); + + List logs = getLogs(); + int index = logs.indexOf(log); + + if(index == -1) throw new NoSuchElementException(); + + int fromIndex = index - pre; + int toIndex = index + post + 1; + + return getLogs().subList(fromIndex > 0 ? fromIndex : 0, toIndex < logs.size() ? toIndex : logs.size()); + } + + /** + * Returns a string with log l which are before and after a specific log line (and the line itself). + * @param log reference log line + * @param pre number of lines before the reference line + * @param post number of lines after the reference line + * @return list of log lines (size: pre + post + 1) + */ + public String rangeAsString(LogLine log, int pre, int post) { + List list = range(log, pre, post); + + String ls = System.getProperty("line.separator"); + + boolean first = true; + StringBuilder buf = new StringBuilder(); + for(LogLine line : list) { + if(!first) buf.append(ls); + else first = false; + + buf.append(line); + } + + return buf.toString(); + } + + public LogLine getLogLine(int lineNum) { + int index = lineNum; + if(index >= logs.size()) index = logs.size()-1; + + LogLine logLine = logs.get(lineNum); + while(logLine.getLineNumber() > lineNum) { + logLine = logs.get(--index); + } + while(logLine.getLineNumber() < lineNum) { + logLine = logs.get(++index); + } + + return logLine; + } + + public List range(int lineNum, int pre, int post) { + LogLine logLine = getLogLine(lineNum); + return range(logLine, pre, post); + } + + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogParser.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model; + +import com.oracle.graal.visualizer.logviewer.model.io.FileLine; +import com.oracle.graal.visualizer.logviewer.model.io.ProgressMonitor; +import com.oracle.graal.visualizer.logviewer.model.io.SeekableFile; +import com.oracle.graal.visualizer.logviewer.model.io.SeekableFileReader; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LogParser { + + private static final Pattern METHOD_PATTERN = + Pattern.compile("Finished target method HotSpotMethod<(.+?)>, isStub (true|false)"); + private static final Pattern SCOPE_PATTERN = + Pattern.compile("scope: (.+?)"); + private static final Pattern NODE_PATTERN = + Pattern.compile(".*?([0-9]+)\\|([0-9a-zA-Z.]+).*?"); + + private final List errorListeners = new ArrayList<>(); + private final List errors = new ArrayList<>(); + + /** + * Parses a log file without any feedback. When the parsing process is finished, the method returns a LogModel-object. + * @param file log file + * @return model-object + * @throws IOException + * @throws LogParserException + */ + public LogModel parse(File file) throws IOException { + return parse(file, null); + } + + /** + * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object. + * @param file log file + * @param monitor monitor for progress monitoring (uses default gap) + * @return model-object + * @throws IOException + * @throws LogParserException + */ + public LogModel parse(File file, ProgressMonitor monitor) throws IOException { + return parse(file, monitor, SeekableFileReader.DEFAULT_GAP); + } + + /** + * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object. + * @param file log file + * @param monitor monitor for progress monitoring (uses custom gap) + * @param gap custom gap (every x bytes read from the file, the monitor will be informed) + * @return model-object + * @throws IOException + * @throws LogParserException + */ + public LogModel parse(File file, ProgressMonitor monitor, int gap) throws IOException { + errors.clear(); + SeekableFileReader reader = new SeekableFileReader(file, monitor, gap); + SeekableFile seekableFile = reader.getSeekableFile(); + BufferedReader r = new BufferedReader(reader); + + LogModel model = new LogModel(); + Method currentMethod = new Method(model); + Scope currentScope = null; + + Matcher matcher; + boolean methodNameSet = false; + + int lineNum = -1; + String line; + while((line = r.readLine()) != null) { + lineNum++; + + methodNameSet = false; + + matcher = SCOPE_PATTERN.matcher(line); + if(matcher.matches()) { + String name = matcher.group(1); + currentScope = new Scope(name, currentMethod); + currentMethod.add(currentScope); + } + + matcher = METHOD_PATTERN.matcher(line); + boolean methodPatternMatches = matcher.matches(); + + if(methodPatternMatches){ + currentScope = null; + String name = matcher.group(1); + boolean isStub = Boolean.parseBoolean(matcher.group(2)); + currentMethod.init(name, isStub); + model.add(currentMethod); + methodNameSet = true; + } + + Node currentNode = null; + matcher = NODE_PATTERN.matcher(line); + if(matcher.matches()) { + if(currentScope == null){ + raiseError(lineNum, line, "scope is missing"); + continue; + } + int number = Integer.parseInt(matcher.group(1)); + currentNode = currentScope.getNode(number); + if(currentNode == null) { + String name = matcher.group(2); + currentNode = new Node(number, name, currentScope); + currentScope.add(currentNode); + } + } + + FileLine fileLine = seekableFile.get(lineNum); + LogLine log = new LogLine(lineNum, fileLine, currentMethod, currentScope, currentNode); + if(currentNode != null) currentNode.add(log); + if(currentScope != null) currentScope.add(log); + currentMethod.add(log); + model.add(log); + + if(methodPatternMatches) { + currentMethod = new Method(model); + } + } + + if(!methodNameSet) raiseError(lineNum, line, "unexpected end of stream"); + + return model; + } + + private void raiseError(int lineNum, String line, String message) { + ParseError error = new ParseError(lineNum, line, message); + errors.add(error); + for(ParseErrorListener listener : errorListeners) { + listener.errorOccurred(error); + } + } + + /** + * Adds a ParseErrorListener to the listeners + * @param listener + */ + public void addParseErrorListener(ParseErrorListener listener) { + errorListeners.add(listener); + } + + public void removeParseErrorListener(ParseErrorListener listener) { + errorListeners.remove(listener); + } + + /** + * Checks if errors occurred during the parsing process + * @return true if there are errors stored, false otherwise + */ + public boolean hasErrors() { + return !errors.isEmpty(); + } + + /** + * Returns a list of all errors. + * @return error list + */ + public List getErrors() { + return Collections.unmodifiableList(errors); + } + + public static class ParseError { + + private final int lineNum; + private final String line; + private final String message; + + private ParseError(int lineNum, String line, String message) { + this.lineNum = lineNum; + this.message = message; + this.line = line; + } + + public int getLineNumber() { + return lineNum; + } + + public String getLine() { + return line; + } + + public String getMessage() { + return message; + } + + } + + public static interface ParseErrorListener { + + /** + * Called when a new error occurs.

+ * Attention: This method runs on the same thread as the parsing process. + * If time-consuming tasks should be executed, please consider multithreading. + * @param error + */ + public void errorOccurred(ParseError error); + + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Method.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Method.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Method { + + private String name; + private boolean isStub; + private final LogModel model; + private List scopes = new ArrayList<>(); + private List logs = new ArrayList<>(); + + Method(LogModel model) { + name = null; + isStub = false; + this.model = model; + } + + void init(String name, boolean isStub) { + this.name = name; + this.isStub = isStub; + } + + /** + * Returns the name of the method + * @return the method name + */ + public String getName() { + return name; + } + + /** + * Returns true if this is a stub method. + * @return true if is stub, false otherwise + */ + public boolean isStub() { + return isStub; + } + + /** + * Returns the model which holds this method. + * @return model-object + */ + public LogModel getModel() { + return model; + } + + void add(Scope scope) { + scopes.add(scope); + } + + /** + * Returns a list of all scopes inside a target method. + * @return list of scopes + */ + public List getScopes() { + return scopes; + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs in the context of the method. + * @return list of log lines + */ + public List getLogs() { + return Collections.unmodifiableList(logs); + } + + /** + * The string representation of a method is its name. + */ + @Override + public String toString() { + return getName(); + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Node.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Node.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Node { + + private final int number; + private final String name; + private final Scope scope; + private List logs = new ArrayList<>(); + + + Node(int number, String name, Scope scope) { + this.number = number; + this.name = name; + this.scope = scope; + } + + /** + * Returns the node number. + * @return the node number + */ + public int getNumber() { + return number; + } + + /** + * Returns the node name. + * @return the node name + */ + public String getName() { + return name; + } + + /** + * Returns the parent scope. + * @return the parent scope + */ + public Scope getScope() { + return scope; + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs within a nodes context. + * @return list of log lines + */ + public List getLogs() { + return Collections.unmodifiableList(logs); + } + + /** + * The string represenation of a node is "<name> (<number>)". + */ + @Override + public String toString() { + return getName() + "(" + getNumber() + ")"; + } +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Scope.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Scope.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Scope { + + private final String name; + private final Method method; + private List nodes = new ArrayList<>(); + private List logs = new ArrayList<>(); + + Scope(String name, Method method) { + this.name = name; + this.method = method; + } + + /** + * Returns the scope name. + * @return the scope name + */ + public String getName() { + return name; + } + + /** + * Returns the parent method. + * @return the parent method + */ + public Method getMethod() { + return method; + } + + void add(Node node) { + nodes.add(node); + } + + /** + * Returns a list of all node-objects inside a scope. + * @return list of nodes + */ + public List getNodes() { + return Collections.unmodifiableList(nodes); + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs inside a scope. + * @return list of log lines + */ + public List getLogs() { + return logs; + } + + /** + * Returns the node inside a scope with the given number. + * @param number node number + * @return node-object + */ + public Node getNode(int number) { + for(Node node : nodes) { + if(node.getNumber() == number) return node; + } + return null; + } + + /** + * The string representation of a scope is its name. + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getName(); + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/Filter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/Filter.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.filter; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; + +public interface Filter { + + /** + * Sets the constraints for a filter.
+ * They can be every type of objects. In general these are strings, but it can also be + * a Integer (like in the NodeFilter):
+ * Filter nodeFilter = filterManager.getNodeFilter(); + * filter.setConstraints((String)nodeName, (Integer)nodeNumber); + * @param constraints filter constraints + */ + void setConstraints(Object ... constraints); + + /** + * Indicates whether to keep a log line in the filter results, or not. + * @param line log line which should be checked + * @return true if the line should be kept, false otherwise + */ + boolean keep(LogLine line); + + /** + * Activates or deactivates a filter. Deactivated filters will be ignored. + * @param active true to activate, false to deactivate + */ + void setActive(boolean active); + + /** + * Returns the activation status + * @return true for an active filter, false otherwise + */ + boolean isActive(); + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FilterManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FilterManager.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.filter; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import com.oracle.graal.visualizer.logviewer.model.LogModel; +import java.util.ArrayList; +import java.util.List; + +public class FilterManager { + + private final List filters = new ArrayList<>(); + private final Filter methodFilter, scopeFilter, nodeFilter, fulltextFilter; + + /** + * Creates a new instance of the filter manager. + */ + public FilterManager() { + add(methodFilter = new MethodFilter()); + add(scopeFilter = new ScopeFilter()); + add(nodeFilter = new NodeFilter()); + add(fulltextFilter = new FullTextFilter()); + } + + /** + * Executes a filtering process with the given log model as subject. Inactive filters will be ignored. + * @param model subject + * @return filtered list of log lines + * @throws InterruptedException + */ + public List execute(LogModel model) throws InterruptedException { + List input = model.getLogs(); + List output = new ArrayList<>(); + + for(LogLine line : input) { + if(Thread.interrupted()) throw new InterruptedException(); + if(keep(line)) output.add(line); + } + + if(Thread.interrupted()) throw new InterruptedException(); + + return output; + } + + private boolean keep(LogLine line) { + boolean keep = true; + for(Filter filter : filters) { + keep = keep && (!filter.isActive() || filter.keep(line)); + } + return keep; + } + + private Filter add(Filter filter) { + filters.add(filter); + return filter; + } + + /** + * Returns the instance of a method filter + * @return method filter + */ + public Filter getMethodFilter() { + return methodFilter; + } + + /** + * Returns the instance of a scope filter + * @return scope filter + */ + public Filter getScopeFilter() { + return scopeFilter; + } + + /** + * Returns the instance of a node filter + * @return node filter + */ + public Filter getNodeFilter() { + return nodeFilter; + } + + /** + * Returns the instance of a full text filter + * @return full text filter + */ + public Filter getFullTextFilter() { + return fulltextFilter; + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FullTextFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FullTextFilter.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.filter; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class FullTextFilter implements Filter { + + private Pattern p; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + } + + @Override + public boolean keep(LogLine line) { + if(p == null) return true; + + Matcher matcher = p.matcher(line.getText()); + return matcher.find(); + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/MethodFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/MethodFilter.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.filter; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class MethodFilter implements Filter { + + private Pattern p; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + } + + @Override + public boolean keep(LogLine line) { + if(p == null) return true; + + Matcher matcher = p.matcher(line.getMethod().getName()); + return matcher.find(); + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/NodeFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/NodeFilter.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.filter; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class NodeFilter implements Filter { + + private Pattern p; + private Integer nodeNum; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.nodeNum = null; + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + else if(constraint instanceof Integer) { + this.nodeNum = (Integer)constraint; + } + + } + + @Override + public boolean keep(LogLine line) { + if(p == null && nodeNum == null) return true; + + if(line.getNode() == null) return false; + + boolean keep = false; + + if(p != null) { + Matcher matcher = p.matcher(line.getNode().getName()); + keep = keep || matcher.find(); + } + if(nodeNum != null) { + keep = keep || nodeNum.equals(line.getNode().getNumber()); + } + + return keep; + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/ScopeFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/ScopeFilter.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.filter; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class ScopeFilter implements Filter { + + private Pattern p; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + } + + @Override + public boolean keep(LogLine line) { + if(p == null) return true; + + if(line.getScope() == null) return false; + + Matcher matcher = p.matcher(line.getScope().getName()); + return matcher.find(); + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/FileLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/FileLine.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.io; + +import java.io.IOException; +import java.lang.ref.WeakReference; + +public class FileLine implements CharSequence { + + private final SeekableFile seekableFile; + private WeakReference cache; + public final long off; + public final int len; + + public FileLine(SeekableFile seekableFile, long off, int len) { + this.seekableFile = seekableFile; + this.off = off; + this.len = len; + } + + @Override + public String toString() { + String line = null; + + if(cache != null) line = cache.get(); + + if(line == null) { + try { + line = seekableFile.read(this); + cache = new WeakReference<>(line); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return line; + } + + @Override + public int length() { + return len; + } + + @Override + public char charAt(int index) { + String line = toString(); + return line != null ? line.charAt(index) : 0; + } + + @Override + public CharSequence subSequence(int start, int end) { + String line = toString(); + return line != null ? line.subSequence(start, end) : ""; + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/ProgressMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/ProgressMonitor.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.io; + +public interface ProgressMonitor { + + /** + * Triggered when some work has been done.

+ * Attention: This method runs on the same thread as the reading process. + * If time-consuming tasks should be executed, please consider multithreading. + * @param percentage Value in range between 0 and 1 to indicate how much work has been done. + */ + public void worked(float percentage); + + /** + * Triggered when work is done completely.

+ * Attention: This method runs on the same thread as the reading process. + * If time-consuming tasks should be executed, please consider multithreading. + */ + public void finished(); + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFile.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.io; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +public class SeekableFile implements Closeable { + + private final RandomAccessFile raf; + private List lines = new ArrayList<>(); + + SeekableFile(File file) throws FileNotFoundException { + raf = new RandomAccessFile(file, "r"); + } + + void addLine(long off, int len) { + lines.add(new FileLine(this, off, len)); + } + + public int size() { + return lines.size(); + } + + public FileLine get(int lineNum) throws IOException { + FileLine line = lines.get(lineNum); + return line; + } + + String read(FileLine line) throws IOException { + if(line == null) throw new IllegalArgumentException("line is null"); + raf.seek(line.off); + + byte [] buf = new byte[line.len]; + + if(raf.read(buf) != line.len) throw new IOException("error while reading line"); + + return new String(buf); + } + + @Override + public void close() throws IOException { + raf.close(); + } + + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFileReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFileReader.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.model.io; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +public class SeekableFileReader extends Reader { + + public static final int DEFAULT_GAP = 1024; // in bytes + + private final FileReader reader; + private SeekableFile seekableFile; + private ProgressMonitor monitor; + private long filelen; + private int gap; + + public SeekableFileReader(File file) throws IOException { + super(file); + reader = new FileReader(file); + seekableFile = new SeekableFile(file); + } + + public SeekableFileReader(File file, ProgressMonitor monitor, int gap) throws IOException { + this(file); + this.monitor = monitor; + this.filelen = file.length(); + this.gap = gap; + } + + public SeekableFileReader(File file, ProgressMonitor monitor) throws IOException { + this(file, monitor, DEFAULT_GAP); + } + + public SeekableFile getSeekableFile() { + return seekableFile; + } + + @Override + public void close() throws IOException { + reader.close(); + } + + private long bytes = 0; + private boolean skipLF = false; + private long off; + private long lastGapped = 0; + private boolean finished = false; + + @Override + public int read(char[] cbuf, int offset, int length) throws IOException { + + int l = reader.read(cbuf, offset, length); + + if(l == -1 && !finished) { + seekableFile.addLine(off, (int)(bytes-off)); + finished = true; + if(monitor != null) { + monitor.worked(1); + monitor.finished(); + } + } + + for(int i = 0; i < l; ++i) { + Character ch = new Character(cbuf[i]); + int chlen = ch.toString().getBytes(reader.getEncoding()).length; + + if(skipLF && ch != '\n') { + seekableFile.addLine(off, (int)(bytes-off-chlen)); + off = bytes; + skipLF = false; + } + + bytes += chlen; + + if(monitor != null) { + if(bytes > lastGapped+gap) { + lastGapped = bytes; + monitor.worked(((float)bytes)/((float)filelen)); + } + } + + if(ch == '\r') { + skipLF = true; + } + if(ch == '\n') { + seekableFile.addLine(off, (int)(bytes-off-(skipLF ? 2*chlen : chlen))); + off = bytes; + skipLF = false; + } + } + + return l; + } + + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkDialog.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.scene; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; +import javax.swing.*; + +public class BookmarkDialog extends JDialog { + + private JList lstBookmarks; + private List logLines; + + public BookmarkDialog(List bookmarks, Window parent) { + super(parent, JDialog.ModalityType.APPLICATION_MODAL); + + this.logLines = bookmarks; + + DefaultListModel mdlBookmarks = new DefaultListModel(); + lstBookmarks = new JList(mdlBookmarks); + JScrollPane jspBookmarks = new JScrollPane(lstBookmarks); + + for (LogLine bookmark : bookmarks) { + mdlBookmarks.addElement(bookmark.getLineNumber() + ": Method " + bookmark.getMethod() + " - Scope " + bookmark.getScope() + " - " + bookmark.getText()); + } + + JButton btnOk = new JButton("Go to"); + JButton btnCancel = new JButton("Cancel"); + + // init listeners + lstBookmarks.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + close(); + } + } + }); + + btnOk.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + if (lstBookmarks.isSelectionEmpty()) + return; + close(); + } + }); + btnCancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + lstBookmarks.clearSelection(); + close(); + } + }); + + // build layout + JPanel pnlButtons = new JPanel(); + + pnlButtons.setLayout(new GridLayout(1, 2)); + pnlButtons.add(btnOk); + pnlButtons.add(btnCancel); + + this.setLayout(new BorderLayout()); + this.add(jspBookmarks, BorderLayout.CENTER); + this.add(pnlButtons, BorderLayout.SOUTH); + + this.pack(); + this.setMinimumSize(new Dimension(600, this.getPreferredSize().height)); + this.setLocationRelativeTo(parent); + this.setResizable(false); + this.setVisible(true); + } + + public LogLine getTarget() { + if (lstBookmarks.isSelectionEmpty()) + return null; + return logLines.get(lstBookmarks.getSelectedIndex()); + } + + private void close() { + this.setVisible(false); + this.dispose(); + } +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkableLogViewer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkableLogViewer.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.scene; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; +import org.openide.util.Exceptions; + +public class BookmarkableLogViewer extends JPanel { + + private static final Color BOOKMARK_COLOR = Color.CYAN; + + private static final Highlighter.HighlightPainter BOOKMARK_PAINTER = + new DefaultHighlighter.DefaultHighlightPainter(BOOKMARK_COLOR); + + private JTextPane txpText; + private JTextPane txpLines; + private Highlighter textHighlighter; + private Highlighter lineHighlighter; + private FontMetrics fm; + private Map bookmarks = new TreeMap<>(); + private List logLines = new ArrayList<>(); + + public BookmarkableLogViewer() { + init(); + } + + private void init() { + txpText = new JTextPane(); + txpLines = new JTextPane(); + + // needed for correct layouting + Insets ins = txpLines.getInsets(); + txpLines.setMargin(new Insets(ins.top + 1, ins.left, ins.bottom, ins.right)); + + textHighlighter = new BookmarkHighlighter(); + lineHighlighter = new BookmarkHighlighter(); + + txpText.setHighlighter(textHighlighter); + //txpText.setMinimumSize(new Dimension(100, 100)); + txpText.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); + txpText.setEditable(false); + + txpLines.setHighlighter(lineHighlighter); + txpLines.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); + txpLines.setBackground(Color.LIGHT_GRAY); + txpLines.setEnabled(false); + txpLines.setForeground(Color.BLACK); + txpLines.addMouseListener(mouseInputListener); + + fm = txpText.getFontMetrics(txpText.getFont()); + + JPanel pnlBookmarks = new JPanel(); + pnlBookmarks.setLayout(new BorderLayout()); + pnlBookmarks.add(txpText, BorderLayout.CENTER); + + JScrollPane jspBookmarks = new JScrollPane(pnlBookmarks); + jspBookmarks.setRowHeaderView(txpLines); + jspBookmarks.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + jspBookmarks.getVerticalScrollBar().setUnitIncrement(15); + + this.setLayout(new BorderLayout()); + this.add(jspBookmarks, BorderLayout.CENTER); + } + + public int getCurrentlyDisplayedTopLine() { + Rectangle view = txpText.getVisibleRect(); + return getAbsoluteLine((int) Math.ceil(view.y/fm.getHeight())); + } + + public int getCurrentTopLine() { + return logLines.get(0).getLineNumber(); + } + + public int getCurrentBottomLine() { + return logLines.get(logLines.size()-1).getLineNumber(); + } + + public void clearLogLines() { + this.logLines = new ArrayList<>(); + txpText.setText(""); + txpLines.setText(""); + clearHighlighter(); + } + + public void setLogLines(List logLines) { + this.logLines = logLines; + + clearHighlighter(); + clearLineNumbers(); + String text = ""; + for (int i = 0; i < logLines.size(); i++) { + text += logLines.get(i).getText(); + if (i < logLines.size() - 1) { + text += "\n"; + } + } + txpText.setText(text); + setLineNumbers(); + + txpText.setCaretPosition(0); + txpLines.setCaretPosition(0); + + for (int bookmark : bookmarks.keySet()) { + if (bookmark < logLines.get(0).getLineNumber()) { + continue; + } + if (bookmark > logLines.get(logLines.size() - 1).getLineNumber()) { + break; + } + + int line = getRelativeLine(bookmark); + + addHighlight(logLines.get(line)); + } + } + + public void setLogLines(List logLines, int focus) { + setLogLines(logLines); + + //does not work for some reason - jtextpane jumps to caret position afterwards + //moveToBookmark(focus); + + //workaround - set caret position bevore moving + Rectangle visible = txpText.getVisibleRect(); + int visibleLines = (int)(Math.ceil(visible.height/fm.getHeight())); + + String text = txpText.getText(); + int line = logLines.get(0).getLineNumber(); + for (int i = 0; i < text.length(); i++) { + if (text.charAt(i) == '\n') + line++; + if (line == focus+visibleLines || i == text.length() - 1) { + txpText.setCaretPosition(i); + break; + } + } + moveToBookmark(focus); + } + + public List getBookmarkedLines() { + List lines = new ArrayList<>(); + for (int bookmark : bookmarks.keySet()) { + lines.add(bookmarks.get(bookmark).logLine); + } + return lines; + } + + public int tryLastBookmark() { + int line = getCurrentlyDisplayedTopLine(); + + int firstShownLine = getCurrentTopLine(); + + int bookmarkKey = -1; + for (int key : bookmarks.keySet()) { + if (key >= line) { + break; + } + + bookmarkKey = key; + } + + if (bookmarkKey >= firstShownLine) { + moveToBookmark(bookmarkKey); + return -1; + } + + return bookmarkKey; + } + + public int tryNextBookmark() { + Rectangle visible = txpText.getVisibleRect(); + int lastLine = (int) Math.floor((visible.y + visible.height) / fm.getHeight()); + lastLine = getAbsoluteLine(lastLine); + + int lastShownLine = getCurrentBottomLine(); + + int bookmarkKey = -1; + for (int key : bookmarks.keySet()) { + if (key > lastLine) { + bookmarkKey = key; + break; + } + if (key > lastShownLine) { + break; + } + } + + if (bookmarkKey > 0 && bookmarkKey <= lastShownLine) { + moveToBookmark(bookmarkKey); + return -1; + } + + return bookmarkKey; + } + + private void moveToBookmark(int line) { + int relLine = getRelativeLine(line); + Rectangle visible = txpText.getVisibleRect(); + Rectangle position = new Rectangle(0, relLine * fm.getHeight(), visible.width, visible.height); + txpText.scrollRectToVisible(position); + } + + private int getAbsoluteLine(int line) { + return logLines.get(0).getLineNumber() + line; + } + + private int getRelativeLine(int line) { + return line - logLines.get(0).getLineNumber(); + } + + private int getStartOffset(JTextComponent component, int line) { + return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset(); + } + + private int getEndOffset(JTextComponent component, int line) { + return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset(); + } + + private void addHighlight(LogLine logLine) { + try { + int line = logLine.getLineNumber(); + int relativeLine = getRelativeLine(line); + + Object hl1 = textHighlighter.addHighlight(getStartOffset(txpText, relativeLine), getEndOffset(txpText, relativeLine), BOOKMARK_PAINTER); + Object hl2 = lineHighlighter.addHighlight(getStartOffset(txpLines, relativeLine), getEndOffset(txpLines, relativeLine), BOOKMARK_PAINTER); + bookmarks.put(line, new Bookmark(logLine, hl1, hl2)); + } catch (BadLocationException ex) { + Exceptions.printStackTrace(ex); + } + } + + private void removeHighlight(int line) { + int abs = getAbsoluteLine(line); + Bookmark bookmark = bookmarks.get(abs); + textHighlighter.removeHighlight(bookmark.hl1); + lineHighlighter.removeHighlight(bookmark.hl2); + bookmarks.remove(abs); + } + + public void clearBookmarks() { + bookmarks = new TreeMap<>(); + clearHighlighter(); + } + + private void clearHighlighter() { + textHighlighter.removeAllHighlights(); + lineHighlighter.removeAllHighlights(); + } + + private void clearLineNumbers() { + txpLines.setText(""); + } + + private void setLineNumbers() { + clearLineNumbers(); + + if (logLines.isEmpty()) { + return; + } + + int colCnt = String.valueOf(logLines.get(logLines.size() - 1).getLineNumber()).length() + 2; + + int firstNr = logLines.get(0).getLineNumber(); + String text = String.format("%" + colCnt + "s", firstNr + " "); + for (int i = 1; i < logLines.size(); i++) { + text += "\n"; + text += String.format("%" + colCnt + "s", (firstNr + i) + " "); + } + txpLines.setText(text); + } + + private MouseListener mouseInputListener = new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent me) { + if (txpLines.getText().length() == 0) { + return; + } + if (me.getClickCount() == 2) { + int caretPos = txpLines.getCaretPosition(); + + int lineOffset = txpLines.getDocument().getDefaultRootElement().getElementIndex(caretPos); + if (txpLines.getText().charAt(caretPos - 1) == '\n') { + lineOffset--; + } + + if (bookmarks.containsKey(getAbsoluteLine(lineOffset))) { + removeHighlight(lineOffset); + } else { + addHighlight(logLines.get(lineOffset)); + } + } + } + }; + + class Bookmark { + + public final LogLine logLine; + public final Object hl1; + public final Object hl2; + + public Bookmark(LogLine logLine, Object hl1, Object hl2) { + this.logLine = logLine; + this.hl1 = hl1; + this.hl2 = hl2; + } + } + + class BookmarkHighlighter extends DefaultHighlighter { + + private JTextComponent component; + + @Override + public void install(JTextComponent component) { + super.install(component); + this.component = component; + } + + @Override + public void deinstall(JTextComponent component) { + super.deinstall(component); + this.component = null; + } + + @Override + public void paint(Graphics g) { + Highlighter.Highlight[] highlights = getHighlights(); + + for (int i = 0; i < highlights.length; i++) { + Highlighter.Highlight hl = highlights[i]; + Rectangle bg = component.getBounds(); + Insets insets = component.getInsets(); + bg.x = insets.left; + bg.y = insets.top; + bg.height = insets.top + insets.bottom; + Highlighter.HighlightPainter painter = hl.getPainter(); + painter.paint(g, hl.getStartOffset(), hl.getEndOffset(), bg, component); + } + } + } +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/ImportLogErrorDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/ImportLogErrorDialog.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.scene; + +import com.oracle.graal.visualizer.logviewer.model.LogParser; +import java.awt.Component; +import java.util.List; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +public class ImportLogErrorDialog { + + public static void showDialog(Component parent, List errors) { + JTextArea txaErrors = new JTextArea(); + + for (LogParser.ParseError error : errors) { + txaErrors.append("Error at line " + error.getLineNumber()); + txaErrors.append(": " + error.getMessage()); + txaErrors.append("\n"); + txaErrors.append("Log line: " + error.getLine()); + txaErrors.append("\n"); + } + + JScrollPane scpErrors = new JScrollPane(txaErrors); + + JOptionPane.showMessageDialog(parent, scpErrors, "Parse errors", JOptionPane.ERROR_MESSAGE); + } +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/LogScene.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/LogScene.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,671 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.scene; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; +import com.oracle.graal.visualizer.logviewer.model.LogModel; +import com.oracle.graal.visualizer.logviewer.model.LogParser; +import com.oracle.graal.visualizer.logviewer.model.filter.Filter; +import com.oracle.graal.visualizer.logviewer.model.filter.FilterManager; +import com.oracle.graal.visualizer.logviewer.model.io.ProgressMonitor; +import com.oracle.graal.visualizer.logviewer.scene.model.LogTableModel; +import com.oracle.graal.visualizer.logviewer.scene.model.TableLine; +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.regex.PatternSyntaxException; +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import org.openide.util.Exceptions; +import org.openide.util.NbPreferences; +import sun.awt.CausedFocusEvent; + +public class LogScene extends JPanel { + private static final String PREFERENCE_DIR = "dir"; + + private static final String ICON_PREFIX = "/com/oracle/graal/visualizer/logviewer/scene/icons/"; + private static final String ICON_ARROW_DOWN = ICON_PREFIX + "arrow_down.png"; + private static final String ICON_ARROW_UP = ICON_PREFIX + "arrow_up.png"; + private static final String ICON_BOOKMARK_BACK = ICON_PREFIX + "bookmark_back.png"; + private static final String ICON_BOOKMARK_FWD = ICON_PREFIX + "bookmark_forward.png"; + private static final String ICON_BOOKMARK_LIST = ICON_PREFIX + "bookmark_list.png"; + private static final String ICON_LOAD = ICON_PREFIX + "loading.gif"; + + private static final ImageIcon IMGICON_LOAD = new ImageIcon(LogScene.class.getResource(ICON_LOAD)); + + private static final int LOG_LINES = 50; + private static final int KEYSTROKE_RATE = 100; // rate at which the keystrokes are checked + private static final int KEYSTROKE_TRESHOLD = 400; // time in ms after which a search is triggered + + private FilterManager filterManager; + private Thread filterRunThread; + + private int timeSinceLastKeystroke = -1; + + private JLabel lblMessage; + private JLabel lblIcon; + + private JLabel lblMethodFilter; + private JLabel lblScopeFilter; + private JLabel lblNodeFilter; + private JLabel lblFulltextFilter; + private JTextField txfMethodFilter; + private JTextField txfScopeFilter; + private JTextField txfNodeFilter; + private JTextField txfFulltextFilter; + + private JTable tblResult; + private LogTableModel tblResultModel; + + private BookmarkableLogViewer logViewer; + private JButton btnBookmarkBack; + private JButton btnBookmarkFwd; + private JButton btnBookmarkList; + private JButton btnLoadMoreUp; + private JButton btnLoadMoreDown; + + private LogParser parser = new LogParser(); + private LogModel logModel = null; + private LogStatus logStatus = LogStatus.NO_LOG; + + private static LogScene instance; + + private enum LogStatus { + NO_LOG, LOADING, ACTIVE + } + + public static LogScene getInstance() { + return instance; + } + + public LogScene() { + initComponents(); + } + + private void initComponents() { + filterManager = new FilterManager(); + + lblMessage = new JLabel("No logfile loaded."); + lblIcon = new JLabel(""); + + // Initialize filter components + lblMethodFilter = new JLabel("Target Method:"); + lblScopeFilter = new JLabel("Scope:"); + lblNodeFilter = new JLabel("Node:"); + lblFulltextFilter = new JLabel("Fulltext:"); + + txfMethodFilter = new JTextField(); + txfScopeFilter = new JTextField(); + txfNodeFilter = new JTextField(); + txfFulltextFilter = new JTextField(); + + tblResultModel = new LogTableModel(); + tblResult = new JTable(tblResultModel); + tblResult.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + tblResult.getTableHeader().setReorderingAllowed(false); + tblResult.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + + Dimension dim = tblResult.getPreferredScrollableViewportSize(); + tblResult.setPreferredScrollableViewportSize(new Dimension(dim.width, 10*tblResult.getRowHeight() + tblResult.getTableHeader().getHeight())); + JScrollPane scpTblResult = new JScrollPane(tblResult); + scpTblResult.setMinimumSize(new Dimension(dim.width, 10*tblResult.getRowHeight() + tblResult.getTableHeader().getHeight())); + + logViewer = new BookmarkableLogViewer(); + + btnLoadMoreUp = new JButton(new ImageIcon(LogScene.class.getResource(ICON_ARROW_UP))); + btnLoadMoreDown = new JButton(new ImageIcon(LogScene.class.getResource(ICON_ARROW_DOWN))); + + btnLoadMoreUp.setFocusable(false); + btnLoadMoreUp.setToolTipText("Load more previous log lines"); + + btnLoadMoreDown.setFocusable(false); + btnLoadMoreDown.setToolTipText("Load more following log lines"); + + btnBookmarkBack = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_BACK))); + btnBookmarkList = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_LIST))); + btnBookmarkFwd = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_FWD))); + + btnBookmarkBack.setFocusable(false); + btnBookmarkBack.setToolTipText("Navigate to the last bookmark."); + + btnBookmarkFwd.setFocusable(false); + btnBookmarkFwd.setToolTipText("Navigate to the next bookmark."); + + btnBookmarkList.setFocusable(false); + btnBookmarkList.setToolTipText("List all known bookmarks."); + + JPanel pnl = new JPanel(); + pnl.setLayout(new GridBagLayout()); + pnl.setOpaque(false); + + JPanel logViewerPanel = new JPanel(); + logViewerPanel.setLayout(new GridBagLayout()); + logViewerPanel.setOpaque(false); + + JPanel messagePanel = new JPanel(); + messagePanel.setLayout(new BoxLayout(messagePanel, BoxLayout.LINE_AXIS)); + messagePanel.setOpaque(false); + + // Initialize Listeners + initListeners(); + + // Layout components + GridBagConstraints gbc = new GridBagConstraints(); + + messagePanel.add(lblMessage); + messagePanel.add(Box.createHorizontalGlue()); + messagePanel.add(lblIcon); + + Insets standardInsets = gbc.insets; + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1; + gbc.weighty = 0; + gbc.gridwidth = 2; + gbc.insets = new Insets(2, 0, 2, 0); + pnl.add(messagePanel, gbc); + + gbc.fill = GridBagConstraints.NONE; + gbc.gridwidth = 1; + gbc.weightx = 0; + gbc.weighty = 0; + gbc.gridy++; + gbc.insets = standardInsets; + pnl.add(lblMethodFilter, gbc); + + gbc.gridy++; + pnl.add(lblScopeFilter, gbc); + + gbc.gridy++; + pnl.add(lblNodeFilter, gbc); + + gbc.gridy++; + pnl.add(lblFulltextFilter, gbc); + + gbc.gridx++; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 0.75; + pnl.add(txfMethodFilter, gbc); + + gbc.gridy++; + pnl.add(txfScopeFilter, gbc); + + gbc.gridy++; + pnl.add(txfNodeFilter, gbc); + + gbc.gridy++; + pnl.add(txfFulltextFilter, gbc); + + gbc.gridx = 0; + //gbc.gridy++; + gbc.gridwidth = 2; + gbc.weightx = 1; + gbc.anchor = GridBagConstraints.FIRST_LINE_START; + //pnl.add(btnSearch, gbc); + + gbc.gridy++; + pnl.add(scpTblResult, gbc); + + gbc.gridy++; + gbc.weighty = 1; + gbc.fill = GridBagConstraints.BOTH; + pnl.add(logViewerPanel, gbc); + + gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridheight = 6; + gbc.weightx = 1; + gbc.weighty = 1; + gbc.fill = GridBagConstraints.BOTH; + logViewerPanel.add(logViewer, gbc); + + gbc.gridx++; + gbc.weightx = 0; + gbc.weighty = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.PAGE_START; + gbc.gridheight = 1; + logViewerPanel.add(btnLoadMoreUp, gbc); + + gbc.gridy++; + logViewerPanel.add(btnLoadMoreDown, gbc); + + gbc.gridy++; + logViewerPanel.add(Box.createRigidArea(btnLoadMoreUp.getSize())); + + gbc.gridy++; + logViewerPanel.add(btnBookmarkBack, gbc); + + gbc.gridy++; + logViewerPanel.add(btnBookmarkFwd, gbc); + + gbc.gridy++; + logViewerPanel.add(btnBookmarkList, gbc); + + this.setLayout(new BorderLayout()); + this.add(pnl, BorderLayout.CENTER); + + Timer keyTimer = new Timer(); + keyTimer.scheduleAtFixedRate(new KeystrokeTimer(), KEYSTROKE_RATE, KEYSTROKE_RATE); + + LogScene.instance = this; + } + + private void initListeners() { + txfMethodFilter.addKeyListener(new FilterKeyListener()); + txfScopeFilter.addKeyListener(new FilterKeyListener()); + txfNodeFilter.addKeyListener(new FilterKeyListener()); + txfFulltextFilter.addKeyListener(new FilterKeyListener()); + + txfMethodFilter.addFocusListener(new FilterFocusListener()); + txfScopeFilter.addFocusListener(new FilterFocusListener()); + txfNodeFilter.addFocusListener(new FilterFocusListener()); + txfFulltextFilter.addFocusListener(new FilterFocusListener()); + + btnLoadMoreUp.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int line = logViewer.getCurrentlyDisplayedTopLine(); + int top = logViewer.getCurrentTopLine(); + int bottom = logViewer.getCurrentBottomLine(); + logViewer.setLogLines(logModel.range(line, line - top + LOG_LINES, bottom - line), line); + } + }); + + btnLoadMoreDown.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int line = logViewer.getCurrentlyDisplayedTopLine(); + int top = logViewer.getCurrentTopLine(); + int bottom = logViewer.getCurrentBottomLine(); + logViewer.setLogLines(logModel.range(line, line - top, bottom - line + LOG_LINES), line); + } + }); + + btnBookmarkBack.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int result = logViewer.tryLastBookmark(); + if (result >= 0) { + tblResult.clearSelection(); + logViewer.setLogLines(logModel.range(result, LOG_LINES, LOG_LINES), result); + } + } + }); + + btnBookmarkFwd.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int result = logViewer.tryNextBookmark(); + if (result >= 0) { + tblResult.clearSelection(); + logViewer.setLogLines(logModel.range(result, LOG_LINES, LOG_LINES), result); + } + } + }); + + btnBookmarkList.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + List bookmarkedLines = logViewer.getBookmarkedLines(); + if (bookmarkedLines.size() > 0) { + BookmarkDialog bd = new BookmarkDialog(bookmarkedLines, null); + if (bd.getTarget() != null) { + LogLine target = bd.getTarget(); + int line = target.getLineNumber(); + logViewer.setLogLines(logModel.range(line, LOG_LINES, LOG_LINES), line); + } + } else { + JOptionPane.showMessageDialog(LogScene.this, "No bookmarks set.", "", JOptionPane.INFORMATION_MESSAGE); + } + } + }); + + tblResult.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent lse) { + if (tblResult.getSelectedRow() == -1) { + logViewer.clearLogLines(); + return; + } + + TableLine selectedLine = tblResultModel.getTableLine(tblResult.getSelectedRow()); + int firstLine = selectedLine.getFirstLine(); + int lastLine = selectedLine.getLastLine(); + + if (firstLine == lastLine) { + // only display selected line + List line = new ArrayList<>(); + line.add(selectedLine.getLogLine()); + logViewer.setLogLines(line); + } else { + // display selected range + int pre = firstLine==lastLine?LOG_LINES:selectedLine.getLogLine().getLineNumber()-firstLine; + int post = firstLine==lastLine?LOG_LINES:lastLine-selectedLine.getLogLine().getLineNumber(); + + logViewer.setLogLines(logModel.range(selectedLine.getLogLine(), pre, post)); + } + } + }); + } + + private boolean executeFilters() { + if (logStatus == LogStatus.NO_LOG) { + loadLogFile(); + return false; + } + if (logStatus == LogStatus.LOADING) { + return false; + } + + boolean execute = trySetFilter(filterManager.getMethodFilter(), txfMethodFilter.getText().trim(), lblMethodFilter); + execute = trySetFilter(filterManager.getScopeFilter(), txfScopeFilter.getText().trim(), lblScopeFilter) || execute; + try { + // node number + int node = Integer.parseInt(txfNodeFilter.getText().trim()); + execute = trySetFilter(filterManager.getNodeFilter(), node, lblNodeFilter) || execute; + } catch (Exception e) { + // node name + execute = trySetFilter(filterManager.getNodeFilter(), txfNodeFilter.getText().trim(), lblNodeFilter) || execute; + } + execute = trySetFilter(filterManager.getFullTextFilter(), txfFulltextFilter.getText().trim(), lblFulltextFilter) || execute; + + if (!execute) + return true; + + tryInterruptFilter(); + + filterRunThread = new Thread(new Runnable() { + + @Override + public void run() { + try { + List result = filterManager.execute(logModel); + lblIcon.setIcon(null); + + if (!Thread.interrupted()) + buildTableEntries(result); + } catch (InterruptedException e) { + } + } + + }); + lblIcon.setIcon(IMGICON_LOAD); + filterRunThread.start(); + + return true; + } + + private boolean trySetFilter(Filter filter, Object constraint, JLabel marker) { + try { + filter.setConstraints(constraint); + marker.setForeground(Color.BLACK); + return constraint != null && (!(constraint instanceof String) || (constraint instanceof String && ((String)constraint).trim().length() > 0)); + } catch (PatternSyntaxException e) { + filter.setConstraints(new Object[]{}); + marker.setForeground(Color.RED); + return false; + } + } + + private void tryInterruptFilter() { + if (filterRunThread != null && (filterRunThread.isAlive() || !filterRunThread.isInterrupted())) { + lblIcon.setIcon(null); + filterRunThread.interrupt(); + } + } + + private void buildTableEntries(List filterResult) { + List tableEntries; + + int methodLength = txfMethodFilter.getText().trim().length(); + int scopeLength = txfScopeFilter.getText().trim().length(); + int nodeLength = txfNodeFilter.getText().trim().length(); + int fulltextLength = txfFulltextFilter.getText().trim().length(); + + boolean preventGrouping = nodeLength != 0 || fulltextLength != 0; + + if (!preventGrouping && methodLength > 0 && scopeLength == 0) { + tableEntries = groupByMethod(filterResult); + } else if (!preventGrouping && scopeLength > 0) { + tableEntries = groupByScope(filterResult); + } else { + tableEntries = showAllLines(filterResult); + } + + tblResultModel.setLogEntries(tableEntries); + + int width = 0; + for (int i = 0; i < tableEntries.size(); i++) { + TableCellRenderer tcr = tblResult.getCellRenderer(i, 0); + Component c = tcr.getTableCellRendererComponent(tblResult, tblResultModel.getValueAt(i, 0), false, false, i, 0); + if (c instanceof JLabel) { + JLabel l = (JLabel) c; + FontMetrics fm = l.getFontMetrics(l.getFont()); + width = Math.max(width, fm.stringWidth(l.getText())); + } + } + + // proper resizing of column + // setWidth and setPreferredWidth do not trigger resize + TableColumn col = tblResult.getColumnModel().getColumn(0); + col.setMinWidth(width+5); + col.setMaxWidth(width+5); + + // reenable resizing for user + col.setMinWidth(0); + col.setMaxWidth(999); + } + + private List groupByMethod(List filterResult) { + List tableEntries = new ArrayList<>(); + int firstLine = -1; + for (int i = 0; i < filterResult.size(); i++) { + LogLine line = filterResult.get(i); + + if (firstLine < 0) + firstLine = line.getLineNumber(); + + if (i < filterResult.size() - 1) { + LogLine next = filterResult.get(i+1); + if (line.getMethod() != next.getMethod()) { + tableEntries.add(new TableLine(line, firstLine)); + firstLine = next.getLineNumber(); + } + } else { + tableEntries.add(new TableLine(line, firstLine)); + } + } + return tableEntries; + } + + private List groupByScope(List filterResult) { + List tableEntries = new ArrayList<>(); + LogLine firstScopeLine = null; + for (int i = 0; i < filterResult.size(); i++) { + LogLine line = filterResult.get(i); + + if (firstScopeLine == null) + firstScopeLine = line; + + if (i < filterResult.size() - 1) { + LogLine next = filterResult.get(i+1); + if (line.getScope() != next.getScope()) { + tableEntries.add(new TableLine(firstScopeLine, line.getLineNumber())); + firstScopeLine = next; + } + } else { + tableEntries.add(new TableLine(firstScopeLine, line.getLineNumber())); + } + } + return tableEntries; + } + + private List showAllLines(List filterResult) { + List tableEntries = new ArrayList<>(); + for (LogLine line : filterResult) { + tableEntries.add(new TableLine(line)); + } + return tableEntries; + } + + public void loadLogFile() { + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(new javax.swing.filechooser.FileFilter() { + + @Override + public boolean accept(File f) { + return f.isDirectory() || + f.getName().toLowerCase().endsWith(".txt") || + f.getName().toLowerCase().endsWith(".log"); + } + + @Override + public String getDescription() { + return "Log files (*.txt, *.log)"; + } + }); + fc.setCurrentDirectory(new File(NbPreferences.forModule(LogScene.class).get(PREFERENCE_DIR, "~"))); + fc.setDialogTitle("Load log file"); + + if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + tryInterruptFilter(); + + final File file = fc.getSelectedFile(); + + NbPreferences.forModule(LogScene.class).put(PREFERENCE_DIR, file.getParent()); + + lblIcon.setIcon(IMGICON_LOAD); + logStatus = LogStatus.LOADING; + new Thread(new Runnable(){ + + @Override + public void run() { + try { + logModel = parser.parse(file, new LoadProgressMonitor(lblMessage, "Loading file " + file.getName() + "...")); + lblIcon.setIcon(null); + lblMessage.setText("Current logfile: " + file.getName()); + logStatus = LogStatus.ACTIVE; + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + }).start(); + } + } + + private class FilterKeyListener extends KeyAdapter { + @Override + public void keyTyped(KeyEvent e) { + tryInterruptFilter(); + timeSinceLastKeystroke = 0; + } + } + + private class FilterFocusListener implements FocusListener { + private boolean ignore = false; + + @Override + public void focusGained(FocusEvent fe) { + if (!ignore && logStatus == LogStatus.NO_LOG) { + ignore = true; + loadLogFile(); + } + } + + @Override + public void focusLost(FocusEvent fe) { + if (fe instanceof CausedFocusEvent) { + CausedFocusEvent cfe = (CausedFocusEvent) fe; + ignore = ignore && // don't change ignore to true if it is already false + cfe.getCause() == CausedFocusEvent.Cause.ACTIVATION; // ACTIVATION is triggered if the + // FileChooser is opened + } + } + + } + + private class KeystrokeTimer extends TimerTask { + @Override + public void run() { + if (timeSinceLastKeystroke < 0) + return; + + timeSinceLastKeystroke += KEYSTROKE_RATE; + + if (timeSinceLastKeystroke >= KEYSTROKE_TRESHOLD) { + int save = timeSinceLastKeystroke; + timeSinceLastKeystroke = -1; // needs to be set to -1 to prevent + // multiple parallel filter execution + + if (!executeFilters()) + timeSinceLastKeystroke = save; + } + } + } + + private class LoadProgressMonitor implements ProgressMonitor { + private String staticText; + private JLabel lblStatus; + + public LoadProgressMonitor(JLabel lblStatus, String staticText) { + this.lblStatus = lblStatus; + this.staticText = staticText; + + lblStatus.setText(staticText); + } + + @Override + public void worked(float percentage) { + int perc = Math.round(percentage*100); + lblStatus.setText(staticText + " (" + perc + " %)"); + } + + @Override + public void finished() { + if (parser.hasErrors()) { + if (JOptionPane.showConfirmDialog(LogScene.this, "Parsing log file finished with errors. Show error messages?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { + List errors = parser.getErrors(); + ImportLogErrorDialog.showDialog(LogScene.this, errors); + } + } + } + + }; +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/actions/ImportLogAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/actions/ImportLogAction.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.scene.actions; + +import com.oracle.graal.visualizer.logviewer.scene.LogScene; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.logviewer.scene.actions.ImportLogActions", category = "File") +@ActionRegistration(displayName = "Import Log", iconBase = "com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png") +@ActionReference(path = "Menu/File", position = 600) +public class ImportLogAction implements ActionListener { + + @Override + public void actionPerformed(ActionEvent ae) { + LogScene.getInstance().loadLogFile(); + } +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_down.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_down.png has changed diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_up.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_up.png has changed diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_back.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_back.png has changed diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_forward.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_forward.png has changed diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_list.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_list.png has changed diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png has changed diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/loading.gif Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/loading.gif has changed diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/LogTableModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/LogTableModel.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.scene.model; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.table.AbstractTableModel; + +public class LogTableModel extends AbstractTableModel { + private final static String[] columnNames = {"Line #", "Method", "Scope", "Node", "Log Text"}; + + private List entries = new ArrayList<>(); + + public void setLogEntries(List entries) { + this.entries = entries; + fireTableDataChanged(); + } + + public TableLine getTableLine(int line) { + return entries.get(line); + } + + @Override + public int getRowCount() { + return entries.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public String getColumnName(int column) { + return columnNames[column]; + } + + @Override + public Object getValueAt(int i, int i1) { + switch (i1) { + case 0: + return entries.get(i).getLineNr(); + case 1: + return entries.get(i).getLogLine().getMethod().getName(); + case 2: + return entries.get(i).getLogLine().getScope()!=null? + entries.get(i).getLogLine().getScope().getName():""; + case 3: + return entries.get(i).getLogLine().getNode()!=null? + entries.get(i).getLogLine().getNode().getName():""; + case 4: + return entries.get(i).getLogLine().getText(); + } + return null; + } + +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/TableLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/TableLine.java Mon Jul 02 18:20:25 2012 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.oracle.graal.visualizer.logviewer.scene.model; + +import com.oracle.graal.visualizer.logviewer.model.LogLine; + +public class TableLine { + + private int lineNr; + private LogLine logLine; + + // display single log line + public TableLine(LogLine logLine) { + this(logLine, logLine.getLineNumber()); + } + + // display line number range (from logLine to lineNr or vice versa) + public TableLine(LogLine logLine, int lineNr) { + this.logLine = logLine; + this.lineNr = lineNr; + } + + public int getFirstLine() { + return lineNr < logLine.getLineNumber()?lineNr:logLine.getLineNumber(); + } + + public int getLastLine() { + return lineNr > logLine.getLineNumber()?lineNr:logLine.getLineNumber(); + } + + public String getLineNr() { + if (lineNr == logLine.getLineNumber()) { + return String.valueOf(lineNr); + } + return getFirstLine() + "-" + getLastLine(); + } + + public LogLine getLogLine() { + return logLine; + } +} diff -r c84c75339af1 -r a8c6104ef526 visualizer/nbproject/project.properties --- a/visualizer/nbproject/project.properties Mon Jul 02 16:53:12 2012 +0200 +++ b/visualizer/nbproject/project.properties Mon Jul 02 18:20:25 2012 +0200 @@ -1,48 +1,50 @@ -app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif -app.name=graalvisualizer -app.title=Graal Visualizer -branding.token=${app.name} -modules=\ - ${project.com.sun.hotspot.igv.graph}:\ - ${project.com.sun.hotspot.igv.filter}:\ - ${project.com.sun.hotspot.igv.hierarchicallayout}:\ - ${project.com.sun.hotspot.igv.layout}:\ - ${project.com.sun.hotspot.igv.data}:\ - ${project.com.sun.hotspot.igv.view}:\ - ${project.com.sun.hotspot.igv.bytecodes}:\ - ${project.com.sun.hotspot.igv.difference}:\ - ${project.com.sun.hotspot.igv.settings}:\ - ${project.com.sun.hotspot.igv.util}:\ - ${project.com.sun.hotspot.igv.svg}:\ - ${project.com.sun.hotspot.igv.filterwindow}:\ - ${project.com.sun.hotspot.igv.graal}:\ - ${project.at.ssw.visualizer.cfg}:\ - ${project.org.eclipse.draw2d}:\ - ${project.com.oracle.graal.visualizer.editor}:\ - ${project.com.oracle.graal.visualizer.outline}:\ - ${project.com.oracle.graal.visualizer.snapshots}:\ - ${project.com.oracle.graal.visualizer.sharedactions} -project.at.ssw.visualizer.cfg=ControlFlowEditor -project.com.oracle.graal.visualizer.editor=Editor -project.com.oracle.graal.visualizer.outline=OutlineView -project.com.oracle.graal.visualizer.sharedactions=SharedActions -project.com.oracle.graal.visualizer.snapshots=SnapshotsView -project.com.sun.hotspot.igv.bytecodes=Bytecodes -project.com.sun.hotspot.igv.data=Data -project.com.sun.hotspot.igv.difference=Difference -project.com.sun.hotspot.igv.filter=Filter -project.com.sun.hotspot.igv.filterwindow=FilterWindow -project.com.sun.hotspot.igv.graal=Graal -project.com.sun.hotspot.igv.graph=Graph -project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout -project.com.sun.hotspot.igv.layout=Layout -project.com.sun.hotspot.igv.settings=Settings -project.com.sun.hotspot.igv.svg=BatikSVGProxy -project.com.sun.hotspot.igv.view=View -project.com.sun.hotspot.igv.util=Util - -project.org.eclipse.draw2d=Draw2DLibrary -# Disable assertions for RequestProcessor to prevent annoying messages in case -# of multiple SceneAnimator update tasks in the default RequestProcessor. -run.args.extra = -J-client -J-da:org.openide.util.RequestProcessor -debug.args.extra = -J-client -J-da:org.openide.util.RequestProcessor +app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif +app.name=graalvisualizer +app.title=Graal Visualizer +branding.token=${app.name} +modules=\ + ${project.com.sun.hotspot.igv.graph}:\ + ${project.com.sun.hotspot.igv.filter}:\ + ${project.com.sun.hotspot.igv.hierarchicallayout}:\ + ${project.com.sun.hotspot.igv.layout}:\ + ${project.com.sun.hotspot.igv.data}:\ + ${project.com.sun.hotspot.igv.view}:\ + ${project.com.sun.hotspot.igv.bytecodes}:\ + ${project.com.sun.hotspot.igv.difference}:\ + ${project.com.sun.hotspot.igv.settings}:\ + ${project.com.sun.hotspot.igv.util}:\ + ${project.com.sun.hotspot.igv.svg}:\ + ${project.com.sun.hotspot.igv.filterwindow}:\ + ${project.com.sun.hotspot.igv.graal}:\ + ${project.at.ssw.visualizer.cfg}:\ + ${project.org.eclipse.draw2d}:\ + ${project.com.oracle.graal.visualizer.editor}:\ + ${project.com.oracle.graal.visualizer.outline}:\ + ${project.com.oracle.graal.visualizer.snapshots}:\ + ${project.com.oracle.graal.visualizer.sharedactions}:\ + ${project.com.oracle.graal.visualizer.logviewer} +project.at.ssw.visualizer.cfg=ControlFlowEditor +project.com.oracle.graal.visualizer.logviewer=LogViewer +project.com.oracle.graal.visualizer.editor=Editor +project.com.oracle.graal.visualizer.outline=OutlineView +project.com.oracle.graal.visualizer.sharedactions=SharedActions +project.com.oracle.graal.visualizer.snapshots=SnapshotsView +project.com.sun.hotspot.igv.bytecodes=Bytecodes +project.com.sun.hotspot.igv.data=Data +project.com.sun.hotspot.igv.difference=Difference +project.com.sun.hotspot.igv.filter=Filter +project.com.sun.hotspot.igv.filterwindow=FilterWindow +project.com.sun.hotspot.igv.graal=Graal +project.com.sun.hotspot.igv.graph=Graph +project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout +project.com.sun.hotspot.igv.layout=Layout +project.com.sun.hotspot.igv.settings=Settings +project.com.sun.hotspot.igv.svg=BatikSVGProxy +project.com.sun.hotspot.igv.view=View +project.com.sun.hotspot.igv.util=Util + +project.org.eclipse.draw2d=Draw2DLibrary +# Disable assertions for RequestProcessor to prevent annoying messages in case +# of multiple SceneAnimator update tasks in the default RequestProcessor. +run.args.extra = -J-client -J-da:org.openide.util.RequestProcessor +debug.args.extra = -J-client -J-da:org.openide.util.RequestProcessor