Mercurial > hg > graal-compiler
changeset 4531:3a309467fc8e
Merge
line wrap: on
line diff
--- a/.hgignore Wed Feb 08 21:13:35 2012 -0800 +++ b/.hgignore Wed Feb 08 21:15:00 2012 -0800 @@ -23,8 +23,8 @@ \.pdf$ \.dot$ \.pyc$ -build.xml -nbproject +^graal/.*/build.xml +^graal/.*/nbproject/ dist ^doc/.*/dot_temp_ ^doc/doxygen/.*$ @@ -36,6 +36,7 @@ /nbproject/private/ ^graal/hotspot/java$ ^scratch/ +^test-output/ scratch/ bin/ ^local/ @@ -43,5 +44,9 @@ ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/ ^src/share/tools/IdealGraphVisualizer/build/ ^src/share/tools/IdealGraphVisualizer/dist/ +^visualizer/[a-zA-Z0-9]*/build/ +^visualizer/build/ +^visualizer/dist/ +^visualizer/nbplatform/ ^.hgtip .DS_Store
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java Wed Feb 08 21:15:00 2012 -0800 @@ -48,6 +48,10 @@ l.patchInstructions(this); } + public abstract void align(int modulus); + + public abstract void jmp(Label l); + protected abstract void patchJumpTarget(int branch, int jumpTarget); protected final void emitByte(int x) {
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/NumUtil.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/NumUtil.java Wed Feb 08 21:15:00 2012 -0800 @@ -98,4 +98,8 @@ assert isShort(v); return (short) v; } + + public static int roundUp(int number, int mod) { + return ((number + mod - 1) / mod) * mod; + } }
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java Wed Feb 08 21:15:00 2012 -0800 @@ -759,6 +759,7 @@ } } + @Override public final void jmp(Label l) { if (l.isBound()) { jmp(l.position(), false); @@ -2876,6 +2877,7 @@ testl(AMD64.rax, new CiAddress(Word, r.asValue(Word), 0)); } + @Override public void align(int modulus) { if (codeBuffer.position() % modulus != 0) { nop(modulus - (codeBuffer.position() % modulus));
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiUtil.java Wed Feb 08 21:15:00 2012 -0800 @@ -728,11 +728,11 @@ return result; } - public static Class<?>[] signatureToTypes(RiSignature signature, RiType accessingClass) { + public static Class<?>[] signatureToTypes(RiSignature signature, RiResolvedType accessingClass) { int count = signature.argumentCount(false); Class<?>[] result = new Class<?>[count]; for (int i = 0; i < result.length; ++i) { - result[i] = ((RiResolvedType) signature.argumentTypeAt(i, accessingClass)).toJava(); + result[i] = signature.argumentTypeAt(i, accessingClass).resolve(accessingClass).toJava(); } return result; }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiSignature.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiSignature.java Wed Feb 08 21:15:00 2012 -0800 @@ -49,7 +49,7 @@ * not care for a resolved type. * @return the {@code index}'th argument type */ - RiType argumentTypeAt(int index, RiType accessingClass); + RiType argumentTypeAt(int index, RiResolvedType accessingClass); /** * Gets the argument kind at the specified position.
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiType.java Wed Feb 08 21:15:00 2012 -0800 @@ -97,4 +97,6 @@ * @return the kind of constants for the specified part of the type */ CiKind getRepresentationKind(Representation r); + + RiResolvedType resolve(RiResolvedType accessingClass); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.simple; + +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.alloc.util.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; + +public abstract class AssignRegisters { + public final LIR lir; + public final FrameMap frameMap; + + public AssignRegisters(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + } + + private CiBitMap curRegisterRefMap; + private CiBitMap curFrameRefMap; + + public void execute() { + ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value); } }; + ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value); } }; + ValueProcedure setReferenceProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setReference(value); } }; + + Debug.log("==== start assign registers ===="); + for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) { + Block block = lir.linearScanOrder().get(i); + Debug.log("start block %s", block); + + curRegisterRefMap = frameMap.initRegisterRefMap(); + curFrameRefMap = frameMap.initFrameRefMap(); + + // Put all values live at the end of the block into the reference map. + locationsForBlockEnd(block).forEachLocation(setReferenceProc); + + for (int j = block.lir.size() - 1; j >= 0; j--) { + LIRInstruction op = block.lir.get(j); + Debug.log(" op %d %s", op.id(), op); + + op.forEachOutput(defProc); + op.forEachTemp(defProc); + op.forEachState(useProc); + op.forEachAlive(useProc); + + if (op.info != null) { + Debug.log(" registerRefMap: %s frameRefMap: %s", curRegisterRefMap, curFrameRefMap); + op.info.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap); + + if (op instanceof LIRXirInstruction) { + LIRXirInstruction xir = (LIRXirInstruction) op; + if (xir.infoAfter != null) { + xir.infoAfter.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap); + } + } + } + + // 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. + op.forEachInput(useProc); + } + Debug.log("end block %s", block); + } + Debug.log("==== end assign registers ===="); + } + + private CiValue use(CiValue value) { + Debug.log(" use %s", value); + if (isLocation(value)) { + CiValue location = asLocation(value).location; + frameMap.setReference(location, curRegisterRefMap, curFrameRefMap); + return location; + } else { + frameMap.setReference(value, curRegisterRefMap, curFrameRefMap); + return value; + } + } + + private CiValue def(CiValue value) { + Debug.log(" def %s", value); + if (isLocation(value)) { + CiValue location = asLocation(value).location; + frameMap.clearReference(location, curRegisterRefMap, curFrameRefMap); + return location; + } else { + frameMap.clearReference(value, curRegisterRefMap, curFrameRefMap); + return value; + } + } + + private CiValue setReference(CiValue value) { + Debug.log(" setReference %s", value); + frameMap.setReference(asLocation(value).location, curRegisterRefMap, curFrameRefMap); + return value; + } + + protected abstract LocationMap locationsForBlockEnd(Block block); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.simple; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.lir.ValueUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; + +public class DataFlowAnalysis { + private final LIR lir; + private final RiRegisterConfig registerConfig; + + public DataFlowAnalysis(LIR lir, RiRegisterConfig registerConfig) { + this.lir = lir; + this.registerConfig = registerConfig; + } + + public void execute() { + numberInstructions(); + backwardDataFlow(); + } + + + private List<Block> blocks() { + return lir.linearScanOrder(); + } + + private int numVariables() { + return lir.numVariables(); + } + + private boolean isAllocatableRegister(CiValue value) { + return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; + } + + + private int[] definitions; + private BitSet[] blockLiveIn; + private Block[] opIdBlock; + private Object[] opIdKilledValues; + + + public BitSet liveIn(Block block) { + return blockLiveIn[block.getId()]; + } + private void setLiveIn(Block block, BitSet liveIn) { + blockLiveIn[block.getId()] = liveIn; + } + + private Block blockOf(int opId) { + return opIdBlock[opId >> 1]; + } + private void setBlockOf(int opId, Block block) { + opIdBlock[opId >> 1] = block; + } + + private Object killedValues(int opId) { + return opIdKilledValues[opId]; + } + private void setKilledValues(int opId, Object killedValues) { + opIdKilledValues[opId] = killedValues; + } + + public void forEachKilled(LIRInstruction op, boolean end, ValueProcedure proc) { + Object entry = killedValues(op.id() + (end ? 1 : 0)); + if (entry == null) { + // Nothing to do + } else if (entry instanceof CiValue) { + CiValue newValue = proc.doValue((CiValue) entry, null, null); + assert newValue == entry : "procedure does not allow to change values"; + } else { + CiValue[] values = (CiValue[]) entry; + for (int i = 0; i < values.length; i++) { + if (values[i] != null) { + CiValue newValue = proc.doValue(values[i], null, null); + assert newValue == values[i] : "procedure does not allow to change values"; + } + } + } + } + + public int definition(Variable value) { + return definitions[value.index]; + } + + /** + * Numbers all instructions in all blocks. The numbering follows the {@linkplain ComputeLinearScanOrder linear scan order}. + */ + private void numberInstructions() { + ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setDef(value); } }; + + int numInstructions = 0; + for (Block block : blocks()) { + numInstructions += block.lir.size(); + } + opIdBlock = new Block[numInstructions]; + opIdKilledValues = new Object[numInstructions << 1]; + definitions = new int[numVariables()]; + + curOpId = 0; + for (Block block : blocks()) { + for (LIRInstruction op : block.lir) { + op.setId(curOpId); + setBlockOf(curOpId, block); + + op.forEachTemp(defProc); + op.forEachOutput(defProc); + + curOpId += 2; // numbering of lirOps by two + } + } + assert curOpId == numInstructions << 1; + } + + private CiValue setDef(CiValue value) { + if (isVariable(value)) { + assert definitions[asVariable(value).index] == 0 : "Variable defined twice"; + definitions[asVariable(value).index] = curOpId; + } + return value; + } + + + private BitSet variableLive; + private BitSet registerLive; + private int curOpId; + + private void backwardDataFlow() { + ValueProcedure inputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } }; + ValueProcedure aliveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } }; + ValueProcedure tempProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, true); } }; + ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, false); } }; + + blockLiveIn = new BitSet[blocks().size()]; + registerLive = new BitSet(); + + Debug.log("==== start backward data flow analysis ===="); + for (int i = blocks().size() - 1; i >= 0; i--) { + Block block = blocks().get(i); + Debug.log("start block %s loop %s", block, block.getLoop()); + + variableLive = new BitSet(); + for (Block sux : block.getSuccessors()) { + BitSet suxLive = liveIn(sux); + if (suxLive != null) { + Debug.log(" sux %s suxLive: %s", sux, suxLive); + variableLive.or(suxLive); + } + } + + assert registerLive.isEmpty() : "no fixed register must be alive before processing a block"; + + for (int j = block.lir.size() - 1; j >= 0; j--) { + LIRInstruction op = block.lir.get(j); + curOpId = op.id(); + Debug.log(" op %d %s variableLive: %s registerLive: %s", curOpId, op, variableLive, registerLive); + + op.forEachOutput(outputProc); + op.forEachTemp(tempProc); + op.forEachState(aliveProc); + op.forEachAlive(aliveProc); + op.forEachInput(inputProc); + } + + assert registerLive.isEmpty() : "no fixed register must be alive after processing a block"; + assert liveIn(block) == null; + setLiveIn(block, variableLive); + + if (block.isLoopHeader()) { + Debug.log(" loop header, propagating live set to loop blocks variableLive: %s", variableLive); + // All variables that are live at the beginning of a loop are also live the whole loop. + // This is guaranteed by the SSA form. + for (Block loop : block.getLoop().blocks) { + BitSet loopLiveIn = liveIn(loop); + assert loopLiveIn != null : "All loop blocks must have been processed before the loop header"; + loopLiveIn.or(variableLive); + Debug.log(" block %s loopLiveIn %s", loop, loopLiveIn); + } + } + + Debug.log("end block %s variableLive: %s", block, variableLive); + } + Debug.log("==== end backward data flow analysis ===="); + } + + private CiValue use(CiValue value, int killOpId) { + Debug.log(" use %s", value); + if (isVariable(value)) { + int variableIdx = asVariable(value).index; + assert definitions[variableIdx] < curOpId; + if (!variableLive.get(variableIdx)) { + Debug.log(" set live variable %d", variableIdx); + variableLive.set(variableIdx); + kill(value, killOpId); + } + + } else if (isAllocatableRegister(value)) { + int regNum = asRegister(value).number; + if (!registerLive.get(regNum)) { + Debug.log(" set live register %d", regNum); + registerLive.set(regNum); + kill(value, killOpId); + } + } + return value; + } + + private CiValue def(CiValue value, boolean isTemp) { + Debug.log(" def %s", value); + if (isVariable(value)) { + int variableIdx = asVariable(value).index; + assert definitions[variableIdx] == curOpId; + if (variableLive.get(variableIdx)) { + Debug.log(" clear live variable %d", variableIdx); + assert !isTemp : "temp variable cannot be used after the operation"; + variableLive.clear(variableIdx); + } else { + // Variable has never been used, so kill it immediately after the definition. + kill(value, curOpId + 1); + } + + } else if (isAllocatableRegister(value)) { + int regNum = asRegister(value).number; + if (registerLive.get(regNum)) { + Debug.log(" clear live register %d", regNum); + assert !isTemp : "temp variable cannot be used after the operation"; + registerLive.clear(regNum); + } else { + // Register has never been used, so kill it immediately after the definition. + kill(value, curOpId + 1); + } + } + return value; + } + + private void kill(CiValue value, int opId) { + if (opId < 0) { + return; + } + if (isVariable(value)) { + int defOpId = definitions[asVariable(value).index]; + assert defOpId > 0 && defOpId <= opId; + + Block defBlock = blockOf(defOpId); + Block useBlock = blockOf(opId); + + if (useBlock.getLoop() != null && useBlock.getLoop() != defBlock.getLoop()) { + // This is a value defined outside of the loop it is currently used in. Therefore, it is live the whole loop + // and is not killed by the current instruction. + Debug.log(" no kill because use in %s, definition in %s", useBlock.getLoop(), defBlock.getLoop()); + return; + } + } + Debug.log(" kill %s at %d", value, opId); + + Object entry = killedValues(opId); + if (entry == null) { + setKilledValues(opId, value); + } else if (entry instanceof CiValue) { + setKilledValues(opId, new CiValue[] {(CiValue) entry, value}); + } else { + CiValue[] killed = (CiValue[]) entry; + for (int i = 0; i < killed.length; i++) { + if (killed[i] == null) { + killed[i] = value; + return; + } + } + int oldLen = killed.length; + killed = Arrays.copyOf(killed, oldLen * 2); + setKilledValues(opId, killed); + killed[oldLen] = value; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.simple; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiRegister.RegisterFlag; +import com.oracle.max.graal.alloc.util.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; + +public class LinearScanAllocator { + private final LIR lir; + private final FrameMap frameMap; + + private final DataFlowAnalysis dataFlow; + + public LinearScanAllocator(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + + this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig); + this.blockBeginLocations = new LocationMap[lir.linearScanOrder().size()]; + this.blockEndLocations = new LocationMap[lir.linearScanOrder().size()]; + this.moveResolver = new MoveResolverImpl(lir, frameMap); + + this.variableLastUse = new int[lir.numVariables()]; + } + + private class MoveResolverImpl extends MoveResolver { + public MoveResolverImpl(LIR lir, FrameMap frameMap) { + super(lir, frameMap); + } + + @Override + protected CiValue scratchRegister(Variable spilled) { + GraalInternalError.shouldNotReachHere("needs working implementation"); + + EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); + CiRegister[] availableRegs = categorizedRegs.get(spilled.flag); + for (CiRegister reg : availableRegs) { + if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) { + return reg.asValue(spilled.kind); + } + } + throw new CiBailout("No register found"); + } + } + + private class ResolveDataFlowImpl extends ResolveDataFlow { + public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) { + super(lir, moveResolver, dataFlow); + } + + @Override + protected LocationMap locationsForBlockBegin(Block block) { + return beginLocationsFor(block); + } + + @Override + protected LocationMap locationsForBlockEnd(Block block) { + return endLocationsFor(block); + } + } + + private class AssignRegistersImpl extends AssignRegisters { + public AssignRegistersImpl(LIR lir, FrameMap frameMap) { + super(lir, frameMap); + } + + @Override + protected LocationMap locationsForBlockEnd(Block block) { + return endLocationsFor(block); + } + } + + + private int maxRegisterNum() { + return frameMap.target.arch.registers.length; + } + + private boolean isAllocatableRegister(CiValue value) { + return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; + } + + + private final LocationMap[] blockBeginLocations; + + private LocationMap beginLocationsFor(Block block) { + return blockBeginLocations[block.getId()]; + } + private void setBeginLocationsFor(Block block, LocationMap locations) { + blockBeginLocations[block.getId()] = locations; + } + + private final LocationMap[] blockEndLocations; + + private LocationMap endLocationsFor(Block block) { + return blockEndLocations[block.getId()]; + } + private void setEndLocationsFor(Block block, LocationMap locations) { + blockEndLocations[block.getId()] = locations; + } + + private final int[] variableLastUse; + + private int lastUseFor(Variable variable) { + return variableLastUse[variable.index]; + } + + private void setLastUseFor(Variable variable, int lastUse) { + variableLastUse[variable.index] = lastUse; + } + + private MoveResolver moveResolver; + private LocationMap curLocations; + private CiValue[] curInRegisterState; + private CiValue[] curOutRegisterState; + private BitSet curLiveIn; + private int curOpId; + private boolean curPhiDefs; + + private LocationMap canonicalSpillLocations; + + public void execute() { + assert LIRVerifier.verify(true, lir, frameMap); + + dataFlow.execute(); + IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow); + + allocate(); + + IntervalPrinter.printAfterAllocation("After linear scan allocation", lir, frameMap.registerConfig, dataFlow, blockEndLocations); + + ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow); + resolveDataFlow.execute(); + frameMap.finish(); + + IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockEndLocations); + assert RegisterVerifier.verify(lir, frameMap); + + AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap); + assignRegisters.execute(); + + Debug.dump(lir, "After register asignment"); + assert LIRVerifier.verify(false, lir, frameMap); + } + + private void allocate() { + ValueProcedure recordUseProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return recordUse(value); } }; + ValueProcedure killNonLiveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } }; + ValueProcedure unblockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return unblock(value); } }; + ValueProcedure killProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value); } }; + ValueProcedure blockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } }; + ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } }; + ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } }; + + Debug.log("==== start linear scan allocation ===="); + canonicalSpillLocations = new LocationMap(lir.numVariables()); + curInRegisterState = new CiValue[maxRegisterNum()]; + curOutRegisterState = new CiValue[maxRegisterNum()]; + for (Block block : lir.linearScanOrder()) { + Debug.log("start block %s %s", block, block.getLoop()); + + Arrays.fill(curOutRegisterState, null); + if (block.getDominator() != null) { + LocationMap dominatorState = endLocationsFor(block.getDominator()); + curLocations = new LocationMap(dominatorState); + // Clear out all variables that are not live at the begin of this block + curLiveIn = dataFlow.liveIn(block); + curLocations.forEachLocation(killNonLiveProc); + assert checkInputState(block); + } else { + curLocations = new LocationMap(lir.numVariables()); + } + Debug.log(logCurrentState()); + + for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) { + LIRInstruction op = block.lir.get(opIdx); + curOpId = op.id(); + curPhiDefs = opIdx == 0; + + Debug.log(" op %d %s", op.id(), op); + + System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length); + + // Unblock fixed registers that are only used for inputs in curOutRegisterState. + dataFlow.forEachKilled(op, false, unblockProc); + // Block fixed registers defined by this instruction in curOutRegisterState. + op.forEachTemp(blockProc); + op.forEachOutput(blockProc); + + op.forEachInput(recordUseProc); + op.forEachAlive(recordUseProc); + + moveResolver.init(block.lir, opIdx); + // Process Alive before Input because they are more restricted and the same variable can be Alive and Input. + op.forEachAlive(useProc); + op.forEachInput(useProc); + + dataFlow.forEachKilled(op, false, killProc); + + if (op.hasCall()) { + spillCallerSaveRegisters(); + } + + op.forEachTemp(defProc); + op.forEachOutput(defProc); + + // Fixed temp and output registers can evict variables from their assigned register, allocate new location for them. + fixupEvicted(); + // State values are the least critical and can get the leftover registers (or stack slots if no more register available). + op.forEachState(useProc); + + if (opIdx == 0) { + assert !moveResolver.hasMappings() : "cannot insert spill moves before label"; + setBeginLocationsFor(block, new LocationMap(curLocations)); + } + moveResolver.resolve(); + + dataFlow.forEachKilled(op, true, unblockProc); + dataFlow.forEachKilled(op, true, killProc); + + curOpId = -1; + } + + assert endLocationsFor(block) == null; + setEndLocationsFor(block, curLocations); + + logCurrentState(); + Debug.log("end block %s", block); + } + + moveResolver.finish(); + Debug.log("==== end linear scan allocation ===="); + } + + private CiValue killNonLive(CiValue value) { + assert isLocation(value); + if (!curLiveIn.get(asLocation(value).variable.index)) { + return null; + + } else if (isAllocatableRegister(asLocation(value).location)) { + int regNum = asRegister(asLocation(value).location).number; + assert curOutRegisterState[regNum] == null; + curOutRegisterState[regNum] = value; + } + return value; + } + + private CiValue unblock(CiValue value) { + if (isAllocatableRegister(value)) { + Debug.log(" unblock register %s", value); + int regNum = asRegister(value).number; + assert curOutRegisterState[regNum] == value; + curOutRegisterState[regNum] = null; + } + return value; + } + + private CiValue kill(CiValue value) { + if (isVariable(value)) { + Location location = curLocations.get(asVariable(value)); + Debug.log(" kill location %s", location); + if (isRegister(location.location)) { + int regNum = asRegister(location.location).number; + if (curOutRegisterState[regNum] == location) { + curOutRegisterState[regNum] = null; + } + } + curLocations.clear(asVariable(value)); + } + return value; + } + + + private CiValue block(CiValue value) { + if (isAllocatableRegister(value)) { + Debug.log(" block %s", value); + int regNum = asRegister(value).number; + assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof Location; + curOutRegisterState[regNum] = value; + } + return value; + } + + private void spillCallerSaveRegisters() { + Debug.log(" spill caller save registers in curInRegisterState %s", Arrays.toString(curInRegisterState)); + for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) { + CiValue in = curInRegisterState[reg.number]; + if (in != null && isLocation(in)) { + spill(asLocation(in)); + } + } + } + + private CiValue recordUse(CiValue value) { + if (isVariable(value)) { + assert lastUseFor(asVariable(value)) <= curOpId; + setLastUseFor(asVariable(value), curOpId); + + } + return value; + } + + private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + assert mode == OperandMode.Input || 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)) { + 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) { + Debug.log(" use %s %s: use current register %s", mode, value, curLoc.location); + return curLoc; + } + } + + Debug.log(" use %s %s", mode, value); + + Location newLoc = allocateRegister(asVariable(value), mode, flags); + if (newLoc != curLoc) { + moveResolver.add(curLoc, newLoc); + } + return newLoc; + } else { + assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] == value; + } + return value; + } + + private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + + private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + assert mode == OperandMode.Temp || mode == OperandMode.Output; + if (isVariable(value)) { + Debug.log(" def %s %s", mode, value); + assert curLocations.get(asVariable(value)) == null; + + Location newLoc = allocateRegister(asVariable(value), mode, flags); + return newLoc; + } + return value; + } + + + private void fixupEvicted() { + for (int i = 0; i < curInRegisterState.length; i++) { + CiValue in = curInRegisterState[i]; + CiValue out = curOutRegisterState[i]; + + 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); + assert oldLoc != newLoc; + moveResolver.add(oldLoc, newLoc); + } + + + } + } + + + private Location allocateRegister(final Variable variable, OperandMode mode, EnumSet<OperandFlag> flags) { +// if (flags.contains(OperandFlag.RegisterHint)) { +// CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() { +// @Override +// public CiValue doValue(CiValue registerHint) { +// Debug.log(" registerHint %s", registerHint); +// CiRegister hint = null; +// if (isRegister(registerHint)) { +// hint = asRegister(registerHint); +// } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) { +// hint = asRegister(asLocation(registerHint).location); +// } +// if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) { +// return selectRegister(hint, variable, inRegisterState, outRegisterState); +// } +// return null; +// } +// }); +// +// if (result != null) { +// return asLocation(result); +// } +// } +// + EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); + CiRegister[] availableRegs = categorizedRegs.get(variable.flag); + + Location bestSpillCandidate = null; + for (CiRegister reg : availableRegs) { + if (isFree(reg, mode)) { + return selectRegister(reg, variable, mode); + } else { + Location spillCandidate = spillCandidate(reg); + if (betterSpillCandidate(spillCandidate, bestSpillCandidate)) { + bestSpillCandidate = spillCandidate; + } + } + } + + if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) { + return selectSpillSlot(variable); + } + + if (bestSpillCandidate == null) { + if (curPhiDefs) { + return selectSpillSlot(variable); + } + + // This should not happen as long as all LIR instructions have fulfillable register constraints. But be safe in product mode and bail out. + assert false; + throw new CiBailout("No register available"); + } + + spill(bestSpillCandidate); + + return selectRegister(asRegister(bestSpillCandidate.location), variable, mode); + } + + private void spill(Location value) { + Location newLoc = spillLocation(value.variable); + Debug.log(" spill %s to %s", value, newLoc); + if (!curPhiDefs) { + moveResolver.add(value, newLoc); + } + curLocations.put(newLoc); + + CiRegister reg = asRegister(value.location); + assert curInRegisterState[reg.number] == value; + curInRegisterState[reg.number] = null; + if (curOutRegisterState[reg.number] == value) { + curOutRegisterState[reg.number] = null; + } + } + + private boolean isFree(CiRegister 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(); + } + } + + private Location spillCandidate(CiRegister reg) { + CiValue in = curInRegisterState[reg.number]; + CiValue out = curOutRegisterState[reg.number]; + if (in == out && in != null && isLocation(in) && lastUseFor(asLocation(in).variable) < curOpId) { + return asLocation(in); + } + return null; + } + + private boolean betterSpillCandidate(Location loc, Location compare) { + if (loc == null) { + return false; + } + if (compare == null) { + return true; + } + if (canonicalSpillLocations.get(loc.variable) != null && canonicalSpillLocations.get(compare.variable) == null) { + return true; + } + return dataFlow.definition(loc.variable) < dataFlow.definition(compare.variable); + } + + private Location spillLocation(Variable variable) { + Location result = canonicalSpillLocations.get(variable); + if (result == null) { + result = new Location(variable, frameMap.allocateSpillSlot(variable.kind)); + canonicalSpillLocations.put(result); + } + return result; + } + + private Location selectRegister(CiRegister reg, Variable variable, OperandMode mode) { + assert isFree(reg, mode); + + Location loc = new Location(variable, reg.asValue(variable.kind)); + if (mode == OperandMode.Input || mode == OperandMode.Alive) { + curInRegisterState[reg.number] = loc; + } + curOutRegisterState[reg.number] = loc; + curLocations.put(loc); + recordUse(variable); + + Debug.log(" selected register %s", loc); + return loc; + } + + private Location selectSpillSlot(Variable variable) { + Location loc = spillLocation(variable); + curLocations.put(loc); + recordUse(variable); + + Debug.log(" selected spill slot %s", loc); + return loc; + } + + private boolean checkInputState(final Block block) { + final BitSet liveState = new BitSet(); + curLocations.forEachLocation(new ValueProcedure() { + @Override + public CiValue doValue(CiValue value) { + liveState.set(asLocation(value).variable.index); + + for (Block pred : block.getPredecessors()) { + LocationMap predState = endLocationsFor(pred); + if (predState != null) { + assert predState.get(asLocation(value).variable) != null; + } else { + assert block.isLoopHeader(); + } + } + return value; + } + }); + assert liveState.equals(curLiveIn); + return true; + } + + + private String logCurrentState() { + final StringBuilder sb = new StringBuilder(); + sb.append(" current lcoations: "); + curLocations.forEachLocation(new ValueProcedure() { + @Override + public CiValue doValue(CiValue value) { + sb.append(value).append(" "); + return value; + } + }); + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.simple; + +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.alloc.util.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.StandardOp.*; +import com.oracle.max.graal.lir.cfg.*; + +public abstract class ResolveDataFlow { + public final LIR lir; + public final MoveResolver moveResolver; + public final DataFlowAnalysis dataFlow; + + public ResolveDataFlow(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) { + this.lir = lir; + this.moveResolver = moveResolver; + this.dataFlow = dataFlow; + } + + private LocationMap curFromLocations; + + public void execute() { + ValueProcedure locMappingProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return locMapping(value); } }; + + Debug.log("==== start resolve data flow ===="); + for (Block toBlock : lir.linearScanOrder()) { + PhiLabelOp phiDefs = null; + if (toBlock.lir.get(0) instanceof PhiLabelOp) { + phiDefs = (PhiLabelOp) toBlock.lir.get(0); + } + + for (Block fromBlock : toBlock.getPredecessors()) { + Debug.log("start edge %s -> %s", fromBlock, toBlock); + findInsertPos(fromBlock, toBlock); + + LocationMap toLocations = locationsForBlockBegin(toBlock); + curFromLocations = locationsForBlockEnd(fromBlock); + if (toLocations != curFromLocations) { + toLocations.forEachLocation(locMappingProc); + } + + if (phiDefs != null) { + PhiJumpOp phiInputs = (PhiJumpOp) fromBlock.lir.get(fromBlock.lir.size() - 1); + phiMapping(phiInputs.getPhiInputs(), phiDefs.getPhiDefinitions()); + phiInputs.markResolved(); + } + + moveResolver.resolve(); + Debug.log("end edge %s -> %s", fromBlock, toBlock); + } + + if (phiDefs != null) { + // Phi functions are resolved with moves now, so delete them. + phiDefs.markResolved(); + } + } + moveResolver.finish(); + Debug.log("==== end resolve data flow ===="); + } + + private CiValue locMapping(CiValue value) { + Location to = asLocation(value); + Location from = curFromLocations.get(to.variable); + if (value != from && from != null) { + moveResolver.add(from, to); + } + return value; + } + + private void phiMapping(CiValue[] inputs, CiValue[] outputs) { + assert inputs.length == outputs.length; + for (int i = 0; i < inputs.length; i++) { + if (inputs[i] != outputs[i]) { + moveResolver.add(inputs[i], asLocation(outputs[i])); + } + } + } + + private void findInsertPos(Block fromBlock, Block toBlock) { + assert fromBlock.getSuccessors().contains(toBlock) && toBlock.getPredecessors().contains(fromBlock); + + if (fromBlock.numberOfSux() == 1) { + List<LIRInstruction> instructions = fromBlock.lir; + LIRInstruction instr = instructions.get(instructions.size() - 1); + assert instr instanceof StandardOp.JumpOp : "block does not end with an unconditional jump"; + moveResolver.init(instructions, instructions.size() - 1); + Debug.log(" insert at end of %s before %d", fromBlock, instructions.size() - 1); + + } else if (toBlock.numberOfPreds() == 1) { + moveResolver.init(toBlock.lir, 1); + Debug.log(" insert at beginning of %s before %d", toBlock, 1); + + } else { + GraalInternalError.shouldNotReachHere("Critical edge not split"); + } + } + + protected abstract LocationMap locationsForBlockBegin(Block block); + protected abstract LocationMap locationsForBlockEnd(Block block); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.simple; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiRegister.RegisterFlag; +import com.oracle.max.graal.alloc.util.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; + +public class SpillAllAllocator { + private final LIR lir; + private final FrameMap frameMap; + + private final DataFlowAnalysis dataFlow; + + public SpillAllAllocator(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + + this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig); + this.blockLocations = new LocationMap[lir.linearScanOrder().size()]; + this.moveResolver = new MoveResolverImpl(lir, frameMap); + } + + private class MoveResolverImpl extends MoveResolver { + public MoveResolverImpl(LIR lir, FrameMap frameMap) { + super(lir, frameMap); + } + + @Override + protected CiValue scratchRegister(Variable spilled) { + EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); + CiRegister[] availableRegs = categorizedRegs.get(spilled.flag); + for (CiRegister reg : availableRegs) { + if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) { + return reg.asValue(spilled.kind); + } + } + throw new CiBailout("No register found"); + } + } + + private class ResolveDataFlowImpl extends ResolveDataFlow { + public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) { + super(lir, moveResolver, dataFlow); + } + + @Override + protected LocationMap locationsForBlockBegin(Block block) { + assert block.numberOfPreds() > 0 && block.getDominator() != null; + return locationsFor(block.getDominator()); + } + + @Override + protected LocationMap locationsForBlockEnd(Block block) { + return locationsFor(block); + } + } + + private class AssignRegistersImpl extends AssignRegisters { + public AssignRegistersImpl(LIR lir, FrameMap frameMap) { + super(lir, frameMap); + } + + @Override + protected LocationMap locationsForBlockEnd(Block block) { + return locationsFor(block); + } + } + + + private int maxRegisterNum() { + return frameMap.target.arch.registers.length; + } + + private boolean isAllocatableRegister(CiValue value) { + return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; + } + + + private final LocationMap[] blockLocations; + + private LocationMap locationsFor(Block block) { + return blockLocations[block.getId()]; + } + private void setLocationsFor(Block block, LocationMap locations) { + blockLocations[block.getId()] = locations; + } + + private MoveResolver moveResolver; + private LocationMap curStackLocations; + private LocationMap curRegisterLocations; + private Object[] curInRegisterState; + private Object[] curOutRegisterState; + private BitSet curLiveIn; + private LIRInstruction curInstruction; + + public void execute() { + assert LIRVerifier.verify(true, lir, frameMap); + + dataFlow.execute(); + IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow); + + allocate(); + + IntervalPrinter.printAfterAllocation("After spill all allocation", lir, frameMap.registerConfig, dataFlow, blockLocations); + + ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow); + resolveDataFlow.execute(); + frameMap.finish(); + + IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockLocations); + assert RegisterVerifier.verify(lir, frameMap); + + AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap); + assignRegisters.execute(); + + Debug.dump(lir, "After register asignment"); + assert LIRVerifier.verify(false, lir, frameMap); + } + + private void allocate() { + ValueProcedure killNonLiveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } }; + ValueProcedure killBeginProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, false); } }; + ValueProcedure killEndProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, true); } }; + ValueProcedure killLocationProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killLocation(value); } }; + ValueProcedure blockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } }; + ValueProcedure loadProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return load(value, mode, flags); } }; + ValueProcedure spillProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return spill(value, mode, flags); } }; + ValueProcedure useSlotProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } }; + + Debug.log("==== start spill all allocation ===="); + curInRegisterState = new Object[maxRegisterNum()]; + curOutRegisterState = new Object[maxRegisterNum()]; + curRegisterLocations = new LocationMap(lir.numVariables()); + for (Block block : lir.linearScanOrder()) { + Debug.log("start block %s %s", block, block.getLoop()); + assert checkEmpty(curOutRegisterState); + + if (block.getDominator() != null) { + LocationMap dominatorState = locationsFor(block.getDominator()); + curStackLocations = new LocationMap(dominatorState); + // Clear out all variables that are not live at the begin of this block + curLiveIn = dataFlow.liveIn(block); + curStackLocations.forEachLocation(killNonLiveProc); + assert checkInputState(block); + } else { + curStackLocations = new LocationMap(lir.numVariables()); + } + Debug.log(logCurrentState()); + + for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) { + LIRInstruction op = block.lir.get(opIdx); + curInstruction = op; + Debug.log(" op %d %s", op.id(), op); + + assert curRegisterLocations.checkEmpty(); + + System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length); + + // Block fixed registers that are defined by this instruction, so that they are no longer available for normal allocation. + op.forEachTemp(blockProc); + op.forEachOutput(blockProc); + + moveResolver.init(block.lir, opIdx); + // Process Alive before Input because they are more restricted and the same variable can be Alive and Input. + op.forEachAlive(loadProc); + op.forEachInput(loadProc); + moveResolver.resolve(); + op.forEachState(useSlotProc); + + dataFlow.forEachKilled(op, false, killBeginProc); + assert !op.hasCall() || checkNoCallerSavedRegister() : "caller saved register in use accross call site"; + + moveResolver.init(block.lir, opIdx + 1); + op.forEachTemp(spillProc); + op.forEachOutput(spillProc); + moveResolver.resolve(); + + dataFlow.forEachKilled(op, true, killEndProc); + curRegisterLocations.forEachLocation(killLocationProc); + + assert curRegisterLocations.checkEmpty(); + curInstruction = null; + } + assert checkEmpty(curOutRegisterState); + assert locationsFor(block) == null; + setLocationsFor(block, curStackLocations); + + logCurrentState(); + Debug.log("end block %s", block); + } + + moveResolver.finish(); + Debug.log("==== end spill all allocation ===="); + } + + private CiValue killNonLive(CiValue value) { + assert isLocation(value); + if (!curLiveIn.get(asLocation(value).variable.index)) { + return null; + } + return value; + } + + private CiValue kill(CiValue value, boolean end) { + if (isVariable(value)) { + Debug.log(" kill variable %s", value); + + Variable variable = asVariable(value); + curStackLocations.clear(variable); + + Location loc = curRegisterLocations.get(variable); + if (loc != null) { + killLocation(loc); + curRegisterLocations.clear(variable); + + Debug.log(" location %s", loc); + assert isAllocatableRegister(loc.location); + + int regNum = asRegister(loc.location).number; + if (curOutRegisterState[regNum] == loc) { + curOutRegisterState[regNum] = null; + } + } + + } else if (isAllocatableRegister(value)) { + Debug.log(" kill register %s", value); + int regNum = asRegister(value).number; + assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction && curInstruction != null; + + if (end || curOutRegisterState[regNum] != curInstruction) { + curOutRegisterState[regNum] = null; + } + + } else { + throw GraalInternalError.shouldNotReachHere(); + } + return value; + } + + private CiValue killLocation(CiValue value) { + Debug.log(" kill location %s", value); + assert isAllocatableRegister(asLocation(value).location); + + int regNum = asRegister(asLocation(value).location).number; + if (curOutRegisterState[regNum] == value) { + curOutRegisterState[regNum] = null; + } + return null; + } + + private CiValue block(CiValue value) { + if (isAllocatableRegister(value)) { + Debug.log(" block %s", value); + int regNum = asRegister(value).number; + assert curInstruction != null; + assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction; + curOutRegisterState[regNum] = curInstruction; + } + return value; + } + + private CiValue load(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + assert mode == OperandMode.Input || mode == OperandMode.Alive; + if (flags.contains(OperandFlag.Stack)) { + return useSlot(value); + } + if (isVariable(value)) { + Debug.log(" load %s", value); + Location regLoc = curRegisterLocations.get(asVariable(value)); + if (regLoc != null) { + // 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); + Location stackLoc = curStackLocations.get(asVariable(value)); + assert stackLoc != null; + moveResolver.add(stackLoc, regLoc); + } + return regLoc; + } else { + assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] instanceof LIRInstruction; + return value; + } + } + + private CiValue spill(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + assert mode == OperandMode.Temp || mode == OperandMode.Output; + 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) { + Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind)); + curStackLocations.put(stackLoc); + moveResolver.add(regLoc, stackLoc); + } + return regLoc; + } else { + assert !isAllocatableRegister(value) || curOutRegisterState[asRegister(value).number] == curInstruction && curInstruction != null; + return value; + } + } + + private CiValue useSlot(CiValue value) { + if (isVariable(value)) { + Debug.log(" useSlot %s", value); + Location stackLoc = curStackLocations.get(asVariable(value)); + assert stackLoc != null; + Debug.log(" slot %s", stackLoc); + return stackLoc; + } else { + return value; + } + } + + private CiValue defSlot(CiValue value) { + if (isVariable(value)) { + Debug.log(" assignSlot %s", value); + Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind)); + assert curStackLocations.get(asVariable(value)) == null; + curStackLocations.put(stackLoc); + Debug.log(" slot %s", stackLoc); + return stackLoc; + } else { + return value; + } + } + + private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet<OperandFlag> flags) { + if (flags.contains(OperandFlag.RegisterHint)) { + CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() { + @Override + public CiValue doValue(CiValue registerHint) { + Debug.log(" registerHint %s", registerHint); + CiRegister hint = null; + if (isRegister(registerHint)) { + hint = asRegister(registerHint); + } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) { + hint = asRegister(asLocation(registerHint).location); + } + if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) { + return selectRegister(hint, variable, inRegisterState, outRegisterState); + } + return null; + } + }); + + if (result != null) { + return asLocation(result); + } + } + + EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); + CiRegister[] availableRegs = categorizedRegs.get(variable.flag); + + for (CiRegister reg : availableRegs) { + if (isFree(reg, inRegisterState, outRegisterState)) { + return selectRegister(reg, variable, inRegisterState, outRegisterState); + } + + } + throw new CiBailout("No register found"); + } + + private static boolean isFree(CiRegister reg, Object[] inRegisterState, Object[] outRegisterState) { + return (inRegisterState == null || inRegisterState[reg.number] == null) && (outRegisterState == null || outRegisterState[reg.number] == null); + } + + private Location selectRegister(CiRegister reg, Variable variable, Object[] inRegisterState, Object[] outRegisterState) { + Location loc = new Location(variable, reg.asValue(variable.kind)); + if (inRegisterState != null) { + inRegisterState[reg.number] = loc; + } + if (outRegisterState != null) { + outRegisterState[reg.number] = loc; + } + assert curRegisterLocations.get(variable) == null; + curRegisterLocations.put(loc); + Debug.log(" selected register %s", loc); + return loc; + } + + private boolean checkInputState(final Block block) { + final BitSet liveState = new BitSet(); + curStackLocations.forEachLocation(new ValueProcedure() { + @Override + public CiValue doValue(CiValue value) { + liveState.set(asLocation(value).variable.index); + + for (Block pred : block.getPredecessors()) { + LocationMap predState = locationsFor(pred); + if (predState != null) { + assert predState.get(asLocation(value).variable) == value; + } else { + assert block.isLoopHeader(); + } + } + return value; + } + }); + assert liveState.equals(curLiveIn); + return true; + } + + private boolean checkNoCallerSavedRegister() { + for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) { + assert curOutRegisterState[reg.number] == null || curOutRegisterState[reg.number] == curInstruction : "caller saved register in use accross call site"; + } + return true; + } + + private static boolean checkEmpty(Object[] array) { + for (Object o : array) { + assert o == null; + } + return true; + } + + + private String logCurrentState() { + final StringBuilder sb = new StringBuilder(); + sb.append(" curVariableLocations: "); + curStackLocations.forEachLocation(new ValueProcedure() { + @Override + public CiValue doValue(CiValue value) { + sb.append(value).append(" "); + return value; + } + }); + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.alloc.util; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.alloc.simple.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; + +public final class IntervalPrinter { + + public static void printBeforeAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow) { + if (Debug.isDumpEnabled()) { + IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, null); + Debug.dump(lir, label); + Debug.dump(printer.execute(), label); + } + } + + public static void printAfterAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) { + if (Debug.isDumpEnabled()) { + IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, blockEndLocations); + Debug.dump(lir, label); + Debug.dump(printer.execute(), label); + } + } + + + public static class Range { + public final int from; + public final int to; + + public Range(int from, int to) { + this.from = from; + this.to = to; + } + } + + public static class UsePosition { + public final int pos; + public final String kind; + + public UsePosition(int pos, String kind) { + this.pos = pos; + this.kind = kind; + } + } + + public static class Interval { + public final String name; + public final String description; + public final String variable; + public final String type; + public final List<Range> ranges; + public final List<UsePosition> uses; + + protected final int orderNum; + protected int lastTo; + + public Interval(int orderNum, String name, String description, String variable, String type) { + this.orderNum = orderNum; + this.name = name; + this.description = description; + this.variable = variable; + this.type = type; + this.ranges = new ArrayList<>(); + this.uses = new ArrayList<>(); + } + } + + + private final LIR lir; + private final RiRegisterConfig registerConfig; + private final DataFlowAnalysis dataFlow; + private final LocationMap[] blockEndLocations; + private final Variable[] variables; + private final Map<String, Interval> intervals; + + private IntervalPrinter(LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) { + this.lir = lir; + this.registerConfig = registerConfig; + this.dataFlow = dataFlow; + this.blockEndLocations = blockEndLocations; + this.variables = new Variable[lir.numVariables()]; + this.intervals = new HashMap<>(); + } + + private boolean isAllocatableRegister(CiValue value) { + return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; + } + + private int curOpId; + private String curUseKind; + + public Interval[] execute() { + ValueProcedure varProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return var(value); } }; + + for (Block block : lir.linearScanOrder()) { + for (LIRInstruction op : block.lir) { + op.forEachOutput(varProc); + } + } + + ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } }; + ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, flags); } }; + + intervals.put("call", new Interval(-2, "call", "", "call", "hasCall")); + intervals.put("st", new Interval(-1, "st", "", "st", "hasState")); + + for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) { + Block block = lir.linearScanOrder().get(i); + + curOpId = block.getLastLirInstructionId() + 2; + for (Block sux : block.getSuccessors()) { + BitSet suxIn = dataFlow.liveIn(sux); + for (int idx = suxIn.nextSetBit(0); idx >= 0; idx = suxIn.nextSetBit(idx + 1)) { + if (blockEndLocations != null) { + out(blockEndLocations[block.getId()].get(variables[idx])); + } else { + out(variables[idx]); + } + } + } + + for (int j = block.lir.size() - 1; j >= 0; j--) { + LIRInstruction op = block.lir.get(j); + if (op.id() >= 0) { + curOpId = op.id(); + } else { + curOpId = (curOpId - 1) | 1; + } + + op.forEachOutput(defProc); + op.forEachTemp(defProc); + op.forEachInput(useProc); + op.forEachAlive(useProc); + curUseKind = "L"; + op.forEachState(useProc); + curUseKind = null; + + if (op.hasCall()) { + intervals.get("call").ranges.add(new Range(curOpId, curOpId + 1)); + } + if (op.info != null) { + intervals.get("st").ranges.add(new Range(curOpId, curOpId + 1)); + } + } + + for (Interval interval : intervals.values()) { + if (interval.lastTo != 0) { + interval.ranges.add(new Range(block.getFirstLirInstructionId(), interval.lastTo)); + interval.lastTo = 0; + } + } + } + + Interval[] intervalsArray = intervals.values().toArray(new Interval[0]); + Arrays.sort(intervalsArray, new Comparator<Interval>() { + @Override + public int compare(Interval o1, Interval o2) { + return o1.orderNum - o2.orderNum; + } + }); + return intervalsArray; + } + + public CiValue var(CiValue value) { + if (isLocation(value)) { + variables[asLocation(value).variable.index] = asLocation(value).variable; + } else if (isVariable(value)) { + variables[asVariable(value).index] = asVariable(value); + } + return value; + } + + private Interval findInterval(CiValue value) { + Interval interval; + if (isLocation(value)) { + Interval parent = findInterval(asLocation(value).variable); + String name = "v" + asLocation(value).variable.index + ":" + asLocation(value).location; + String description = isStackSlot(asLocation(value).location) ? "stack" : ""; + interval = new Interval(asLocation(value).variable.index * 2 + 1001, name, description, parent.name, value.kind.javaName); + + } else if (isVariable(value)) { + interval = new Interval(asVariable(value).index * 2 + 1000, value.toString(), "", value.toString(), value.kind.javaName); + + } else if (isAllocatableRegister(value)) { + interval = new Interval(asRegister(value).number, asRegister(value).toString(), "", asRegister(value).toString(), "fixed"); + + } else { + return null; + } + + Interval existing = intervals.get(interval.name); + if (existing != null) { + return existing; + } + intervals.put(interval.name, interval); + return interval; + } + + private String useKind(EnumSet<OperandFlag> flags) { + if (curUseKind != null) { + return curUseKind; + } else if (flags.contains(OperandFlag.Stack)) { + return "S"; + } else { + return "M"; + } + } + + private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + Interval interval = findInterval(value); + if (interval != null) { + if (interval.uses.size() == 0 || interval.uses.get(interval.uses.size() - 1).pos != curOpId) { + interval.uses.add(new UsePosition(curOpId, useKind(flags))); + } + if (interval.lastTo == 0) { + interval.lastTo = curOpId + (mode == OperandMode.Alive ? 1 : 0); + } + } + return value; + } + + private CiValue def(CiValue value, EnumSet<OperandFlag> flags) { + Interval interval = findInterval(value); + if (interval != null) { + interval.uses.add(new UsePosition(curOpId, useKind(flags))); + if (interval.lastTo == 0) { + interval.ranges.add(new Range(curOpId, curOpId + 1)); + } else { + interval.ranges.add(new Range(curOpId, interval.lastTo)); + } + interval.lastTo = 0; + } + return value; + } + + private CiValue out(CiValue value) { + Interval interval = findInterval(value); + if (interval != null) { + interval.lastTo = curOpId; + } + return value; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/Location.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.util; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.lir.*; + +public class Location extends CiValue { + private static final long serialVersionUID = -1786677729152726126L; + + public final Variable variable; + public final CiValue location; + + public Location(Variable variable, CiValue location) { + super(variable.kind); + this.variable = variable; + this.location = location; + + assert variable.kind == location.kind; + } + + @Override + public String toString() { + return variable + "[" + location + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/LocationMap.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.util; + +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; + +public class LocationMap { + private final Location[] locations; + + public LocationMap(int numVariables) { + locations = new Location[numVariables]; + } + + public LocationMap(LocationMap template) { + locations = Arrays.copyOf(template.locations, template.locations.length); + } + + public Location get(Variable variable) { + assert locations[variable.index] == null || locations[variable.index].variable == variable; + return locations[variable.index]; + } + + public void put(Location location) { + locations[location.variable.index] = location; + } + + public void clear(Variable variable) { + locations[variable.index] = null; + } + + public void forEachLocation(ValueProcedure proc) { + for (int i = 0; i < locations.length; i++) { + if (locations[i] != null) { + CiValue newValue = proc.doValue(locations[i], null, null); + assert newValue == null || asLocation(newValue).variable == locations[i].variable; + locations[i] = (Location) newValue; + } + } + } + + public boolean checkEmpty() { + for (int i = 0; i < locations.length; i++) { + assert locations[i] == null; + } + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/LocationUtil.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011, 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.max.graal.alloc.util; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.lir.*; + +public class LocationUtil extends ValueUtil { + + public static boolean isLocation(CiValue value) { + assert value != null; + return value instanceof Location; + } + + public static Location asLocation(CiValue value) { + assert value != null; + return (Location) value; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/MoveResolver.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,342 @@ +/* + * 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.max.graal.alloc.util; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; + +public abstract class MoveResolver { + private final LIR lir; + private final FrameMap frameMap; + private final int[] registersBlocked; + private final Map<CiValue, Integer> valuesBlocked; + private final List<CiValue> mappingFrom; + private final List<Location> mappingTo; + private final LIRInsertionBuffer insertionBuffer; + private int insertPos; + + public MoveResolver(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + + registersBlocked = new int[frameMap.target.arch.registers.length]; + valuesBlocked = new HashMap<>(); + + mappingFrom = new ArrayList<>(); + mappingTo = new ArrayList<>(); + insertionBuffer = new LIRInsertionBuffer(); + insertPos = -1; + + assert checkEmpty(); + } + + public void init(List<LIRInstruction> newInsertList, int newInsertPos) { + assert checkEmpty(); + + if (insertionBuffer.lirList() != newInsertList) { + // Block changed, so append insertionBuffer because it is bound to a specific block + finish(); + insertionBuffer.init(newInsertList); + } + insertPos = newInsertPos; + + assert checkValid(); + } + + public void add(CiValue from, Location to) { + assert checkValid(); + assert isLocation(from) || isConstant(from); + assert from != to; + + Debug.log("mr add mapping from %s to %s", from, to); + mappingFrom.add(from); + mappingTo.add(to); + + assert checkValid(); + } + + public boolean hasMappings() { + return mappingFrom.size() > 0; + } + + public void resolve() { + assert checkValid(); + + if (mappingFrom.size() == 1) { + // If there is only one mapping, it is trivial that this mapping is safe to resolve. + Debug.log("mr resolve mappings: %d", mappingFrom.size()); + insertMove(mappingFrom.get(0), mappingTo.get(0)); + mappingFrom.remove(0); + mappingTo.remove(0); + } else if (mappingFrom.size() > 1) { + Debug.log("mr resolve mappings: %d", mappingFrom.size()); + doResolve(); + } + insertPos = -1; + + assert checkEmpty(); + } + + public void finish() { + assert checkEmpty(); + + if (insertionBuffer.initialized()) { + insertionBuffer.finish(); + } + + assert !insertionBuffer.initialized() : "must be uninitialized now"; + assert checkEmpty(); + } + + + private void doResolve() { + // Block all registers and stack slots that are used as inputs of a move. + // When a register is blocked, no move to this register is emitted. + // This is necessary for detecting cycles in moves. + for (CiValue from : mappingFrom) { + block(from); + } + + while (mappingFrom.size() > 0) { + boolean processed = false; + for (int i = mappingFrom.size() - 1; i >= 0; i--) { + CiValue from = mappingFrom.get(i); + Location to = mappingTo.get(i); + + if (safeToProcessMove(from, to)) { + insertMove(from, to); + unblock(from); + mappingFrom.remove(i); + mappingTo.remove(i); + processed = true; + } + } + + if (!processed) { + // No move could be processed because there is a cycle in the move list + // (e.g., r1 -> r2, r2 -> r1), so one location must be spilled. + spill(); + } + } + } + + private void spill() { + Location spillCandidate = null; + int exchangeCandidate = -1; + int exchangeOther = -1; + + for (int i = mappingFrom.size() - 1; i >= 0; i--) { + CiValue from = mappingFrom.get(i); + Location to = mappingTo.get(i); + assert !safeToProcessMove(from, to) : "would not be in this code otherwise"; + + if (isConstant(from)) { + continue; + } + CiValue fromLoc = asLocation(from).location; + + // Check if we can insert an exchange to save us from spilling. + if (isRegister(fromLoc) && isRegister(to) && asRegister(fromLoc) != asRegister(to) && blockedCount(to) == 1) { + for (int j = mappingFrom.size() - 1; j >= 0; j--) { + CiValue possibleOther = mappingFrom.get(j); + if (isLocation(possibleOther)) { + if (asLocation(possibleOther).location == to.location) { + assert exchangeCandidate == -1 : "must not find twice because of blocked check above"; + exchangeCandidate = i; + exchangeOther = j; + } else if (i != j && asLocation(possibleOther).location == fromLoc) { + // From is read multiple times, so exchange would be too complicated. + exchangeCandidate = -1; + break; + } + } + } + } + + if (exchangeCandidate != -1) { + // Already found a result, no need to search further + break; + } + if (spillCandidate == null || isStackSlot(spillCandidate.location)) { + // this interval cannot be processed now because target is not free + spillCandidate = asLocation(from); + } + } + + if (exchangeCandidate != -1) { + Location from = asLocation(mappingFrom.get(exchangeCandidate)); + Location to = mappingTo.get(exchangeCandidate); + Location other = asLocation(mappingFrom.get(exchangeOther)); + + Location newOther = new Location(other.variable, from.variable); + mappingFrom.set(exchangeOther, newOther); + + insertExchange(newOther, to); + unblock(to); + mappingFrom.remove(exchangeCandidate); + mappingTo.remove(exchangeCandidate); + + } else { + assert spillCandidate != null : "no location for spilling found"; + + Location spillLocation = new Location(spillCandidate.variable, frameMap.allocateSpillSlot(spillCandidate.kind)); + insertMove(spillCandidate, spillLocation); + + for (int i = mappingFrom.size() - 1; i >= 0; i--) { + if (mappingFrom.get(i) == spillCandidate) { + mappingFrom.set(i, spillLocation); + unblock(spillCandidate); + block(spillLocation); + } + } + assert blockedCount(spillCandidate) == 0 : "register must be unblocked after spilling"; + } + } + + private void block(CiValue value) { + if (isLocation(value)) { + CiValue location = asLocation(value).location; + if (isRegister(location)) { + registersBlocked[asRegister(location).number]++; + } else { + Integer count = valuesBlocked.get(location); + valuesBlocked.put(location, count == null ? 1 : count + 1); + } + } + } + + private void unblock(CiValue value) { + if (isLocation(value)) { + assert blockedCount(asLocation(value)) > 0; + CiValue location = asLocation(value).location; + if (isRegister(location)) { + registersBlocked[asRegister(location).number]--; + } else { + Integer count = valuesBlocked.remove(location); + if (count > 1) { + valuesBlocked.put(location, count - 1); + } + } + } + } + + private int blockedCount(Location value) { + CiValue location = asLocation(value).location; + if (isRegister(location)) { + return registersBlocked[asRegister(location).number]; + } else { + Integer count = valuesBlocked.get(location); + return count == null ? 0 : count; + } + } + + private boolean safeToProcessMove(CiValue from, Location to) { + int count = blockedCount(to); + return count == 0 || (count == 1 && isLocation(from) && asLocation(from).location == to.location); + } + + private void insertExchange(Location from, Location to) { + Debug.log("mr XCHG %s, %s", from, to); + // TODO create XCHG instruction and use it here + insertionBuffer.append(insertPos, null); + throw GraalInternalError.unimplemented(); + } + + private void insertMove(CiValue src, Location dst) { + if (isStackSlot(dst.location) && isLocation(src) && isStackSlot(asLocation(src).location)) { + // Move between two stack slots. We need a temporary registers. If the allocator can give + // us a free register, we need two moves: src->scratch, scratch->dst + // If the allocator cannot give us a free register (it returns a Location in this case), + // we need to spill the scratch register first, so we need four moves in total. + + CiValue scratch = scratchRegister(dst.variable); + + Location scratchSaved = null; + CiValue scratchRegister = scratch; + if (isLocation(scratch)) { + scratchSaved = new Location(asLocation(scratch).variable, frameMap.allocateSpillSlot(scratch.kind)); + insertMove(scratch, scratchSaved); + scratchRegister = asLocation(scratch).location; + } + assert isRegister(scratchRegister); + + Location scratchLocation = new Location(dst.variable, scratchRegister); + insertMove(src, scratchLocation); + insertMove(scratchLocation, dst); + + if (scratchSaved != null) { + insertMove(scratchSaved, asLocation(scratch)); + } + + } else { + Debug.log("mr MOV %s -> %s", src, dst); + insertionBuffer.append(insertPos, lir.spillMoveFactory.createMove(dst, src)); + } + } + + /** + * Provides a register that can be used by the move resolver. If the returned value is a + * {@link CiRegisterValue}, the register can be overwritten without precautions. If the + * returned value is a {@link Location}, it needs to be spilled and rescued itself. + */ + protected abstract CiValue scratchRegister(Variable spilled); + + private boolean checkEmpty() { + assert insertPos == -1; + assert mappingFrom.size() == 0 && mappingTo.size() == 0; + for (int registerBlocked : registersBlocked) { + assert registerBlocked == 0; + } + assert valuesBlocked.size() == 0; + return true; + } + + private boolean checkValid() { + assert insertPos != -1; + for (int registerBlocked : registersBlocked) { + assert registerBlocked == 0; + } + assert mappingFrom.size() == mappingTo.size(); + assert insertionBuffer.initialized() && insertPos != -1; + + for (int i = 0; i < mappingTo.size(); i++) { + CiValue from = mappingFrom.get(i); + Location to = mappingTo.get(i); + + assert from.kind.stackKind() == to.kind; + + for (int j = i + 1; j < mappingTo.size(); j++) { + Location otherTo = mappingTo.get(j); + assert to != otherTo && to.variable != otherTo.variable && to.location != otherTo.location : "Cannot write to same location twice"; + } + } + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.alloc/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,248 @@ +/* + * 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.max.graal.alloc.util; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; + +public final class RegisterVerifier { + private final FrameMap frameMap; + + /** + * All blocks that must be processed. + */ + private final List<Block> workList; + + /** + * Saved information of previous check. + * <br> + * State mapping: mapping from registers and stack slots ({@link CiRegister} and {@link Integer} stack slot offsets) to the + * value that is currently contained in there ({@link Location} for operands that were variables; {@link CiRegisterValue} or + * {@link CiStackSlot} for operands that used fixed registers or stack slots). + */ + private final Map<Object, CiValue>[] blockStates; + + private void addToWorkList(Block block) { + if (!workList.contains(block)) { + workList.add(block); + } + } + + private Map<Object, CiValue> stateFor(Block block) { + return blockStates[block.getId()]; + } + + private void setStateFor(Block block, Map<Object, CiValue> savedState) { + blockStates[block.getId()] = savedState; + } + + private static Map<Object, CiValue> copy(Map<Object, CiValue> inputState) { + return new HashMap<>(inputState); + } + + public static boolean verify(LIR lir, FrameMap frameMap) { + RegisterVerifier verifier = new RegisterVerifier(lir, frameMap); + verifier.verify(lir.cfg.getStartBlock()); + return true; + } + + @SuppressWarnings("unchecked") + private RegisterVerifier(LIR lir, FrameMap frameMap) { + this.frameMap = frameMap; + this.workList = new LinkedList<>(); + this.blockStates = new Map[lir.linearScanOrder().size()]; + } + + private Map<Object, CiValue> curInputState; + + private void verify(Block startBlock) { + ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, flags); } }; + ValueProcedure tempProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return temp(value); } }; + ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return output(value); } }; + + curInputState = new HashMap<>(); + setStateFor(startBlock, curInputState); + addToWorkList(startBlock); + + Debug.log("==== start verify register allocation ===="); + do { + Block block = workList.remove(0); + + // Must copy state because it is modified. + curInputState = copy(stateFor(block)); + Debug.log("start block %s %s", block, block.getLoop()); + Debug.log(logCurrentState()); + + for (LIRInstruction op : block.lir) { + Debug.log(" op %d %s", op.id(), op); + + op.forEachInput(useProc); + if (op.hasCall()) { + invalidateRegisters(); + } + op.forEachAlive(useProc); + op.forEachState(useProc); + op.forEachTemp(tempProc); + op.forEachOutput(outputProc); + } + + for (Block succ : block.getSuccessors()) { + processSuccessor(succ); + } + + Debug.log("end block %s", block); + } while (!workList.isEmpty()); + Debug.log("==== end verify register allocation ===="); + } + + private void processSuccessor(Block succ) { + Map<Object, CiValue> savedState = stateFor(succ); + if (savedState == null) { + // Block was not processed before, so set initial inputState. + Debug.log(" successor %s: initial visit", succ); + setStateFor(succ, copy(curInputState)); + addToWorkList(succ); + + } else { + // This block was already processed before. + // Check if new inputState is consistent with savedState. + Debug.log(" successor %s: state present", succ); + Iterator<Map.Entry<Object, CiValue>> iter = savedState.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry<Object, CiValue> entry = iter.next(); + CiValue savedValue = entry.getValue(); + CiValue inputValue = curInputState.get(entry.getKey()); + + if (savedValue != inputValue) { + // Current inputState and previous savedState assume a different value in this register. + // Assume that this register is invalid and remove it from the saved state. + Debug.log(" invalididating %s because it is inconsistent with %s", savedValue, inputValue); + iter.remove(); + // Must re-visit this block. + addToWorkList(succ); + } + } + } + } + + private void invalidateRegisters() { + // Invalidate all caller save registers at calls. + Iterator<Object> iter = curInputState.keySet().iterator(); + while (iter.hasNext()) { + Object value1 = iter.next(); + if (value1 instanceof CiRegister && frameMap.registerConfig.getAttributesMap()[((CiRegister) value1).number].isCallerSave) { + Debug.log(" remove caller save register %s", value1); + iter.remove(); + } + } + } + + /** + * Gets the mapping key for a value. The key should be as narrow as possible, e.g., it should not + * include the kind of the value because we do not want to distinguish between the same register with + * different kinds. + */ + private Object key(CiValue value) { + if (isLocation(value)) { + return key(asLocation(value).location); + } else if (isRegister(value)) { + return asRegister(value); + } else if (isStackSlot(value)) { + return Integer.valueOf(frameMap.offsetForStackSlot(asStackSlot(value))); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + + private boolean isIgnoredRegister(CiValue value) { + return isRegister(value) && !frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; + } + + private CiValue use(CiValue value, EnumSet<OperandFlag> flags) { + if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) { + CiValue actual = curInputState.get(key(value)); + 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)); + Debug.log(logCurrentState()); + throw GraalInternalError.shouldNotReachHere(); + } + } + return value; + } + + private CiValue temp(CiValue value) { + if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) { + Debug.log(" temp %s -> remove key %s", value, key(value)); + curInputState.remove(key(value)); + } + return value; + } + + private CiValue output(CiValue value) { + if (value != CiValue.IllegalValue && !isIgnoredRegister(value)) { + Debug.log(" output %s -> set key %s", value, key(value)); + curInputState.put(key(value), value); + } + return value; + } + + + private String logCurrentState() { + ArrayList<Object> keys = new ArrayList<>(curInputState.keySet()); + Collections.sort(keys, new Comparator<Object>() { + @Override + public int compare(Object o1, Object o2) { + if (o1 instanceof CiRegister) { + if (o2 instanceof CiRegister) { + return ((CiRegister) o1).number - ((CiRegister) o2).number; + } else { + return -1; + } + } else { + if (o2 instanceof CiRegister) { + return 1; + } else { + return ((Integer) o1).intValue() - ((Integer) o2).intValue(); + } + } + } + }); + + StringBuilder sb = new StringBuilder(" state: "); + for (Object key : keys) { + sb.append(key).append("=").append(curInputState.get(key)).append(" "); + } + return sb.toString(); + } +}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.simple; - -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.alloc.util.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; - -public abstract class AssignRegisters { - public final LIR lir; - public final FrameMap frameMap; - - public AssignRegisters(LIR lir, FrameMap frameMap) { - this.lir = lir; - this.frameMap = frameMap; - } - - private CiBitMap curRegisterRefMap; - private CiBitMap curFrameRefMap; - - public void execute() { - ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value); } }; - ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value); } }; - ValueProcedure setReferenceProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setReference(value); } }; - - assert trace("==== start assign registers ===="); - for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) { - Block block = lir.linearScanOrder().get(i); - assert trace("start block %s", block); - assert block.phis == null : "Register assignment must run after phi functions have been replaced by moves"; - - curRegisterRefMap = frameMap.initRegisterRefMap(); - curFrameRefMap = frameMap.initFrameRefMap(); - - // Put all values live at the end of the block into the reference map. - locationsForBlockEnd(block).forEachLocation(setReferenceProc); - - for (int j = block.lir.size() - 1; j >= 0; j--) { - LIRInstruction op = block.lir.get(j); - assert trace(" op %d %s", op.id(), op); - - op.forEachOutput(defProc); - op.forEachTemp(defProc); - op.forEachState(useProc); - op.forEachAlive(useProc); - - if (op.info != null) { - assert trace(" registerRefMap: %s frameRefMap: %s", curRegisterRefMap, curFrameRefMap); - op.info.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap); - - if (op instanceof LIRXirInstruction) { - LIRXirInstruction xir = (LIRXirInstruction) op; - if (xir.infoAfter != null) { - xir.infoAfter.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap); - } - } - } - - // 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. - op.forEachInput(useProc); - } - assert trace("end block %s", block); - } - assert trace("==== end assign registers ===="); - } - - private CiValue use(CiValue value) { - assert trace(" use %s", value); - if (isLocation(value)) { - CiValue location = asLocation(value).location; - frameMap.setReference(location, curRegisterRefMap, curFrameRefMap); - return location; - } else { - frameMap.setReference(value, curRegisterRefMap, curFrameRefMap); - return value; - } - } - - private CiValue def(CiValue value) { - assert trace(" def %s", value); - if (isLocation(value)) { - CiValue location = asLocation(value).location; - frameMap.clearReference(location, curRegisterRefMap, curFrameRefMap); - return location; - } else { - frameMap.clearReference(value, curRegisterRefMap, curFrameRefMap); - return value; - } - } - - private CiValue setReference(CiValue value) { - assert trace(" setReference %s", value); - frameMap.setReference(asLocation(value).location, curRegisterRefMap, curFrameRefMap); - return value; - } - - protected abstract LocationMap locationsForBlockEnd(Block block); - - private static boolean trace(String format, Object...args) { - if (GraalOptions.TraceRegisterAllocation) { - TTY.println(format, args); - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.simple; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.alloc.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; - -public class DataFlowAnalysis { - private final LIR lir; - private final RiRegisterConfig registerConfig; - - public DataFlowAnalysis(LIR lir, RiRegisterConfig registerConfig) { - this.lir = lir; - this.registerConfig = registerConfig; - } - - public void execute() { - numberInstructions(); - backwardDataFlow(); - } - - - private List<Block> blocks() { - return lir.linearScanOrder(); - } - - private int numVariables() { - return lir.numVariables(); - } - - private boolean isAllocatableRegister(CiValue value) { - return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; - } - - - private int[] definitions; - private BitSet[] blockLiveIn; - private Block[] opIdBlock; - private Object[] opIdKilledValues; - - - public BitSet liveIn(Block block) { - return blockLiveIn[block.getId()]; - } - private void setLiveIn(Block block, BitSet liveIn) { - blockLiveIn[block.getId()] = liveIn; - } - - private Block blockOf(int opId) { - return opIdBlock[opId >> 1]; - } - private void setBlockOf(int opId, Block block) { - opIdBlock[opId >> 1] = block; - } - - private Object killedValues(int opId) { - return opIdKilledValues[opId]; - } - private void setKilledValues(int opId, Object killedValues) { - opIdKilledValues[opId] = killedValues; - } - - public void forEachKilled(LIRInstruction op, boolean end, ValueProcedure proc) { - Object entry = killedValues(op.id() + (end ? 1 : 0)); - if (entry == null) { - // Nothing to do - } else if (entry instanceof CiValue) { - CiValue newValue = proc.doValue((CiValue) entry, null, null); - assert newValue == entry : "procedure does not allow to change values"; - } else { - CiValue[] values = (CiValue[]) entry; - for (int i = 0; i < values.length; i++) { - if (values[i] != null) { - CiValue newValue = proc.doValue(values[i], null, null); - assert newValue == values[i] : "procedure does not allow to change values"; - } - } - } - } - - public int definition(Variable value) { - return definitions[value.index]; - } - - /** - * Numbers all instructions in all blocks. The numbering follows the {@linkplain ComputeLinearScanOrder linear scan order}. - */ - private void numberInstructions() { - ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setDef(value); } }; - - int numInstructions = 0; - for (Block block : blocks()) { - numInstructions += block.lir.size(); - } - opIdBlock = new Block[numInstructions]; - opIdKilledValues = new Object[numInstructions << 1]; - definitions = new int[numVariables()]; - - curOpId = 0; - for (Block block : blocks()) { - if (block.phis != null) { - block.phis.forEachOutput(defProc); - } - - for (LIRInstruction op : block.lir) { - op.setId(curOpId); - setBlockOf(curOpId, block); - - op.forEachTemp(defProc); - op.forEachOutput(defProc); - - curOpId += 2; // numbering of lirOps by two - } - } - assert curOpId == numInstructions << 1; - } - - private CiValue setDef(CiValue value) { - if (isVariable(value)) { - assert definitions[asVariable(value).index] == 0 : "Variable defined twice"; - definitions[asVariable(value).index] = curOpId; - } - return value; - } - - - private BitSet variableLive; - private BitSet registerLive; - private int curOpId; - - private void backwardDataFlow() { - ValueProcedure inputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } }; - ValueProcedure aliveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } }; - PhiValueProcedure phiInputProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, -1); } }; - ValueProcedure tempProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, true); } }; - ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, false); } }; - - blockLiveIn = new BitSet[blocks().size()]; - registerLive = new BitSet(); - - assert trace("==== start backward data flow analysis ===="); - for (int i = blocks().size() - 1; i >= 0; i--) { - Block block = blocks().get(i); - assert trace("start block %s loop %s", block, block.getLoop()); - - variableLive = new BitSet(); - for (Block sux : block.getSuccessors()) { - BitSet suxLive = liveIn(sux); - if (suxLive != null) { - assert trace(" sux %s suxLive: %s", sux, suxLive); - variableLive.or(suxLive); - } - - if (sux.phis != null) { - curOpId = block.getLastLirInstructionId(); - assert trace(" phis %d variableLive: %s", curOpId, variableLive); - sux.phis.forEachInput(block, phiInputProc); - } - } - - assert registerLive.isEmpty() : "no fixed register must be alive before processing a block"; - - for (int j = block.lir.size() - 1; j >= 0; j--) { - LIRInstruction op = block.lir.get(j); - curOpId = op.id(); - assert trace(" op %d %s variableLive: %s registerLive: %s", curOpId, op, variableLive, registerLive); - - op.forEachOutput(outputProc); - op.forEachTemp(tempProc); - op.forEachState(aliveProc); - op.forEachAlive(aliveProc); - op.forEachInput(inputProc); - } - - if (block.phis != null) { - curOpId = block.getFirstLirInstructionId(); - assert trace(" phis %d variableLive: %s registerLive: %s", curOpId, variableLive, registerLive); - block.phis.forEachOutput(outputProc); - } - - assert registerLive.isEmpty() : "no fixed register must be alive after processing a block"; - assert liveIn(block) == null; - setLiveIn(block, variableLive); - - if (block.isLoopHeader()) { - assert trace(" loop header, propagating live set to loop blocks variableLive: %s", variableLive); - // All variables that are live at the beginning of a loop are also live the whole loop. - // This is guaranteed by the SSA form. - for (Block loop : block.getLoop().blocks) { - BitSet loopLiveIn = liveIn(loop); - assert loopLiveIn != null : "All loop blocks must have been processed before the loop header"; - loopLiveIn.or(variableLive); - assert trace(" block %s loopLiveIn %s", loop, loopLiveIn); - } - } - - assert trace("end block %s variableLive: %s", block, variableLive); - } - assert trace("==== end backward data flow analysis ===="); - } - - private CiValue use(CiValue value, int killOpId) { - assert trace(" use %s", value); - if (isVariable(value)) { - int variableIdx = asVariable(value).index; - assert definitions[variableIdx] < curOpId; - if (!variableLive.get(variableIdx)) { - assert trace(" set live variable %d", variableIdx); - variableLive.set(variableIdx); - kill(value, killOpId); - } - - } else if (isAllocatableRegister(value)) { - int regNum = asRegister(value).number; - if (!registerLive.get(regNum)) { - assert trace(" set live register %d", regNum); - registerLive.set(regNum); - kill(value, killOpId); - } - } - return value; - } - - private CiValue def(CiValue value, boolean isTemp) { - assert trace(" def %s", value); - if (isVariable(value)) { - int variableIdx = asVariable(value).index; - assert definitions[variableIdx] == curOpId; - if (variableLive.get(variableIdx)) { - assert trace(" clear live variable %d", variableIdx); - assert !isTemp : "temp variable cannot be used after the operation"; - variableLive.clear(variableIdx); - } else { - // Variable has never been used, so kill it immediately after the definition. - kill(value, curOpId + 1); - } - - } else if (isAllocatableRegister(value)) { - int regNum = asRegister(value).number; - if (registerLive.get(regNum)) { - assert trace(" clear live register %d", regNum); - assert !isTemp : "temp variable cannot be used after the operation"; - registerLive.clear(regNum); - } else { - // Register has never been used, so kill it immediately after the definition. - kill(value, curOpId + 1); - } - } - return value; - } - - private void kill(CiValue value, int opId) { - if (opId < 0) { - return; - } - if (isVariable(value)) { - int defOpId = definitions[asVariable(value).index]; - assert defOpId > 0 && defOpId <= opId; - - Block defBlock = blockOf(defOpId); - Block useBlock = blockOf(opId); - - if (useBlock.getLoop() != null && useBlock.getLoop() != defBlock.getLoop()) { - // This is a value defined outside of the loop it is currently used in. Therefore, it is live the whole loop - // and is not killed by the current instruction. - assert trace(" no kill because use in %s, definition in %s", useBlock.getLoop(), defBlock.getLoop()); - return; - } - } - assert trace(" kill %s at %d", value, opId); - - Object entry = killedValues(opId); - if (entry == null) { - setKilledValues(opId, value); - } else if (entry instanceof CiValue) { - setKilledValues(opId, new CiValue[] {(CiValue) entry, value}); - } else { - CiValue[] killed = (CiValue[]) entry; - for (int i = 0; i < killed.length; i++) { - if (killed[i] == null) { - killed[i] = value; - return; - } - } - int oldLen = killed.length; - killed = Arrays.copyOf(killed, oldLen * 2); - setKilledValues(opId, killed); - killed[oldLen] = value; - } - } - - private static boolean trace(String format, Object...args) { - if (GraalOptions.TraceRegisterAllocation) { - TTY.println(format, args); - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,604 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.simple; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiRegister.RegisterFlag; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.alloc.util.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.debug.*; - -public class LinearScanAllocator { - private final LIR lir; - private final FrameMap frameMap; - - private final DataFlowAnalysis dataFlow; - - public LinearScanAllocator(LIR lir, FrameMap frameMap) { - this.lir = lir; - this.frameMap = frameMap; - - this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig); - this.blockBeginLocations = new LocationMap[lir.linearScanOrder().size()]; - this.blockEndLocations = new LocationMap[lir.linearScanOrder().size()]; - this.moveResolver = new MoveResolverImpl(lir, frameMap); - - this.variableLastUse = new int[lir.numVariables()]; - } - - private class MoveResolverImpl extends MoveResolver { - public MoveResolverImpl(LIR lir, FrameMap frameMap) { - super(lir, frameMap); - } - - @Override - protected CiValue scratchRegister(Variable spilled) { - Util.shouldNotReachHere("needs working implementation"); - - EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); - CiRegister[] availableRegs = categorizedRegs.get(spilled.flag); - for (CiRegister reg : availableRegs) { - if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) { - return reg.asValue(spilled.kind); - } - } - throw new CiBailout("No register found"); - } - } - - private class ResolveDataFlowImpl extends ResolveDataFlow { - public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) { - super(lir, moveResolver, dataFlow); - } - - @Override - protected LocationMap locationsForBlockBegin(Block block) { - return beginLocationsFor(block); - } - - @Override - protected LocationMap locationsForBlockEnd(Block block) { - return endLocationsFor(block); - } - } - - private class AssignRegistersImpl extends AssignRegisters { - public AssignRegistersImpl(LIR lir, FrameMap frameMap) { - super(lir, frameMap); - } - - @Override - protected LocationMap locationsForBlockEnd(Block block) { - return endLocationsFor(block); - } - } - - - private int maxRegisterNum() { - return frameMap.target.arch.registers.length; - } - - private boolean isAllocatableRegister(CiValue value) { - return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; - } - - - private final LocationMap[] blockBeginLocations; - - private LocationMap beginLocationsFor(Block block) { - return blockBeginLocations[block.getId()]; - } - private void setBeginLocationsFor(Block block, LocationMap locations) { - blockBeginLocations[block.getId()] = locations; - } - - private final LocationMap[] blockEndLocations; - - private LocationMap endLocationsFor(Block block) { - return blockEndLocations[block.getId()]; - } - private void setEndLocationsFor(Block block, LocationMap locations) { - blockEndLocations[block.getId()] = locations; - } - - private final int[] variableLastUse; - - private int lastUseFor(Variable variable) { - return variableLastUse[variable.index]; - } - - private void setLastUseFor(Variable variable, int lastUse) { - variableLastUse[variable.index] = lastUse; - } - - private MoveResolver moveResolver; - private LocationMap curLocations; - private CiValue[] curInRegisterState; - private CiValue[] curOutRegisterState; - private BitSet curLiveIn; - private int curOpId; - private Block curPhiBlock; - - private LocationMap canonicalSpillLocations; - - public void execute() { - assert LIRVerifier.verify(true, lir, frameMap); - - dataFlow.execute(); - IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow); - - allocate(); - - IntervalPrinter.printAfterAllocation("After linear scan allocation", lir, frameMap.registerConfig, dataFlow, blockEndLocations); - - ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow); - resolveDataFlow.execute(); - frameMap.finish(); - - IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockEndLocations); - assert RegisterVerifier.verify(lir, frameMap); - - AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap); - assignRegisters.execute(); - - Debug.dump(lir, "After register asignment"); - assert LIRVerifier.verify(false, lir, frameMap); - } - - private void allocate() { - ValueProcedure recordUseProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return recordUse(value, mode); } }; - ValueProcedure killNonLiveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } }; - ValueProcedure unblockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return unblock(value); } }; - ValueProcedure killProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value); } }; - ValueProcedure blockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } }; - PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } }; - ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } }; - - assert trace("==== start linear scan allocation ===="); - canonicalSpillLocations = new LocationMap(lir.numVariables()); - curInRegisterState = new CiValue[maxRegisterNum()]; - curOutRegisterState = new CiValue[maxRegisterNum()]; - for (Block block : lir.linearScanOrder()) { - assert trace("start block %s %s", block, block.getLoop()); - - Arrays.fill(curOutRegisterState, null); - if (block.getDominator() != null) { - LocationMap dominatorState = endLocationsFor(block.getDominator()); - curLocations = new LocationMap(dominatorState); - // Clear out all variables that are not live at the begin of this block - curLiveIn = dataFlow.liveIn(block); - curLocations.forEachLocation(killNonLiveProc); - assert checkInputState(block); - } else { - curLocations = new LocationMap(lir.numVariables()); - } - assert traceState(); - - if (block.phis != null) { - assert trace(" phis"); - curPhiBlock = block; - curOpId = block.getFirstLirInstructionId(); - block.phis.forEachOutput(defProc); - curOpId = -1; - curPhiBlock = null; - } - - setBeginLocationsFor(block, new LocationMap(curLocations)); - - for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) { - LIRInstruction op = block.lir.get(opIdx); - curOpId = op.id(); - assert trace(" op %d %s", op.id(), op); - - System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length); - - // Unblock fixed registers that are only used for inputs in curOutRegisterState. - dataFlow.forEachKilled(op, false, unblockProc); - // Block fixed registers defined by this instruction in curOutRegisterState. - op.forEachTemp(blockProc); - op.forEachOutput(blockProc); - - op.forEachInput(recordUseProc); - op.forEachAlive(recordUseProc); - - moveResolver.init(block.lir, opIdx); - // Process Alive before Input because they are more restricted and the same variable can be Alive and Input. - op.forEachAlive(useProc); - op.forEachInput(useProc); - - dataFlow.forEachKilled(op, false, killProc); - - if (op.hasCall()) { - spillCallerSaveRegisters(); - } - - op.forEachTemp(defProc); - op.forEachOutput(defProc); - - // Fixed temp and output registers can evict variables from their assigned register, allocate new location for them. - fixupEvicted(); - // State values are the least critical and can get the leftover registers (or stack slots if no more register available). - op.forEachState(useProc); - - - moveResolver.resolve(); - - dataFlow.forEachKilled(op, true, unblockProc); - dataFlow.forEachKilled(op, true, killProc); - -// curInstruction = null; - curOpId = -1; - } - - for (Block sux : block.getSuccessors()) { - if (sux.phis != null) { - assert trace(" phis of successor %s", sux); - System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length); - curOpId = block.getLastLirInstructionId() + 1; - sux.phis.forEachInput(block, useProc); - curOpId = -1; - } - } - - assert endLocationsFor(block) == null; - setEndLocationsFor(block, curLocations); - - traceState(); - assert trace("end block %s", block); - } - - moveResolver.finish(); - assert trace("==== end linear scan allocation ===="); - } - - private CiValue killNonLive(CiValue value) { - assert isLocation(value); - if (!curLiveIn.get(asLocation(value).variable.index)) { - return null; - - } else if (isAllocatableRegister(asLocation(value).location)) { - int regNum = asRegister(asLocation(value).location).number; - assert curOutRegisterState[regNum] == null; - curOutRegisterState[regNum] = value; - } - return value; - } - - private CiValue unblock(CiValue value) { - if (isAllocatableRegister(value)) { - assert trace(" unblock register %s", value); - int regNum = asRegister(value).number; - assert curOutRegisterState[regNum] == value; - curOutRegisterState[regNum] = null; - } - return value; - } - - private CiValue kill(CiValue value) { - if (isVariable(value)) { - Location location = curLocations.get(asVariable(value)); - assert trace(" kill location %s", location); - if (isRegister(location.location)) { - int regNum = asRegister(location.location).number; - if (curOutRegisterState[regNum] == location) { - curOutRegisterState[regNum] = null; - } - } - curLocations.clear(asVariable(value)); - } - return value; - } - - - private CiValue block(CiValue value) { - if (isAllocatableRegister(value)) { - assert trace(" block %s", value); - int regNum = asRegister(value).number; - assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof Location; - curOutRegisterState[regNum] = value; - } - return value; - } - - private void spillCallerSaveRegisters() { - assert trace(" spill caller save registers in curInRegisterState %s", Arrays.toString(curInRegisterState)); - for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) { - CiValue in = curInRegisterState[reg.number]; - if (in != null && isLocation(in)) { - spill(asLocation(in)); - } - } - } - - private CiValue recordUse(CiValue value, OperandMode mode) { - if (isVariable(value)) { - int id = mode == OperandMode.Input ? curOpId : curOpId + 1; - assert lastUseFor(asVariable(value)) <= id; - setLastUseFor(asVariable(value), id); - - } - return value; - } - - private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - assert mode == OperandMode.Input || 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, mode); - - Location curLoc = curLocations.get(asVariable(value)); - if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.Stack)) { - assert trace(" 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) { - assert trace(" use %s %s: use current register %s", mode, value, curLoc.location); - return curLoc; - } - } - - assert trace(" use %s %s", mode, value); - - Location newLoc = allocateRegister(asVariable(value), mode, flags); - if (newLoc != curLoc) { - moveResolver.add(curLoc, newLoc); - } - return newLoc; - } else { - assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] == value; - } - return value; - } - - private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - - private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - assert mode == OperandMode.Temp || mode == OperandMode.Output; - if (isVariable(value)) { - assert trace(" def %s %s", mode, value); - assert curLocations.get(asVariable(value)) == null; - - Location newLoc = allocateRegister(asVariable(value), mode, flags); - return newLoc; - } - return value; - } - - - private void fixupEvicted() { - for (int i = 0; i < curInRegisterState.length; i++) { - CiValue in = curInRegisterState[i]; - CiValue out = curOutRegisterState[i]; - - if (in != null && in != out && isLocation(in) && curLocations.get(asLocation(in).variable) == in) { - assert trace(" %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); - assert oldLoc != newLoc; - moveResolver.add(oldLoc, newLoc); - } - - - } - } - - - private Location allocateRegister(final Variable variable, OperandMode mode, EnumSet<OperandFlag> flags) { -// if (flags.contains(OperandFlag.RegisterHint)) { -// CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() { -// @Override -// public CiValue doValue(CiValue registerHint) { -// assert trace(" registerHint %s", registerHint); -// CiRegister hint = null; -// if (isRegister(registerHint)) { -// hint = asRegister(registerHint); -// } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) { -// hint = asRegister(asLocation(registerHint).location); -// } -// if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) { -// return selectRegister(hint, variable, inRegisterState, outRegisterState); -// } -// return null; -// } -// }); -// -// if (result != null) { -// return asLocation(result); -// } -// } -// - EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); - CiRegister[] availableRegs = categorizedRegs.get(variable.flag); - - Location bestSpillCandidate = null; - for (CiRegister reg : availableRegs) { - if (isFree(reg, mode)) { - return selectRegister(reg, variable, mode); - } else { - Location spillCandidate = spillCandidate(reg); - if (betterSpillCandidate(spillCandidate, bestSpillCandidate)) { - bestSpillCandidate = spillCandidate; - } - } - } - - if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) { - return selectSpillSlot(variable, mode); - } - - if (bestSpillCandidate == null) { - if (curPhiBlock != null) { - return selectSpillSlot(variable, mode); - } - // This should not happen as long as all LIR instructions have fulfillable register constraints. But be safe in product mode and bail out. - assert false; - throw new CiBailout("No register available"); - } - - spill(bestSpillCandidate); - - return selectRegister(asRegister(bestSpillCandidate.location), variable, mode); - } - - private void spill(Location value) { - Location newLoc = spillLocation(value.variable); - assert trace(" spill %s to %s", value, newLoc); - if (curPhiBlock == null) { - moveResolver.add(value, newLoc); - } - curLocations.put(newLoc); - - CiRegister reg = asRegister(value.location); - assert curInRegisterState[reg.number] == value; - curInRegisterState[reg.number] = null; - if (curOutRegisterState[reg.number] == value) { - curOutRegisterState[reg.number] = null; - } - } - - private boolean isFree(CiRegister 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 Util.shouldNotReachHere(); - } - } - - private Location spillCandidate(CiRegister reg) { - CiValue in = curInRegisterState[reg.number]; - CiValue out = curOutRegisterState[reg.number]; - if (in == out && in != null && isLocation(in) && lastUseFor(asLocation(in).variable) < curOpId) { - return asLocation(in); - } - return null; - } - - private boolean betterSpillCandidate(Location loc, Location compare) { - if (loc == null) { - return false; - } - if (compare == null) { - return true; - } - if (canonicalSpillLocations.get(loc.variable) != null && canonicalSpillLocations.get(compare.variable) == null) { - return true; - } - return dataFlow.definition(loc.variable) < dataFlow.definition(compare.variable); - } - - private Location spillLocation(Variable variable) { - Location result = canonicalSpillLocations.get(variable); - if (result == null) { - result = new Location(variable, frameMap.allocateSpillSlot(variable.kind)); - canonicalSpillLocations.put(result); - } - return result; - } - - private Location selectRegister(CiRegister reg, Variable variable, OperandMode mode) { - assert isFree(reg, mode); - - Location loc = new Location(variable, reg.asValue(variable.kind)); - if (mode == OperandMode.Input || mode == OperandMode.Alive) { - curInRegisterState[reg.number] = loc; - } - curOutRegisterState[reg.number] = loc; - curLocations.put(loc); - recordUse(variable, mode); - - assert trace(" selected register %s", loc); - return loc; - } - - private Location selectSpillSlot(Variable variable, OperandMode mode) { - Location loc = spillLocation(variable); - curLocations.put(loc); - recordUse(variable, mode); - - assert trace(" selected spill slot %s", loc); - return loc; - } - - private boolean checkInputState(final Block block) { - final BitSet liveState = new BitSet(); - curLocations.forEachLocation(new ValueProcedure() { - @Override - public CiValue doValue(CiValue value) { - liveState.set(asLocation(value).variable.index); - - for (Block pred : block.getPredecessors()) { - LocationMap predState = endLocationsFor(pred); - if (predState != null) { - assert predState.get(asLocation(value).variable) != null; - } else { - assert block.isLoopHeader(); - } - } - return value; - } - }); - assert liveState.equals(curLiveIn); - return true; - } - - - private boolean traceState() { - if (GraalOptions.TraceRegisterAllocation) { - TTY.print(" current lcoations: "); - curLocations.forEachLocation(new ValueProcedure() { - @Override - public CiValue doValue(CiValue value) { - TTY.print("%s ", value); - return value; - } - }); - TTY.println(); - } - return true; - } - - private static boolean trace(String format, Object...args) { - if (GraalOptions.TraceRegisterAllocation) { - TTY.println(format, args); - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.simple; - -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.alloc.util.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.util.*; - -public abstract class ResolveDataFlow { - public final LIR lir; - public final MoveResolver moveResolver; - public final DataFlowAnalysis dataFlow; - - public ResolveDataFlow(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) { - this.lir = lir; - this.moveResolver = moveResolver; - this.dataFlow = dataFlow; - } - - private Block curToBlock; - private LocationMap curFromLocations; - - public void execute() { - ValueProcedure locMappingProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return locMapping(value); } }; - PhiValueProcedure phiMappingProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue input, CiValue output) { return phiMapping(input, output); } }; - - assert trace("==== start resolve data flow ===="); - for (Block toBlock : lir.linearScanOrder()) { - curToBlock = toBlock; - - for (Block fromBlock : toBlock.getPredecessors()) { - assert trace("start edge %s -> %s", fromBlock, toBlock); - findInsertPos(fromBlock, toBlock); - - LocationMap toLocations = locationsForBlockBegin(toBlock); - curFromLocations = locationsForBlockEnd(fromBlock); - if (toLocations != curFromLocations) { - toLocations.forEachLocation(locMappingProc); - } - - if (toBlock.phis != null) { - toBlock.phis.forEachInput(fromBlock, phiMappingProc); - } - - moveResolver.resolve(); - assert trace("end edge %s -> %s", fromBlock, toBlock); - } - - // Phi functions are resolved with moves now, so delete them. - toBlock.phis = null; - } - moveResolver.finish(); - assert trace("==== end resolve data flow ===="); - } - - private CiValue locMapping(CiValue value) { - Location to = asLocation(value); - Location from = curFromLocations.get(to.variable); - if (value != from && dataFlow.liveIn(curToBlock).get(to.variable.index)) { - moveResolver.add(from, to); - } - return value; - } - - private CiValue phiMapping(CiValue input, CiValue output) { - if (input != output) { - moveResolver.add(input, asLocation(output)); - } - return input; - } - - private void findInsertPos(Block fromBlock, Block toBlock) { - assert fromBlock.getSuccessors().contains(toBlock) && toBlock.getPredecessors().contains(fromBlock); - - if (fromBlock.numberOfSux() == 1) { - List<LIRInstruction> instructions = fromBlock.lir; - LIRInstruction instr = instructions.get(instructions.size() - 1); - assert instr instanceof StandardOp.JumpOp : "block does not end with an unconditional jump"; - moveResolver.init(instructions, instructions.size() - 1); - assert trace(" insert at end of %s before %d", fromBlock, instructions.size() - 1); - - } else if (toBlock.numberOfPreds() == 1) { - moveResolver.init(toBlock.lir, 1); - assert trace(" insert at beginning of %s before %d", toBlock, 1); - - } else { - Util.shouldNotReachHere("Critical edge not split"); - } - } - - protected abstract LocationMap locationsForBlockBegin(Block block); - protected abstract LocationMap locationsForBlockEnd(Block block); - - - private static boolean trace(String format, Object...args) { - if (GraalOptions.TraceRegisterAllocation) { - TTY.println(format, args); - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,495 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.simple; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiRegister.RegisterFlag; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.alloc.util.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.debug.*; - -public class SpillAllAllocator { - private final LIR lir; - private final FrameMap frameMap; - - private final DataFlowAnalysis dataFlow; - - public SpillAllAllocator(LIR lir, FrameMap frameMap) { - this.lir = lir; - this.frameMap = frameMap; - - this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig); - this.blockLocations = new LocationMap[lir.linearScanOrder().size()]; - this.moveResolver = new MoveResolverImpl(lir, frameMap); - } - - private class MoveResolverImpl extends MoveResolver { - public MoveResolverImpl(LIR lir, FrameMap frameMap) { - super(lir, frameMap); - } - - @Override - protected CiValue scratchRegister(Variable spilled) { - EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); - CiRegister[] availableRegs = categorizedRegs.get(spilled.flag); - for (CiRegister reg : availableRegs) { - if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) { - return reg.asValue(spilled.kind); - } - } - throw new CiBailout("No register found"); - } - } - - private class ResolveDataFlowImpl extends ResolveDataFlow { - public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver, DataFlowAnalysis dataFlow) { - super(lir, moveResolver, dataFlow); - } - - @Override - protected LocationMap locationsForBlockBegin(Block block) { - assert block.numberOfPreds() > 0 && block.getDominator() != null; - return locationsFor(block.getDominator()); - } - - @Override - protected LocationMap locationsForBlockEnd(Block block) { - return locationsFor(block); - } - } - - private class AssignRegistersImpl extends AssignRegisters { - public AssignRegistersImpl(LIR lir, FrameMap frameMap) { - super(lir, frameMap); - } - - @Override - protected LocationMap locationsForBlockEnd(Block block) { - return locationsFor(block); - } - } - - - private int maxRegisterNum() { - return frameMap.target.arch.registers.length; - } - - private boolean isAllocatableRegister(CiValue value) { - return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; - } - - - private final LocationMap[] blockLocations; - - private LocationMap locationsFor(Block block) { - return blockLocations[block.getId()]; - } - private void setLocationsFor(Block block, LocationMap locations) { - blockLocations[block.getId()] = locations; - } - - private MoveResolver moveResolver; - private LocationMap curStackLocations; - private LocationMap curRegisterLocations; - private Object[] curInRegisterState; - private Object[] curOutRegisterState; - private BitSet curLiveIn; - private LIRInstruction curInstruction; - - public void execute() { - assert LIRVerifier.verify(true, lir, frameMap); - - dataFlow.execute(); - IntervalPrinter.printBeforeAllocation("Before register allocation", lir, frameMap.registerConfig, dataFlow); - - allocate(); - - IntervalPrinter.printAfterAllocation("After spill all allocation", lir, frameMap.registerConfig, dataFlow, blockLocations); - - ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver, dataFlow); - resolveDataFlow.execute(); - frameMap.finish(); - - IntervalPrinter.printAfterAllocation("After resolve data flow", lir, frameMap.registerConfig, dataFlow, blockLocations); - assert RegisterVerifier.verify(lir, frameMap); - - AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap); - assignRegisters.execute(); - - Debug.dump(lir, "After register asignment"); - assert LIRVerifier.verify(false, lir, frameMap); - } - - private void allocate() { - ValueProcedure killNonLiveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } }; - ValueProcedure killBeginProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, false); } }; - ValueProcedure killEndProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, true); } }; - ValueProcedure killLocationProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killLocation(value); } }; - ValueProcedure blockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } }; - ValueProcedure loadProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return load(value, mode, flags); } }; - ValueProcedure spillProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return spill(value, mode, flags); } }; - PhiValueProcedure useSlotProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } }; - ValueProcedure defSlotProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return defSlot(value); } }; - - assert trace("==== start spill all allocation ===="); - curInRegisterState = new Object[maxRegisterNum()]; - curOutRegisterState = new Object[maxRegisterNum()]; - curRegisterLocations = new LocationMap(lir.numVariables()); - for (Block block : lir.linearScanOrder()) { - assert trace("start block %s %s", block, block.getLoop()); - assert checkEmpty(curOutRegisterState); - - if (block.getDominator() != null) { - LocationMap dominatorState = locationsFor(block.getDominator()); - curStackLocations = new LocationMap(dominatorState); - // Clear out all variables that are not live at the begin of this block - curLiveIn = dataFlow.liveIn(block); - curStackLocations.forEachLocation(killNonLiveProc); - assert checkInputState(block); - } else { - curStackLocations = new LocationMap(lir.numVariables()); - } - assert traceState(); - - if (block.phis != null) { - assert trace(" phis"); - block.phis.forEachOutput(defSlotProc); - } - - for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) { - LIRInstruction op = block.lir.get(opIdx); - curInstruction = op; - assert trace(" op %d %s", op.id(), op); - - assert curRegisterLocations.checkEmpty(); - - System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length); - - // Block fixed registers that are defined by this instruction, so that they are no longer available for normal allocation. - op.forEachTemp(blockProc); - op.forEachOutput(blockProc); - - moveResolver.init(block.lir, opIdx); - // Process Alive before Input because they are more restricted and the same variable can be Alive and Input. - op.forEachAlive(loadProc); - op.forEachInput(loadProc); - moveResolver.resolve(); - op.forEachState(useSlotProc); - - dataFlow.forEachKilled(op, false, killBeginProc); - assert !op.hasCall() || checkNoCallerSavedRegister() : "caller saved register in use accross call site"; - - moveResolver.init(block.lir, opIdx + 1); - op.forEachTemp(spillProc); - op.forEachOutput(spillProc); - moveResolver.resolve(); - - dataFlow.forEachKilled(op, true, killEndProc); - curRegisterLocations.forEachLocation(killLocationProc); - - assert curRegisterLocations.checkEmpty(); - curInstruction = null; - } - assert checkEmpty(curOutRegisterState); - - for (Block sux : block.getSuccessors()) { - if (sux.phis != null) { - assert trace(" phis of successor %s", sux); - sux.phis.forEachInput(block, useSlotProc); - } - } - - assert checkEmpty(curOutRegisterState); - assert locationsFor(block) == null; - setLocationsFor(block, curStackLocations); - - traceState(); - assert trace("end block %s", block); - } - - moveResolver.finish(); - assert trace("==== end spill all allocation ===="); - } - - private CiValue killNonLive(CiValue value) { - assert isLocation(value); - if (!curLiveIn.get(asLocation(value).variable.index)) { - return null; - } - return value; - } - - private CiValue kill(CiValue value, boolean end) { - if (isVariable(value)) { - assert trace(" kill variable %s", value); - - Variable variable = asVariable(value); - curStackLocations.clear(variable); - - Location loc = curRegisterLocations.get(variable); - if (loc != null) { - killLocation(loc); - curRegisterLocations.clear(variable); - - assert trace(" location %s", loc); - assert isAllocatableRegister(loc.location); - - int regNum = asRegister(loc.location).number; - if (curOutRegisterState[regNum] == loc) { - curOutRegisterState[regNum] = null; - } - } - - } else if (isAllocatableRegister(value)) { - assert trace(" kill register %s", value); - int regNum = asRegister(value).number; - assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction && curInstruction != null; - - if (end || curOutRegisterState[regNum] != curInstruction) { - curOutRegisterState[regNum] = null; - } - - } else { - throw Util.shouldNotReachHere(); - } - return value; - } - - private CiValue killLocation(CiValue value) { - assert trace(" kill location %s", value); - assert isAllocatableRegister(asLocation(value).location); - - int regNum = asRegister(asLocation(value).location).number; - if (curOutRegisterState[regNum] == value) { - curOutRegisterState[regNum] = null; - } - return null; - } - - private CiValue block(CiValue value) { - if (isAllocatableRegister(value)) { - assert trace(" block %s", value); - int regNum = asRegister(value).number; - assert curInstruction != null; - assert curOutRegisterState[regNum] == null || curOutRegisterState[regNum] instanceof LIRInstruction; - curOutRegisterState[regNum] = curInstruction; - } - return value; - } - - private CiValue load(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - assert mode == OperandMode.Input || mode == OperandMode.Alive; - if (flags.contains(OperandFlag.Stack)) { - return useSlot(value); - } - if (isVariable(value)) { - assert trace(" load %s", value); - Location regLoc = curRegisterLocations.get(asVariable(value)); - if (regLoc != null) { - // This variable has already been processed before. - assert trace(" found location %s", regLoc); - } else { - 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); - } - return regLoc; - } else { - assert !isAllocatableRegister(value) || curInRegisterState[asRegister(value).number] instanceof LIRInstruction; - return value; - } - } - - private CiValue spill(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - assert mode == OperandMode.Temp || mode == OperandMode.Output; - if (flags.contains(OperandFlag.Stack)) { - return defSlot(value); - } - if (isVariable(value)) { - assert trace(" spill %s", value); - assert curStackLocations.get(asVariable(value)) == null; - Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState, mode, flags); - if (mode == OperandMode.Output) { - Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind)); - curStackLocations.put(stackLoc); - moveResolver.add(regLoc, stackLoc); - } - return regLoc; - } else { - assert !isAllocatableRegister(value) || curOutRegisterState[asRegister(value).number] == curInstruction && curInstruction != null; - return value; - } - } - - private CiValue useSlot(CiValue value) { - if (isVariable(value)) { - assert trace(" useSlot %s", value); - Location stackLoc = curStackLocations.get(asVariable(value)); - assert stackLoc != null; - assert trace(" slot %s", stackLoc); - return stackLoc; - } else { - return value; - } - } - - private CiValue defSlot(CiValue value) { - if (isVariable(value)) { - assert trace(" assignSlot %s", value); - Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind)); - assert curStackLocations.get(asVariable(value)) == null; - curStackLocations.put(stackLoc); - assert trace(" slot %s", stackLoc); - return stackLoc; - } else { - return value; - } - } - - private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet<OperandFlag> flags) { - if (flags.contains(OperandFlag.RegisterHint)) { - CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() { - @Override - public CiValue doValue(CiValue registerHint) { - assert trace(" registerHint %s", registerHint); - CiRegister hint = null; - if (isRegister(registerHint)) { - hint = asRegister(registerHint); - } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) { - hint = asRegister(asLocation(registerHint).location); - } - if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) { - return selectRegister(hint, variable, inRegisterState, outRegisterState); - } - return null; - } - }); - - if (result != null) { - return asLocation(result); - } - } - - EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = frameMap.registerConfig.getCategorizedAllocatableRegisters(); - CiRegister[] availableRegs = categorizedRegs.get(variable.flag); - - for (CiRegister reg : availableRegs) { - if (isFree(reg, inRegisterState, outRegisterState)) { - return selectRegister(reg, variable, inRegisterState, outRegisterState); - } - - } - throw new CiBailout("No register found"); - } - - private static boolean isFree(CiRegister reg, Object[] inRegisterState, Object[] outRegisterState) { - return (inRegisterState == null || inRegisterState[reg.number] == null) && (outRegisterState == null || outRegisterState[reg.number] == null); - } - - private Location selectRegister(CiRegister reg, Variable variable, Object[] inRegisterState, Object[] outRegisterState) { - Location loc = new Location(variable, reg.asValue(variable.kind)); - if (inRegisterState != null) { - inRegisterState[reg.number] = loc; - } - if (outRegisterState != null) { - outRegisterState[reg.number] = loc; - } - assert curRegisterLocations.get(variable) == null; - curRegisterLocations.put(loc); - assert trace(" selected register %s", loc); - return loc; - } - - private boolean checkInputState(final Block block) { - final BitSet liveState = new BitSet(); - curStackLocations.forEachLocation(new ValueProcedure() { - @Override - public CiValue doValue(CiValue value) { - liveState.set(asLocation(value).variable.index); - - for (Block pred : block.getPredecessors()) { - LocationMap predState = locationsFor(pred); - if (predState != null) { - assert predState.get(asLocation(value).variable) == value; - } else { - assert block.isLoopHeader(); - } - } - return value; - } - }); - assert liveState.equals(curLiveIn); - return true; - } - - private boolean checkNoCallerSavedRegister() { - for (CiRegister reg : frameMap.registerConfig.getCallerSaveRegisters()) { - assert curOutRegisterState[reg.number] == null || curOutRegisterState[reg.number] == curInstruction : "caller saved register in use accross call site"; - } - return true; - } - - private static boolean checkEmpty(Object[] array) { - for (Object o : array) { - assert o == null; - } - return true; - } - - - private boolean traceState() { - if (GraalOptions.TraceRegisterAllocation) { - TTY.print(" curVariableLocations: "); - curStackLocations.forEachLocation(new ValueProcedure() { - @Override - public CiValue doValue(CiValue value) { - TTY.print("%s ", value); - return value; - } - }); - TTY.println(); - } - return true; - } - - private static boolean trace(String format, Object...args) { - if (GraalOptions.TraceRegisterAllocation) { - TTY.println(format, args); - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.alloc.util; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.alloc.simple.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; - -public final class IntervalPrinter { - - @SuppressWarnings("unused") - public static void printBeforeAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow) { - // TODO(tw): Fix printing. -// if (context.isObserved()) { -// IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, null); -// context.observable.fireCompilationEvent(label, lir, printer.execute()); -// } - } - - @SuppressWarnings("unused") - public static void printAfterAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) { - // TODO(tw): Fix printing. -// if (context.isObserved()) { -// IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, blockEndLocations); -// context.observable.fireCompilationEvent(label, lir, printer.execute()); -// } - } - - - public static class Range { - public final int from; - public final int to; - - public Range(int from, int to) { - this.from = from; - this.to = to; - } - } - - public static class UsePosition { - public final int pos; - public final String kind; - - public UsePosition(int pos, String kind) { - this.pos = pos; - this.kind = kind; - } - } - - public static class Interval { - public final String name; - public final String description; - public final String variable; - public final String type; - public final List<Range> ranges; - public final List<UsePosition> uses; - - protected final int orderNum; - protected int lastTo; - - public Interval(int orderNum, String name, String description, String variable, String type) { - this.orderNum = orderNum; - this.name = name; - this.description = description; - this.variable = variable; - this.type = type; - this.ranges = new ArrayList<>(); - this.uses = new ArrayList<>(); - } - } - - - private final LIR lir; - private final RiRegisterConfig registerConfig; - private final DataFlowAnalysis dataFlow; - private final LocationMap[] blockEndLocations; - private final Variable[] variables; - private final Map<String, Interval> intervals; - - private IntervalPrinter(LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) { - this.lir = lir; - this.registerConfig = registerConfig; - this.dataFlow = dataFlow; - this.blockEndLocations = blockEndLocations; - this.variables = new Variable[lir.numVariables()]; - this.intervals = new HashMap<>(); - } - - private boolean isAllocatableRegister(CiValue value) { - return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; - } - - private int curOpId; - private String curUseKind; - - public Interval[] execute() { - ValueProcedure varProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return var(value); } }; - - for (Block block : lir.linearScanOrder()) { - if (block.phis != null) { - block.phis.forEachOutput(varProc); - } - for (LIRInstruction op : block.lir) { - op.forEachOutput(varProc); - } - } - - PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } }; - ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, flags); } }; - - intervals.put("call", new Interval(-2, "call", "", "call", "hasCall")); - intervals.put("st", new Interval(-1, "st", "", "st", "hasState")); - - for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) { - Block block = lir.linearScanOrder().get(i); - - curOpId = block.getLastLirInstructionId() + 2; - for (Block sux : block.getSuccessors()) { - BitSet suxIn = dataFlow.liveIn(sux); - for (int idx = suxIn.nextSetBit(0); idx >= 0; idx = suxIn.nextSetBit(idx + 1)) { - if (blockEndLocations != null) { - out(blockEndLocations[block.getId()].get(variables[idx])); - } else { - out(variables[idx]); - } - } - } - - curOpId = block.getLastLirInstructionId() + 1; - for (Block sux : block.getSuccessors()) { - if (sux.phis != null) { - sux.phis.forEachInput(block, useProc); - } - } - - for (int j = block.lir.size() - 1; j >= 0; j--) { - LIRInstruction op = block.lir.get(j); - if (op.id() >= 0) { - curOpId = op.id(); - } else { - curOpId = (curOpId - 1) | 1; - } - - op.forEachOutput(defProc); - op.forEachTemp(defProc); - op.forEachInput(useProc); - op.forEachAlive(useProc); - curUseKind = "L"; - op.forEachState(useProc); - curUseKind = null; - - if (op.hasCall()) { - intervals.get("call").ranges.add(new Range(curOpId, curOpId + 1)); - } - if (op.info != null) { - intervals.get("st").ranges.add(new Range(curOpId, curOpId + 1)); - } - } - - if (block.phis != null) { - curOpId = block.getFirstLirInstructionId() + 1; - block.phis.forEachOutput(defProc); - } - - for (Interval interval : intervals.values()) { - if (interval.lastTo != 0) { - interval.ranges.add(new Range(block.getFirstLirInstructionId(), interval.lastTo)); - interval.lastTo = 0; - } - } - } - - Interval[] intervalsArray = intervals.values().toArray(new Interval[0]); - Arrays.sort(intervalsArray, new Comparator<Interval>() { - @Override - public int compare(Interval o1, Interval o2) { - return o1.orderNum - o2.orderNum; - } - }); - return intervalsArray; - } - - public CiValue var(CiValue value) { - if (isLocation(value)) { - variables[asLocation(value).variable.index] = asLocation(value).variable; - } else if (isVariable(value)) { - variables[asVariable(value).index] = asVariable(value); - } - return value; - } - - private Interval findInterval(CiValue value) { - Interval interval; - if (isLocation(value)) { - Interval parent = findInterval(asLocation(value).variable); - String name = "v" + asLocation(value).variable.index + ":" + asLocation(value).location; - String description = isStackSlot(asLocation(value).location) ? "stack" : ""; - interval = new Interval(asLocation(value).variable.index * 2 + 1001, name, description, parent.name, value.kind.javaName); - - } else if (isVariable(value)) { - interval = new Interval(asVariable(value).index * 2 + 1000, value.toString(), "", value.toString(), value.kind.javaName); - - } else if (isAllocatableRegister(value)) { - interval = new Interval(asRegister(value).number, asRegister(value).toString(), "", asRegister(value).toString(), "fixed"); - - } else { - return null; - } - - Interval existing = intervals.get(interval.name); - if (existing != null) { - return existing; - } - intervals.put(interval.name, interval); - return interval; - } - - private String useKind(EnumSet<OperandFlag> flags) { - if (curUseKind != null) { - return curUseKind; - } else if (flags.contains(OperandFlag.Stack)) { - return "S"; - } else { - return "M"; - } - } - - private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - Interval interval = findInterval(value); - if (interval != null) { - if (interval.uses.size() == 0 || interval.uses.get(interval.uses.size() - 1).pos != curOpId) { - interval.uses.add(new UsePosition(curOpId, useKind(flags))); - } - if (interval.lastTo == 0) { - interval.lastTo = curOpId + (mode == OperandMode.Alive ? 1 : 0); - } - } - return value; - } - - private CiValue def(CiValue value, EnumSet<OperandFlag> flags) { - Interval interval = findInterval(value); - if (interval != null) { - interval.uses.add(new UsePosition(curOpId, useKind(flags))); - if (interval.lastTo == 0) { - interval.ranges.add(new Range(curOpId, curOpId + 1)); - } else { - interval.ranges.add(new Range(curOpId, interval.lastTo)); - } - interval.lastTo = 0; - } - return value; - } - - private CiValue out(CiValue value) { - Interval interval = findInterval(value); - if (interval != null) { - interval.lastTo = curOpId; - } - return value; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/Location.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.util; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.lir.*; - -public class Location extends CiValue { - private static final long serialVersionUID = -1786677729152726126L; - - public final Variable variable; - public final CiValue location; - - public Location(Variable variable, CiValue location) { - super(variable.kind); - this.variable = variable; - this.location = location; - - assert variable.kind == location.kind; - } - - @Override - public String toString() { - return variable + "[" + location + "]"; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LocationMap.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.util; - -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; - -public class LocationMap { - private final Location[] locations; - - public LocationMap(int numVariables) { - locations = new Location[numVariables]; - } - - public LocationMap(LocationMap template) { - locations = Arrays.copyOf(template.locations, template.locations.length); - } - - public Location get(Variable variable) { - assert locations[variable.index] == null || locations[variable.index].variable == variable; - return locations[variable.index]; - } - - public void put(Location location) { - locations[location.variable.index] = location; - } - - public void clear(Variable variable) { - locations[variable.index] = null; - } - - public void forEachLocation(ValueProcedure proc) { - for (int i = 0; i < locations.length; i++) { - if (locations[i] != null) { - CiValue newValue = proc.doValue(locations[i], null, null); - assert newValue == null || asLocation(newValue).variable == locations[i].variable; - locations[i] = (Location) newValue; - } - } - } - - public boolean checkEmpty() { - for (int i = 0; i < locations.length; i++) { - assert locations[i] == null; - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,347 +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.max.graal.alloc.util; - -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.alloc.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public abstract class MoveResolver { - private final LIR lir; - private final FrameMap frameMap; - private final int[] registersBlocked; - private final Map<CiValue, Integer> valuesBlocked; - private final List<CiValue> mappingFrom; - private final List<Location> mappingTo; - private final LIRInsertionBuffer insertionBuffer; - private int insertPos; - - public MoveResolver(LIR lir, FrameMap frameMap) { - this.lir = lir; - this.frameMap = frameMap; - - registersBlocked = new int[frameMap.target.arch.registers.length]; - valuesBlocked = new HashMap<>(); - - mappingFrom = new ArrayList<>(); - mappingTo = new ArrayList<>(); - insertionBuffer = new LIRInsertionBuffer(); - insertPos = -1; - - assert checkEmpty(); - } - - public void init(List<LIRInstruction> newInsertList, int newInsertPos) { - assert checkEmpty(); - - if (insertionBuffer.lirList() != newInsertList) { - // Block changed, so append insertionBuffer because it is bound to a specific block - finish(); - insertionBuffer.init(newInsertList); - } - insertPos = newInsertPos; - - assert checkValid(); - } - - public void add(CiValue from, Location to) { - assert checkValid(); - assert isLocation(from) || isConstant(from); - assert from != to; - - assert trace("mr add mapping from %s to %s", from, to); - mappingFrom.add(from); - mappingTo.add(to); - - assert checkValid(); - } - - public void resolve() { - assert checkValid(); - - if (mappingFrom.size() == 1) { - // If there is only one mapping, it is trivial that this mapping is safe to resolve. - assert trace("mr resolve mappings: %d", mappingFrom.size()); - insertMove(mappingFrom.get(0), mappingTo.get(0)); - mappingFrom.remove(0); - mappingTo.remove(0); - } else if (mappingFrom.size() > 1) { - assert trace("mr resolve mappings: %d", mappingFrom.size()); - doResolve(); - } - insertPos = -1; - - assert checkEmpty(); - } - - public void finish() { - assert checkEmpty(); - - if (insertionBuffer.initialized()) { - insertionBuffer.finish(); - } - - assert !insertionBuffer.initialized() : "must be uninitialized now"; - assert checkEmpty(); - } - - - private void doResolve() { - // Block all registers and stack slots that are used as inputs of a move. - // When a register is blocked, no move to this register is emitted. - // This is necessary for detecting cycles in moves. - for (CiValue from : mappingFrom) { - block(from); - } - - while (mappingFrom.size() > 0) { - boolean processed = false; - for (int i = mappingFrom.size() - 1; i >= 0; i--) { - CiValue from = mappingFrom.get(i); - Location to = mappingTo.get(i); - - if (safeToProcessMove(from, to)) { - insertMove(from, to); - unblock(from); - mappingFrom.remove(i); - mappingTo.remove(i); - processed = true; - } - } - - if (!processed) { - // No move could be processed because there is a cycle in the move list - // (e.g., r1 -> r2, r2 -> r1), so one location must be spilled. - spill(); - } - } - } - - private void spill() { - Location spillCandidate = null; - int exchangeCandidate = -1; - int exchangeOther = -1; - - for (int i = mappingFrom.size() - 1; i >= 0; i--) { - CiValue from = mappingFrom.get(i); - Location to = mappingTo.get(i); - assert !safeToProcessMove(from, to) : "would not be in this code otherwise"; - - if (isConstant(from)) { - continue; - } - CiValue fromLoc = asLocation(from).location; - - // Check if we can insert an exchange to save us from spilling. - if (isRegister(fromLoc) && isRegister(to) && asRegister(fromLoc) != asRegister(to) && blockedCount(to) == 1) { - for (int j = mappingFrom.size() - 1; j >= 0; j--) { - CiValue possibleOther = mappingFrom.get(j); - if (isLocation(possibleOther)) { - if (asLocation(possibleOther).location == to.location) { - assert exchangeCandidate == -1 : "must not find twice because of blocked check above"; - exchangeCandidate = i; - exchangeOther = j; - } else if (i != j && asLocation(possibleOther).location == fromLoc) { - // From is read multiple times, so exchange would be too complicated. - exchangeCandidate = -1; - break; - } - } - } - } - - if (exchangeCandidate != -1) { - // Already found a result, no need to search further - break; - } - if (spillCandidate == null || isStackSlot(spillCandidate.location)) { - // this interval cannot be processed now because target is not free - spillCandidate = asLocation(from); - } - } - - if (exchangeCandidate != -1) { - Location from = asLocation(mappingFrom.get(exchangeCandidate)); - Location to = mappingTo.get(exchangeCandidate); - Location other = asLocation(mappingFrom.get(exchangeOther)); - - Location newOther = new Location(other.variable, from.variable); - mappingFrom.set(exchangeOther, newOther); - - insertExchange(newOther, to); - unblock(to); - mappingFrom.remove(exchangeCandidate); - mappingTo.remove(exchangeCandidate); - - } else { - assert spillCandidate != null : "no location for spilling found"; - - Location spillLocation = new Location(spillCandidate.variable, frameMap.allocateSpillSlot(spillCandidate.kind)); - insertMove(spillCandidate, spillLocation); - - for (int i = mappingFrom.size() - 1; i >= 0; i--) { - if (mappingFrom.get(i) == spillCandidate) { - mappingFrom.set(i, spillLocation); - unblock(spillCandidate); - block(spillLocation); - } - } - assert blockedCount(spillCandidate) == 0 : "register must be unblocked after spilling"; - } - } - - private void block(CiValue value) { - if (isLocation(value)) { - CiValue location = asLocation(value).location; - if (isRegister(location)) { - registersBlocked[asRegister(location).number]++; - } else { - Integer count = valuesBlocked.get(location); - valuesBlocked.put(location, count == null ? 1 : count + 1); - } - } - } - - private void unblock(CiValue value) { - if (isLocation(value)) { - assert blockedCount(asLocation(value)) > 0; - CiValue location = asLocation(value).location; - if (isRegister(location)) { - registersBlocked[asRegister(location).number]--; - } else { - Integer count = valuesBlocked.remove(location); - if (count > 1) { - valuesBlocked.put(location, count - 1); - } - } - } - } - - private int blockedCount(Location value) { - CiValue location = asLocation(value).location; - if (isRegister(location)) { - return registersBlocked[asRegister(location).number]; - } else { - Integer count = valuesBlocked.get(location); - return count == null ? 0 : count; - } - } - - private boolean safeToProcessMove(CiValue from, Location to) { - int count = blockedCount(to); - return count == 0 || (count == 1 && isLocation(from) && asLocation(from).location == to.location); - } - - private void insertExchange(Location from, Location to) { - assert trace("mr XCHG %s, %s", from, to); - // TODO create XCHG instruction and use it here - insertionBuffer.append(insertPos, null); - throw Util.unimplemented(); - } - - private void insertMove(CiValue src, Location dst) { - if (isStackSlot(dst.location) && isLocation(src) && isStackSlot(asLocation(src).location)) { - // Move between two stack slots. We need a temporary registers. If the allocator can give - // us a free register, we need two moves: src->scratch, scratch->dst - // If the allocator cannot give us a free register (it returns a Location in this case), - // we need to spill the scratch register first, so we need four moves in total. - - CiValue scratch = scratchRegister(dst.variable); - - Location scratchSaved = null; - CiValue scratchRegister = scratch; - if (isLocation(scratch)) { - scratchSaved = new Location(asLocation(scratch).variable, frameMap.allocateSpillSlot(scratch.kind)); - insertMove(scratch, scratchSaved); - scratchRegister = asLocation(scratch).location; - } - assert isRegister(scratchRegister); - - Location scratchLocation = new Location(dst.variable, scratchRegister); - insertMove(src, scratchLocation); - insertMove(scratchLocation, dst); - - if (scratchSaved != null) { - insertMove(scratchSaved, asLocation(scratch)); - } - - } else { - assert trace("mr MOV %s -> %s", src, dst); - insertionBuffer.append(insertPos, lir.spillMoveFactory.createMove(dst, src)); - } - } - - /** - * Provides a register that can be used by the move resolver. If the returned value is a - * {@link CiRegisterValue}, the register can be overwritten without precautions. If the - * returned value is a {@link Location}, it needs to be spilled and rescued itself. - */ - protected abstract CiValue scratchRegister(Variable spilled); - - private boolean checkEmpty() { - assert insertPos == -1; - assert mappingFrom.size() == 0 && mappingTo.size() == 0; - for (int registerBlocked : registersBlocked) { - assert registerBlocked == 0; - } - assert valuesBlocked.size() == 0; - return true; - } - - private boolean checkValid() { - assert insertPos != -1; - for (int registerBlocked : registersBlocked) { - assert registerBlocked == 0; - } - assert mappingFrom.size() == mappingTo.size(); - assert insertionBuffer.initialized() && insertPos != -1; - - for (int i = 0; i < mappingTo.size(); i++) { - CiValue from = mappingFrom.get(i); - Location to = mappingTo.get(i); - - assert from.kind.stackKind() == to.kind; - - for (int j = i + 1; j < mappingTo.size(); j++) { - Location otherTo = mappingTo.get(j); - assert to != otherTo && to.variable != otherTo.variable && to.location != otherTo.location : "Cannot write to same location twice"; - } - } - return true; - } - - - private static boolean trace(String format, Object...args) { - if (GraalOptions.TraceRegisterAllocation) { - TTY.println(format, args); - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,260 +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.max.graal.alloc.util; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.*; -import com.oracle.max.graal.compiler.util.*; - -public final class RegisterVerifier { - private final FrameMap frameMap; - - /** - * All blocks that must be processed. - */ - private final List<Block> workList; - - /** - * Saved information of previous check. - * <br> - * State mapping: mapping from registers and stack slots ({@link CiRegister} and {@link Integer} stack slot offsets) to the - * value that is currently contained in there ({@link Location} for operands that were variables; {@link CiRegisterValue} or - * {@link CiStackSlot} for operands that used fixed registers or stack slots). - */ - private final Map<Object, CiValue>[] blockStates; - - private void addToWorkList(Block block) { - if (!workList.contains(block)) { - workList.add(block); - } - } - - private Map<Object, CiValue> stateFor(Block block) { - return blockStates[block.getId()]; - } - - private void setStateFor(Block block, Map<Object, CiValue> savedState) { - blockStates[block.getId()] = savedState; - } - - private static Map<Object, CiValue> copy(Map<Object, CiValue> inputState) { - return new HashMap<>(inputState); - } - - public static boolean verify(LIR lir, FrameMap frameMap) { - RegisterVerifier verifier = new RegisterVerifier(lir, frameMap); - verifier.verify(lir.cfg.getStartBlock()); - return true; - } - - @SuppressWarnings("unchecked") - private RegisterVerifier(LIR lir, FrameMap frameMap) { - this.frameMap = frameMap; - this.workList = new LinkedList<>(); - this.blockStates = new Map[lir.linearScanOrder().size()]; - } - - private Map<Object, CiValue> curInputState; - - private void verify(Block startBlock) { - ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, flags); } }; - ValueProcedure tempProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return temp(value); } }; - ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return output(value); } }; - - curInputState = new HashMap<>(); - setStateFor(startBlock, curInputState); - addToWorkList(startBlock); - - assert trace("==== start verify register allocation ===="); - do { - Block block = workList.remove(0); - assert block.phis == null : "phi functions must have been resolved with moves"; - - // Must copy state because it is modified. - curInputState = copy(stateFor(block)); - assert trace("start block %s %s", block, block.getLoop()); - assert traceState(); - - for (LIRInstruction op : block.lir) { - assert trace(" op %d %s", op.id(), op); - - op.forEachInput(useProc); - if (op.hasCall()) { - invalidateRegisters(); - } - op.forEachAlive(useProc); - op.forEachState(useProc); - op.forEachTemp(tempProc); - op.forEachOutput(outputProc); - } - - for (Block succ : block.getSuccessors()) { - processSuccessor(succ); - } - - assert trace("end block %s", block); - } while (!workList.isEmpty()); - assert trace("==== end verify register allocation ===="); - } - - private void processSuccessor(Block succ) { - Map<Object, CiValue> savedState = stateFor(succ); - if (savedState == null) { - // Block was not processed before, so set initial inputState. - assert trace(" successor %s: initial visit", succ); - setStateFor(succ, copy(curInputState)); - addToWorkList(succ); - - } else { - // This block was already processed before. - // Check if new inputState is consistent with savedState. - assert trace(" successor %s: state present", succ); - Iterator<Map.Entry<Object, CiValue>> iter = savedState.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry<Object, CiValue> entry = iter.next(); - CiValue savedValue = entry.getValue(); - CiValue inputValue = curInputState.get(entry.getKey()); - - if (savedValue != inputValue) { - // Current inputState and previous savedState assume a different value in this register. - // Assume that this register is invalid and remove it from the saved state. - assert trace(" invalididating %s because it is inconsistent with %s", savedValue, inputValue); - iter.remove(); - // Must re-visit this block. - addToWorkList(succ); - } - } - } - } - - private void invalidateRegisters() { - // Invalidate all caller save registers at calls. - Iterator<Object> iter = curInputState.keySet().iterator(); - while (iter.hasNext()) { - Object value1 = iter.next(); - if (value1 instanceof CiRegister && frameMap.registerConfig.getAttributesMap()[((CiRegister) value1).number].isCallerSave) { - assert trace(" remove caller save register %s", value1); - iter.remove(); - } - } - } - - /** - * Gets the mapping key for a value. The key should be as narrow as possible, e.g., it should not - * include the kind of the value because we do not want to distinguish between the same register with - * different kinds. - */ - private Object key(CiValue value) { - if (isLocation(value)) { - return key(asLocation(value).location); - } else if (isRegister(value)) { - return asRegister(value); - } else if (isStackSlot(value)) { - return Integer.valueOf(frameMap.offsetForStackSlot(asStackSlot(value))); - } else { - throw Util.shouldNotReachHere(); - } - } - - private boolean isIgnoredRegister(CiValue value) { - return isRegister(value) && !frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; - } - - private CiValue use(CiValue value, EnumSet<OperandFlag> flags) { - if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) { - CiValue actual = curInputState.get(key(value)); - if (actual == null && flags.contains(OperandFlag.Uninitialized)) { - // OK, since uninitialized values are allowed explicitly. - } else if (value != actual) { - TTY.println("!! Error in register allocation: %s != %s for key %s", value, actual, key(value)); - traceState(); - throw Util.shouldNotReachHere(); - } - } - return value; - } - - private CiValue temp(CiValue value) { - if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) { - assert trace(" temp %s -> remove key %s", value, key(value)); - curInputState.remove(key(value)); - } - return value; - } - - private CiValue output(CiValue value) { - if (value != CiValue.IllegalValue && !isIgnoredRegister(value)) { - assert trace(" output %s -> set key %s", value, key(value)); - curInputState.put(key(value), value); - } - return value; - } - - - private boolean traceState() { - if (GraalOptions.TraceRegisterAllocation) { - ArrayList<Object> keys = new ArrayList<>(curInputState.keySet()); - Collections.sort(keys, new Comparator<Object>() { - @Override - public int compare(Object o1, Object o2) { - if (o1 instanceof CiRegister) { - if (o2 instanceof CiRegister) { - return ((CiRegister) o1).number - ((CiRegister) o2).number; - } else { - return -1; - } - } else { - if (o2 instanceof CiRegister) { - return 1; - } else { - return ((Integer) o1).intValue() - ((Integer) o2).intValue(); - } - } - } - }); - - TTY.print(" state: "); - for (Object key : keys) { - TTY.print("%s=%s ", key, curInputState.get(key)); - } - TTY.println(); - } - return true; - } - - private static boolean trace(String format, Object...args) { - if (GraalOptions.TraceRegisterAllocation) { - TTY.println(format, args); - } - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/ValueUtil.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.alloc.util; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.lir.*; - -public class ValueUtil extends CiValueUtil { - - public static boolean isVariable(CiValue value) { - assert value != null; - return value instanceof Variable; - } - - public static Variable asVariable(CiValue value) { - assert value != null; - return (Variable) value; - } - - - public static boolean isLocation(CiValue value) { - assert value != null; - return value instanceof Location; - } - - public static Location asLocation(CiValue value) { - assert value != null; - return (Location) value; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java Wed Feb 08 21:15:00 2012 -0800 @@ -29,19 +29,18 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; -import com.oracle.max.criutils.*; import com.oracle.max.graal.alloc.simple.*; import com.oracle.max.graal.compiler.alloc.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.compiler.phases.PhasePlan.PhasePosition; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.target.*; import com.oracle.max.graal.cri.*; import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; public class GraalCompiler { @@ -81,7 +80,10 @@ if (osrBCI != -1) { throw new CiBailout("No OSR supported"); } - return Debug.scope(createScopeName(method), method, new Callable<CiTargetMethod>() { + Debug.dump(this, "compiler"); + Debug.dump(method, "method"); + + return Debug.scope(createScopeName(method), new Callable<CiTargetMethod>() { public CiTargetMethod call() { final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null; final LIR lir = Debug.scope("FrontEnd", graph, new Callable<LIR>() { @@ -189,6 +191,7 @@ final SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph); + Debug.dump(schedule, "final schedule"); final Block[] blocks = schedule.getCFG().getBlocks(); final Block startBlock = schedule.getCFG().getStartBlock(); @@ -219,6 +222,7 @@ public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final RiResolvedMethod method) { final FrameMap frameMap = backend.newFrameMap(runtime.getRegisterConfig(method)); final LIRGenerator lirGenerator = backend.newLIRGenerator(graph, frameMap, method, lir, xir); + Debug.dump(lirGenerator, "LIRGenerator"); Debug.scope("LIRGen", new Runnable() { public void run() { @@ -226,16 +230,7 @@ lirGenerator.doBlock(b); } - for (Block b : lir.linearScanOrder()) { - if (b.phis != null) { - b.phis.fillInputs(lirGenerator); - } - } - - Debug.dump(lirGenerator, "After LIR generation"); - if (GraalOptions.PrintLIR && !TTY.isSuppressed()) { - LIR.printLIR(lir.linearScanOrder()); - } + Debug.dump(lir, "After LIR generation"); } }); @@ -269,6 +264,7 @@ targetMethod.setAssumptions(assumptions); } + Debug.dump(lir, "After code generation"); Debug.dump(targetMethod, "After code generation"); return targetMethod; }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java Wed Feb 08 21:15:00 2012 -0800 @@ -27,8 +27,8 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.cfg.*; public final class ComputeLinearScanOrder {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Wed Feb 08 21:15:00 2012 -0800 @@ -24,10 +24,10 @@ import java.util.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.cfg.*; /** * This class performs basic optimizations on the control flow graph after LIR generation.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Wed Feb 08 21:15:00 2012 -0800 @@ -24,9 +24,9 @@ import java.util.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.StandardOp.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.StandardOp.*; +import com.oracle.max.graal.lir.cfg.*; /** * This class optimizes moves, particularly those that result from eliminating SSA form.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/Interval.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/Interval.java Wed Feb 08 21:15:00 2012 -0800 @@ -22,15 +22,15 @@ */ package com.oracle.max.graal.compiler.alloc; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; import java.util.*; import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.lir.*; /** * Represents an interval in the {@linkplain LinearScan linear scan register allocator}.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LIRInsertionBuffer.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2009, 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.max.graal.compiler.alloc; - -import java.util.*; - -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -/** - * A buffer to enqueue updates to a list. This avoids frequent re-sizing of the list and copying of list elements - * when insertions are done at multiple positions of the list. Additionally, it ensures that the list is not modified - * while it is, e.g., iterated, and instead only modified once after the iteration is done. - * <br> - * The buffer uses internal data structures to store the enqueued updates. To avoid allocations, a buffer can be re-used. - * Call the methods in the following order: - * {@link #init()}, {@link #append()}, {@link #append()}, ..., {@link #finish()}, {@link #init()}, ... - * <br> - * Note: This class does not depend on LIRInstruction, so we could make it a generic utility class. - */ -public final class LIRInsertionBuffer { - - /** - * The lir list where ops of this buffer should be inserted later (null when uninitialized). - */ - private List<LIRInstruction> lir; - - /** - * List of insertion points. index and count are stored alternately: - * indexAndCount[i * 2]: the index into lir list where "count" ops should be inserted - * indexAndCount[i * 2 + 1]: the number of ops to be inserted at index - */ - private final IntList indexAndCount; - - /** - * The LIROps to be inserted. - */ - private final List<LIRInstruction> ops; - - - public LIRInsertionBuffer() { - indexAndCount = new IntList(8); - ops = new ArrayList<>(8); - } - - /** - * Initialize this buffer. This method must be called before using {@link #append()}. - */ - public void init(List<LIRInstruction> newLir) { - assert !initialized() : "already initialized"; - assert indexAndCount.size() == 0 && ops.size() == 0; - this.lir = newLir; - } - - public boolean initialized() { - return lir != null; - } - - public List<LIRInstruction> lirList() { - return lir; - } - - /** - * Enqueue a new instruction that will be appended to the instruction list when {@link #finish()} is called. - * The new instruction is added <b>before</b> the existing instruction with the given index. This method can only be called - * with increasing values of index, e.g., once an instruction was appended with index 4, subsequent instructions can - * only be appended with index 4 or higher. - */ - public void append(int index, LIRInstruction op) { - int i = numberOfInsertionPoints() - 1; - if (i < 0 || indexAt(i) < index) { - appendNew(index, 1); - } else { - assert indexAt(i) == index : "can append LIROps in ascending order only"; - assert countAt(i) > 0 : "check"; - setCountAt(i, countAt(i) + 1); - } - ops.add(op); - - assert verify(); - } - - /** - * Append all enqueued instructions to the instruction list. After that, {@link init()} can be called again to re-use this buffer. - */ - public void finish() { - if (ops.size() > 0) { - int n = lir.size(); - // increase size of instructions list - for (int i = 0; i < ops.size(); i++) { - lir.add(null); - } - // insert ops from buffer into instructions list - int opIndex = ops.size() - 1; - int ipIndex = numberOfInsertionPoints() - 1; - int fromIndex = n - 1; - int toIndex = lir.size() - 1; - while (ipIndex >= 0) { - int index = indexAt(ipIndex); - // make room after insertion point - while (fromIndex >= index) { - lir.set(toIndex--, lir.get(fromIndex--)); - } - // insert ops from buffer - for (int i = countAt(ipIndex); i > 0; i--) { - lir.set(toIndex--, ops.get(opIndex--)); - } - ipIndex--; - } - indexAndCount.clear(); - ops.clear(); - } - lir = null; - } - - private void appendNew(int index, int count) { - indexAndCount.add(index); - indexAndCount.add(count); - } - - private void setCountAt(int i, int value) { - indexAndCount.set((i << 1) + 1, value); - } - - private int numberOfInsertionPoints() { - assert indexAndCount.size() % 2 == 0 : "must have a count for each index"; - return indexAndCount.size() >> 1; - } - - private int indexAt(int i) { - return indexAndCount.get((i << 1)); - } - - private int countAt(int i) { - return indexAndCount.get((i << 1) + 1); - } - - private boolean verify() { - int sum = 0; - int prevIdx = -1; - - for (int i = 0; i < numberOfInsertionPoints(); i++) { - assert prevIdx < indexAt(i) : "index must be ordered ascending"; - sum += countAt(i); - } - assert sum == ops.size() : "wrong total sum"; - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Wed Feb 08 21:15:00 2012 -0800 @@ -24,7 +24,7 @@ import static com.oracle.max.cri.ci.CiUtil.*; import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; import java.util.*; @@ -35,16 +35,14 @@ import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding; import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority; import com.oracle.max.graal.compiler.alloc.Interval.SpillState; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.StandardOp.MoveOp; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.StandardOp.*; +import com.oracle.max.graal.lir.cfg.*; /** * An implementation of the linear scan register allocator algorithm described @@ -1589,7 +1587,7 @@ } default: { - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } } } @@ -1902,14 +1900,6 @@ } void printLir(String label, @SuppressWarnings("unused") boolean hirValid) { - // TODO(tw): Fix printing. - if (GraalOptions.TraceLinearScanLevel >= 1 && !TTY.isSuppressed()) { - TTY.println(); - TTY.println(label); - LIR.printLIR(ir.linearScanOrder()); - TTY.println(); - } - Debug.dump(ir, label); }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Wed Feb 08 21:15:00 2012 -0800 @@ -23,7 +23,7 @@ package com.oracle.max.graal.compiler.alloc; import static com.oracle.max.cri.ci.CiUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; +import static com.oracle.max.graal.alloc.util.LocationUtil.*; import java.util.*; @@ -35,10 +35,10 @@ import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority; import com.oracle.max.graal.compiler.alloc.Interval.SpillState; import com.oracle.max.graal.compiler.alloc.Interval.State; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.compiler.lir.StandardOp.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.StandardOp.*; +import com.oracle.max.graal.lir.cfg.*; /** */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java Wed Feb 08 21:15:00 2012 -0800 @@ -29,7 +29,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.lir.*; /** */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java Wed Feb 08 21:15:00 2012 -0800 @@ -29,10 +29,10 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.*; import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; /** */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/ExceptionInfo.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2009, 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.max.graal.compiler.asm; - -import com.oracle.max.graal.compiler.lir.*; - -public class ExceptionInfo { - - public final int codeOffset; - public final LabelRef exceptionEdge; - public final int bci; - - public ExceptionInfo(int pcOffset, LabelRef exceptionEdge, int bci) { - this.codeOffset = pcOffset; - this.exceptionEdge = exceptionEdge; - this.bci = bci; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.asm; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIR.SlowPath; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.debug.*; - -public class TargetMethodAssembler { - - public final AbstractAssembler asm; - public final CiTargetMethod targetMethod; - public final CiTarget target; - public final RiRuntime runtime; - public final FrameMap frameMap; - public final List<SlowPath> slowPaths; - - private List<ExceptionInfo> exceptionInfoList; - private int lastSafepointPos; - public TargetMethodAssembler(CiTarget target, RiRuntime runtime, FrameMap frameMap, List<SlowPath> slowPaths, AbstractAssembler asm) { - this.target = target; - this.runtime = runtime; - this.frameMap = frameMap; - this.slowPaths = slowPaths; - this.asm = asm; - this.targetMethod = new CiTargetMethod(); - // 0 is a valid pc for safepoints in template methods - this.lastSafepointPos = -1; - } - - public void setFrameSize(int frameSize) { - targetMethod.setFrameSize(frameSize); - } - - public CiTargetMethod.Mark recordMark(Object id, CiTargetMethod.Mark[] references) { - return targetMethod.recordMark(asm.codeBuffer.position(), id, references); - } - - public void blockComment(String s) { - targetMethod.addAnnotation(new CiTargetMethod.CodeComment(asm.codeBuffer.position(), s)); - } - - public CiTargetMethod finishTargetMethod(Object name, boolean isStub) { - // Install code, data and frame size - targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position()); - - // Record exception handlers if they exist - if (exceptionInfoList != null) { - for (ExceptionInfo ei : exceptionInfoList) { - int codeOffset = ei.codeOffset; - targetMethod.recordExceptionHandler(codeOffset, -1, 0, ei.exceptionEdge.label().position(), -1, null); - } - } - - Debug.metric("TargetMethods").increment(); - Debug.metric("CodeBytesEmitted").add(targetMethod.targetCodeSize()); - Debug.metric("SafepointsEmitted").add(targetMethod.safepoints.size()); - Debug.metric("DataPatches").add(targetMethod.dataReferences.size()); - Debug.metric("ExceptionHandlersEmitted").add(targetMethod.exceptionHandlers.size()); - - if (GraalOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) { - Util.printSection("Target Method", Util.SECTION_CHARACTER); - TTY.println("Name: " + name); - TTY.println("Frame size: " + targetMethod.frameSize()); - TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount); - - if (GraalOptions.PrintCodeBytes) { - Util.printSection("Code", Util.SUB_SECTION_CHARACTER); - TTY.println("Code: %d bytes", targetMethod.targetCodeSize()); - Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), GraalOptions.PrintAssemblyBytesPerLine); - } - - Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER); - String disassembly = runtime.disassemble(targetMethod); - TTY.println(disassembly); - boolean noDis = disassembly == null || disassembly.length() == 0; - - Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Safepoint x : targetMethod.safepoints) { - TTY.println(x.toString()); - if (noDis && x.debugInfo != null) { - TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); - } - } - - Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) { - TTY.println(x.toString()); - } - - Util.printSection("Marks", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Mark x : targetMethod.marks) { - TTY.println(x.toString()); - } - - Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) { - TTY.println(x.toString()); - } - } - - return targetMethod; - } - - public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) { - if (info != null) { - if (info.exceptionEdge != null) { - if (exceptionInfoList == null) { - exceptionInfoList = new ArrayList<>(4); - } - exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge, info.topFrame.bci)); - } - } - } - - public void recordImplicitException(int pcOffset, LIRDebugInfo info) { - // record an implicit exception point - if (info != null) { - assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset; - lastSafepointPos = pcOffset; - targetMethod.recordSafepoint(pcOffset, info.debugInfo()); - assert info.exceptionEdge == null; - } - } - - public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) { - CiDebugInfo 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) { - CiDebugInfo 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) { - // safepoints always need debug info - CiDebugInfo debugInfo = info.debugInfo(); - assert lastSafepointPos < pos; - lastSafepointPos = pos; - targetMethod.recordSafepoint(pos, debugInfo); - } - - public CiAddress recordDataReferenceInCode(CiConstant data, int alignment) { - assert data != null; - int pos = asm.codeBuffer.position(); - Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString()); - targetMethod.recordDataReference(pos, data, alignment); - return CiAddress.Placeholder; - } - - public int lastSafepointPos() { - return lastSafepointPos; - } - - - /** - * Returns the integer value of any constants that can be represented by a 32-bit integer value, - * including long constants that fit into the 32-bit range. - */ - public int asIntConst(CiValue value) { - assert (value.kind.stackKind() == CiKind.Int || value.kind == CiKind.Jsr || value.kind == CiKind.Long) && isConstant(value); - long c = ((CiConstant) value).asLong(); - if (!(NumUtil.isInt(c))) { - throw Util.shouldNotReachHere(); - } - return (int) c; - } - - /** - * Returns the address of a float constant that is embedded as a data references into the code. - */ - public CiAddress asFloatConstRef(CiValue value) { - return asFloatConstRef(value, 4); - } - - public CiAddress asFloatConstRef(CiValue value, int alignment) { - assert value.kind == CiKind.Float && isConstant(value); - return recordDataReferenceInCode((CiConstant) value, alignment); - } - - /** - * Returns the address of a double constant that is embedded as a data references into the code. - */ - public CiAddress asDoubleConstRef(CiValue value) { - return asDoubleConstRef(value, 8); - } - - public CiAddress asDoubleConstRef(CiValue value, int alignment) { - assert value.kind == CiKind.Double && isConstant(value); - return recordDataReferenceInCode((CiConstant) value, alignment); - } - - /** - * Returns the address of a long constant that is embedded as a data references into the code. - */ - public CiAddress asLongConstRef(CiValue value) { - assert value.kind == CiKind.Long && isConstant(value); - return recordDataReferenceInCode((CiConstant) value, 8); - } - - public CiAddress asIntAddr(CiValue value) { - assert value.kind == CiKind.Int; - return asAddress(value); - } - - public CiAddress asLongAddr(CiValue value) { - assert value.kind == CiKind.Long; - return asAddress(value); - } - - public CiAddress asObjectAddr(CiValue value) { - assert value.kind == CiKind.Object; - return asAddress(value); - } - - public CiAddress asFloatAddr(CiValue value) { - assert value.kind == CiKind.Float; - return asAddress(value); - } - - public CiAddress asDoubleAddr(CiValue value) { - assert value.kind == CiKind.Double; - return asAddress(value); - } - - public CiAddress asAddress(CiValue value) { - if (isStackSlot(value)) { - CiStackSlot slot = (CiStackSlot) value; - return new CiAddress(slot.kind, frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot)); - } - return (CiAddress) value; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +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.max.graal.compiler.cfg; - -import java.util.*; - -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.java.*; - -public class Block { - protected int id; - - protected BeginNode beginNode; - protected Node endNode; - protected Loop loop; - protected double probability; - - protected List<Block> predecessors; - protected List<Block> successors; - - protected Block dominator; - protected List<Block> dominated; - protected Block postdominator; - - // Fields that still need to be worked on, try to remove them later. - public FrameState lastState; - public List<LIRInstruction> lir; - public boolean align; - public int linearScanNumber; - public LIRPhiMapping phis; - - public Block() { - id = -1; - } - - public int getId() { - assert id >= 0; - return id; - } - - public BeginNode getBeginNode() { - return beginNode; - } - - public Node getEndNode() { - return endNode; - } - - public Loop getLoop() { - return loop; - } - - public int getLoopDepth() { - return loop == null ? 0 : loop.depth; - } - - public boolean isLoopHeader() { - return getBeginNode() instanceof LoopBeginNode; - } - - public boolean isLoopEnd() { - return getEndNode() instanceof LoopEndNode; - } - - public boolean isExceptionEntry() { - return getBeginNode().next() instanceof ExceptionObjectNode; - } - - public List<Block> getPredecessors() { - return predecessors; - } - - public List<Block> getSuccessors() { - return successors; - } - - public Block getDominator() { - return dominator; - } - - public List<Block> getDominated() { - if (dominated == null) { - return Collections.emptyList(); - } - return dominated; - } - - public Block getPostdominator() { - return postdominator; - } - - private class NodeIterator implements Iterator<Node> { - private Node cur; - - public NodeIterator() { - cur = getBeginNode(); - } - - @Override - public boolean hasNext() { - return cur != null; - } - - @Override - public Node next() { - Node result = cur; - if (cur == getEndNode()) { - cur = null; - } else { - cur = ((FixedWithNextNode) cur).next(); - } - assert !(cur instanceof BeginNode); - return result; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - public Iterable<Node> getNodes() { - return new Iterable<Node>() { - @Override - public Iterator<Node> iterator() { - return new NodeIterator(); - } - }; - } - - public int getFirstLirInstructionId() { - int result = lir.get(0).id(); - assert result >= 0; - return result; - } - - public int getLastLirInstructionId() { - int result = lir.get(lir.size() - 1).id(); - assert result >= 0; - return result; - } - - @Override - public String toString() { - return "B" + id; - } - - -// to be inlined later on - public int numberOfPreds() { - return getPredecessors().size(); - } - - public int numberOfSux() { - return getSuccessors().size(); - } - - public Block predAt(int i) { - return getPredecessors().get(i); - } - - public Block suxAt(int i) { - return getSuccessors().get(i); - } -// end to be inlined later on -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/BlockMap.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.cfg; - -public class BlockMap<T> { - private final T[] data; - - @SuppressWarnings("unchecked") - public BlockMap(ControlFlowGraph cfg) { - data = (T[]) new Object[cfg.getBlocks().length]; - } - - public T get(Block block) { - return data[block.getId()]; - } - - public void put(Block block, T value) { - data[block.getId()] = value; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/CFGVerifier.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.cfg; - -public class CFGVerifier { - public static boolean verify(ControlFlowGraph cfg) { - for (Block block : cfg.getBlocks()) { - assert cfg.getBlocks()[block.getId()] == block; - - for (Block pred : block.getPredecessors()) { - assert pred.getSuccessors().contains(block); - assert pred.getId() < block.getId() || pred.isLoopEnd(); - } - - for (Block sux : block.getSuccessors()) { - assert sux.getPredecessors().contains(block); - assert sux.getId() > block.getId() || sux.isLoopHeader(); - } - - if (block.getDominator() != null) { - assert block.getDominator().getId() < block.getId(); - assert block.getDominator().getDominated().contains(block); - } - for (Block dominated : block.getDominated()) { - assert dominated.getId() > block.getId(); - assert dominated.getDominator() == block; - } - - assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block; - } - - if (cfg.getLoops() != null) { - for (Loop loop : cfg.getLoops()) { - assert loop.header.isLoopHeader(); - - for (Block block : loop.blocks) { - assert block.getId() >= loop.header.getId(); - - Loop blockLoop = block.getLoop(); - while (blockLoop != loop) { - blockLoop = blockLoop.parent; - assert blockLoop != null; - } - } - - for (Block block : loop.exits) { - assert block.getId() >= loop.header.getId(); - - Loop blockLoop = block.getLoop(); - while (blockLoop != null) { - blockLoop = blockLoop.parent; - assert blockLoop != loop; - } - } - } - } - - return true; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.cfg; - -import java.util.*; - -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; - -public class ControlFlowGraph { - - public final StructuredGraph graph; - - private final NodeMap<Block> nodeToBlock; - private Block[] reversePostOrder; - private Loop[] loops; - - public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { - ControlFlowGraph cfg = new ControlFlowGraph(graph); - cfg.identifyBlocks(); - if (connectBlocks || computeLoops || computeDominators || computePostdominators) { - cfg.connectBlocks(); - } - if (computeLoops) { - cfg.computeLoopInformation(); - } - if (computeDominators) { - cfg.computeDominators(); - } - if (computePostdominators) { - cfg.computePostdominators(); - } - assert CFGVerifier.verify(cfg); - return cfg; - } - - protected ControlFlowGraph(StructuredGraph graph) { - this.graph = graph; - this.nodeToBlock = graph.createNodeMap(); - } - - public Block[] getBlocks() { - return reversePostOrder; - } - - public Block getStartBlock() { - return reversePostOrder[0]; - } - - public NodeMap<Block> getNodeToBlock() { - return nodeToBlock; - } - - public Block blockFor(Node node) { - return nodeToBlock.get(node); - } - - public Loop[] getLoops() { - return loops; - } - - private void identifyBlocks() { - // Find all block headers - int numBlocks = 0; - for (Node node : graph.getNodes()) { - if (node instanceof BeginNode) { - Block block = new Block(); - numBlocks++; - - block.beginNode = (BeginNode) node; - Node cur = node; - do { - assert !cur.isDeleted(); - block.endNode = cur; - - assert nodeToBlock.get(cur) == null; - nodeToBlock.set(cur, block); - if (cur instanceof MergeNode) { - for (PhiNode phi : ((MergeNode) cur).phis()) { - nodeToBlock.set(phi, block); - } - } - - if (cur instanceof FixedNode) { - double probability = ((FixedNode) cur).probability(); - if (probability > block.probability) { - block.probability = probability; - } - } - - Node next = null; - for (Node sux : cur.successors()) { - if (sux != null && !(sux instanceof BeginNode)) { - assert next == null; - next = sux; - } - } - cur = next; - } while (cur != null); - } - } - - // Compute reverse postorder. - reversePostOrder = new Block[numBlocks]; - int reversePostOrderId = numBlocks - 1; - - ArrayList<Block> stack = new ArrayList<>(); - stack.add(blockFor(graph.start())); - - do { - Block block = stack.get(stack.size() - 1); - if (block.id == -1) { - // First time we see this block: push all successors. - for (Node suxNode : block.getEndNode().cfgSuccessors()) { - Block suxBlock = blockFor(suxNode); - if (suxBlock.id < 0) { - stack.add(suxBlock); - } - } - block.id = -2; - } else { - // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list. - assert block.id == -2; - stack.remove(stack.size() - 1); - block.id = reversePostOrderId; - reversePostOrder[reversePostOrderId] = block; - reversePostOrderId--; - } - } while (!stack.isEmpty()); - assert reversePostOrderId == -1; - } - - // Connect blocks (including loop backward edges). - private void connectBlocks() { - for (Block block : reversePostOrder) { - List<Block> predecessors = new ArrayList<>(); - for (Node predNode : block.getBeginNode().cfgPredecessors()) { - predecessors.add(nodeToBlock.get(predNode)); - } - if (block.getBeginNode() instanceof LoopBeginNode) { - predecessors.add(nodeToBlock.get(((LoopBeginNode) block.getBeginNode()).loopEnd())); - } - block.predecessors = predecessors; - - List<Block> successors = new ArrayList<>(); - for (Node suxNode : block.getEndNode().cfgSuccessors()) { - successors.add(nodeToBlock.get(suxNode)); - } - if (block.getEndNode() instanceof LoopEndNode) { - successors.add(nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin())); - } - block.successors = successors; - } - } - - private void computeLoopInformation() { - List<Loop> loopsList = new ArrayList<>(); - for (Block block : reversePostOrder) { - Node beginNode = block.getBeginNode(); - if (beginNode instanceof LoopBeginNode) { - Loop loop = new Loop(block.getLoop(), loopsList.size(), block); - loopsList.add(loop); - - LoopEndNode end = ((LoopBeginNode) beginNode).loopEnd(); - Block endBlock = nodeToBlock.get(end); - computeLoopBlocks(endBlock, loop); - } - } - loops = loopsList.toArray(new Loop[loopsList.size()]); - - for (Loop loop : loops) { - for (Block block : loop.blocks) { - for (Block sux : block.getSuccessors()) { - if (sux.getLoopDepth() < loop.depth) { - loop.exits.add(sux); - } - } - } - } - } - - private void computeLoopBlocks(Block block, Loop loop) { - if (block.getLoop() == loop) { - return; - } - assert block.loop == loop.parent; - block.loop = loop; - - assert !loop.blocks.contains(block); - loop.blocks.add(block); - - if (block != loop.header) { - for (Block pred : block.getPredecessors()) { - computeLoopBlocks(pred, loop); - } - } - } - - private void computeDominators() { - assert reversePostOrder[0].getPredecessors().size() == 0 : "start block has no predecessor and therefore no dominator"; - for (int i = 1; i < reversePostOrder.length; i++) { - Block block = reversePostOrder[i]; - List<Block> predecessors = block.getPredecessors(); - assert predecessors.size() > 0; - - if (block.isLoopHeader()) { - // Loop headers have exactly one non-loop predecessor, and that is the dominator. - setDominator(block, predecessors.get(0)); - continue; - } - - Block dominator = predecessors.get(0); - for (int j = 1; j < predecessors.size(); j++) { - Block pred = predecessors.get(j); - dominator = commonDominator(dominator, pred); - } - setDominator(block, dominator); - } - } - - private static void setDominator(Block block, Block dominator) { - block.dominator = dominator; - if (dominator.dominated == null) { - dominator.dominated = new ArrayList<>(); - } - dominator.dominated.add(block); - } - - public static Block commonDominator(Block a, Block b) { - Block iterA = a; - Block iterB = b; - while (iterA != iterB) { - if (iterA.getId() > iterB.getId()) { - iterA = iterA.getDominator(); - } else { - assert iterB.getId() > iterA.getId(); - iterB = iterB.getDominator(); - } - } - return iterA; - } - - private void computePostdominators() { - for (Block block : reversePostOrder) { - if (block.isLoopEnd()) { - // We do not want the loop header registered as the postdominator of the loop end. - continue; - } - Block postdominator = null; - for (Block sux : block.getSuccessors()) { - if (sux.isExceptionEntry()) { - // We ignore exception handlers. - } else if (postdominator == null) { - postdominator = sux; - } else { - postdominator = commonPostdominator(postdominator, sux); - } - } - block.postdominator = postdominator; - } - } - - private static Block commonPostdominator(Block a, Block b) { - Block iterA = a; - Block iterB = b; - while (iterA != iterB) { - if (iterA.getId() < iterB.getId()) { - iterA = iterA.getPostdominator(); - if (iterA == null) { - return null; - } - } else { - assert iterB.getId() < iterA.getId(); - iterB = iterB.getPostdominator(); - if (iterB == null) { - return null; - } - } - } - return iterA; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Loop.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.cfg; - -import java.util.*; - -public class Loop { - public final Loop parent; - public final List<Loop> children; - - public final int depth; - public final int index; - public final Block header; - public final List<Block> blocks; - public final List<Block> exits; - - protected Loop(Loop parent, int index, Block header) { - this.parent = parent; - if (parent != null) { - this.depth = parent.depth + 1; - parent.children.add(this); - } else { - this.depth = 1; - } - this.index = index; - this.header = header; - this.blocks = new ArrayList<>(); - this.children = new ArrayList<>(); - this.exits = new ArrayList<>(); - } - - @Override - public String toString() { - return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : ""); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java Wed Feb 08 21:15:00 2012 -0800 @@ -27,8 +27,8 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.gen.LIRGenerator.LockScope; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.virtual.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Wed Feb 08 21:15:00 2012 -0800 @@ -26,7 +26,7 @@ import static com.oracle.max.cri.ci.CiValue.*; import static com.oracle.max.cri.ci.CiValueUtil.*; import static com.oracle.max.cri.util.MemoryBarriers.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; +import static com.oracle.max.graal.lir.ValueUtil.*; import java.lang.reflect.*; import java.util.*; @@ -46,12 +46,12 @@ import com.oracle.max.cri.xir.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.StandardOp.ParametersOp; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.StandardOp.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.max.graal.nodes.PhiNode.PhiType; @@ -130,7 +130,9 @@ /** * Mapping from blocks to the lock state at the end of the block, indexed by the id number of the block. */ - private LockScope[] blockLocks; + private BlockMap<LockScope> blockLocks; + + private BlockMap<FrameState> blockLastState; /** * The list of currently locked monitors. @@ -149,7 +151,8 @@ this.xir = xir; this.xirSupport = new XirSupport(); this.debugInfoBuilder = new DebugInfoBuilder(nodeOperands); - this.blockLocks = new LockScope[lir.linearScanOrder().size()]; + this.blockLocks = new BlockMap<>(lir.cfg); + this.blockLastState = new BlockMap<>(lir.cfg); } @Override @@ -157,14 +160,6 @@ return target; } - private LockScope locksFor(Block block) { - return blockLocks[block.getId()]; - } - - private void setLocksFor(Block block, LockScope locks) { - blockLocks[block.getId()] = locks; - } - /** * Returns the operand that has been previously initialized by {@link #setResult()} * with the result of an instruction. @@ -196,7 +191,7 @@ case Double: return new Variable(stackKind, lir.nextVariable(), CiRegister.RegisterFlag.FPU); default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } } @@ -300,7 +295,21 @@ assert block.lir == null : "LIR list already computed for this block"; block.lir = new ArrayList<>(); - emitLabel(new Label(), block.align); + if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) { + assert phiValues.isEmpty(); + MergeNode merge = (MergeNode) block.getBeginNode(); + for (PhiNode phi : merge.phis()) { + if (phi.type() == PhiType.Value) { + CiValue phiValue = newVariable(phi.kind()); + setResult(phi, phiValue); + phiValues.add(phiValue); + } + } + append(new PhiLabelOp(new Label(), block.align, phiValues.toArray(new CiValue[phiValues.size()]))); + phiValues.clear(); + } else { + append(new LabelOp(new Label(), block.align)); + } if (GraalOptions.TraceLIRGeneratorLevel >= 1) { TTY.println("BEGIN Generating LIR for block B" + block.getId()); @@ -308,7 +317,7 @@ curLocks = null; for (Block pred : block.getPredecessors()) { - LockScope predLocks = locksFor(pred); + LockScope predLocks = blockLocks.get(pred); if (curLocks == null) { curLocks = predLocks; } else if (curLocks != predLocks && (!pred.isLoopEnd() || predLocks != null)) { @@ -326,8 +335,8 @@ for (Block pred : block.getPredecessors()) { if (fs == null) { - fs = pred.lastState; - } else if (fs != pred.lastState) { + fs = blockLastState.get(pred); + } else if (fs != blockLastState.get(pred)) { fs = null; break; } @@ -345,10 +354,6 @@ lastState = fs; } - if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) { - block.phis = new LIRPhiMapping(block, this); - } - List<Node> nodes = lir.nodesFor(block); for (int i = 0; i < nodes.size(); i++) { Node instr = nodes.get(i); @@ -406,8 +411,8 @@ TTY.println("END Generating LIR for block B" + block.getId()); } - setLocksFor(currentBlock, curLocks); - block.lastState = lastState; + blockLocks.put(currentBlock, curLocks); + blockLastState.put(block, lastState); currentBlock = null; if (GraalOptions.PrintIRWithLIR) { @@ -665,27 +670,65 @@ @Override public void visitMerge(MergeNode x) { - if (x.next() instanceof LoopBeginNode) { - moveToPhi((LoopBeginNode) x.next(), x); - } } @Override public void visitEndNode(EndNode end) { - assert end.merge() != null; moveToPhi(end.merge(), end); - emitJump(getLIRBlock(end.merge()), null); } @Override public void visitLoopEnd(LoopEndNode x) { - moveToPhi(x.loopBegin(), x); if (GraalOptions.GenLoopSafepoints && x.hasSafepointPolling()) { emitSafepointPoll(x); } - emitJump(getLIRBlock(x.loopBegin()), null); + moveToPhi(x.loopBegin(), x); } + private ArrayList<CiValue> phiValues = new ArrayList<>(); + + private void moveToPhi(MergeNode merge, FixedNode pred) { + if (GraalOptions.AllocSSA) { + assert phiValues.isEmpty(); + for (PhiNode phi : merge.phis()) { + if (phi.type() == PhiType.Value) { + phiValues.add(operand(phi.valueAt(pred))); + } + } + append(new PhiJumpOp(getLIRBlock(merge), phiValues.toArray(new CiValue[phiValues.size()]))); + phiValues.clear(); + return; + } + + if (GraalOptions.TraceLIRGeneratorLevel >= 1) { + TTY.println("MOVE TO PHI from " + pred + " to " + merge); + } + PhiResolver resolver = new PhiResolver(this); + for (PhiNode phi : merge.phis()) { + if (phi.type() == PhiType.Value) { + ValueNode curVal = phi.valueAt(pred); + resolver.move(operand(curVal), operandForPhi(phi)); + } + } + resolver.dispose(); + + append(new JumpOp(getLIRBlock(merge), null)); + } + + private CiValue operandForPhi(PhiNode phi) { + assert phi.type() == PhiType.Value : "wrong phi type: " + phi; + CiValue result = operand(phi); + if (result == null) { + // allocate a variable for this phi + Variable newOperand = newVariable(phi.kind()); + setResult(phi, newOperand); + return newOperand; + } else { + return result; + } + } + + public void emitSafepointPoll(FixedNode x) { if (!lastState.method().noSafepointPolls()) { XirSnippet snippet = xir.genSafepointPoll(site(x)); @@ -727,7 +770,7 @@ } else if (node instanceof IsTypeNode) { emitTypeBranch((IsTypeNode) node, trueSuccessor, falseSuccessor, info); } else { - throw Util.unimplemented(node.toString()); + throw GraalInternalError.unimplemented(node.toString()); } } @@ -789,7 +832,7 @@ } else if (node instanceof ConstantNode) { return emitConstantConditional(((ConstantNode) node).asConstant().asBoolean(), trueValue, falseValue); } else { - throw Util.unimplemented(node.toString()); + throw GraalInternalError.unimplemented(node.toString()); } } @@ -921,7 +964,7 @@ } else if (isStackSlot(value)) { return CiStackSlot.get(value.kind.stackKind(), asStackSlot(value).rawOffset(), asStackSlot(value).rawAddFrameSize()); } else { - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } } return value; @@ -945,7 +988,7 @@ argList.add(operand); } else { - throw Util.shouldNotReachHere("I thought we no longer have null entries for two-slot types..."); + throw GraalInternalError.shouldNotReachHere("I thought we no longer have null entries for two-slot types..."); } } return argList; @@ -1127,40 +1170,6 @@ } - - private void moveToPhi(MergeNode merge, FixedNode pred) { - if (GraalOptions.AllocSSA) { - return; - } - - if (GraalOptions.TraceLIRGeneratorLevel >= 1) { - TTY.println("MOVE TO PHI from " + pred + " to " + merge); - } - PhiResolver resolver = new PhiResolver(this); - for (PhiNode phi : merge.phis()) { - if (phi.type() == PhiType.Value) { - ValueNode curVal = phi.valueAt(pred); - resolver.move(operand(curVal), operandForPhi(phi)); - } - } - resolver.dispose(); - } - - private CiValue operandForPhi(PhiNode phi) { - assert phi.type() == PhiType.Value : "wrong phi type: " + phi; - CiValue result = operand(phi); - if (result == null) { - // allocate a variable for this phi - Variable newOperand = newVariable(phi.kind()); - setResult(phi, newOperand); - return newOperand; - } else { - return result; - } - } - - - protected XirArgument toXirArgument(CiValue v) { if (v == null) { return null; @@ -1185,7 +1194,7 @@ } else if (op instanceof XirTemp) { return newVariable(op.kind); } else { - Util.shouldNotReachHere(); + GraalInternalError.shouldNotReachHere(); return null; } }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiResolver.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiResolver.java Wed Feb 08 21:15:00 2012 -0800 @@ -23,7 +23,7 @@ package com.oracle.max.graal.compiler.gen; import static com.oracle.max.cri.ci.CiValue.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; +import static com.oracle.max.graal.lir.ValueUtil.*; import java.util.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +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.max.graal.compiler.lir; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiCallingConvention.Type; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.util.*; - -/** - * This class is used to build the stack frame layout for a compiled method. - * A {@link CiStackSlot} is used to index slots of the frame relative to the stack pointer. - * The frame size is only fixed after register allocation when all spill slots have - * been allocated. Both the outgoing argument area and the spill are can grow until then. - * Therefore, outgoing arguments are indexed from the stack pointer, while spill slots - * are indexed from the beginning of the frame (and the total frame size has to be added - * to get the actual offset from the stack pointer). - * <br> - * This is the format of a stack frame: - * <pre> - * Base Contents - * - * : : ----- - * caller | incoming overflow argument n | ^ - * frame : ... : | positive - * | incoming overflow argument 0 | | offsets - * ---------+--------------------------------+--------------------- - * | return address | | ^ - * current +--------------------------------+ | | ----- - * frame | | | | ^ - * : callee save area : | | | - * | | | | | - * +--------------------------------+ | | | - * | spill slot 0 | | negative | | - * : ... : v offsets | | - * | spill slot n | ----- total frame - * +--------------------------------+ frame size - * | alignment padding | size | - * +--------------------------------+ ----- | | - * | outgoing overflow argument n | ^ | | - * : ... : | positive | | - * | outgoing overflow argument 0 | | offsets v v - * %sp--> +--------------------------------+--------------------------- - * - * </pre> - * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size - * of such a block may be greater than the size of a normal spill slot or the word size. - * <br> - * A runtime has two ways to reserve space in the stack frame for its own use: <ul> - * <li>A memory block somewhere in the frame of size {@link RiRuntime#getCustomStackAreaSize()}. The offset - * to this block is returned in {@link CiTargetMethod#customStackAreaOffset()}. - * <li>At the beginning of the overflow argument area: The calling convention can specify that the first - * overflow stack argument is not at offset 0, but at a specified offset o. Use - * {@link RiRuntime#getMinimumOutgoingSize()} to make sure that call-free methods also have this space - * reserved. Then the VM can use memory the memory at offset 0 relative to the stack pointer. - * </ul> - */ -public final class FrameMap { - public final RiRuntime runtime; - public final CiTarget target; - public final RiRegisterConfig registerConfig; - - /** - * The final frame size, not including the size of the return address. - * The value is only set after register allocation is complete, i.e., after all spill slots have been allocated. - */ - private int frameSize; - - /** - * Size of the area occupied by spill slots and other stack-allocated memory blocks. - */ - private int spillSize; - - /** - * Size of the area occupied by outgoing overflow arguments. - * This value is adjusted as calling conventions for outgoing calls are retrieved. - */ - private int outgoingSize; - - /** - * The list of stack areas allocated in this frame that are present in every reference map. - */ - private final List<CiStackSlot> objectStackBlocks; - - /** - * The stack area reserved for use by the VM, or {@code null} if the VM does not request stack space. - */ - private final CiStackSlot customArea; - - /** - * Creates a new frame map for the specified method. - */ - public FrameMap(RiRuntime runtime, CiTarget target, RiRegisterConfig registerConfig) { - this.runtime = runtime; - this.target = target; - this.registerConfig = registerConfig; - this.frameSize = -1; - this.spillSize = returnAddressSize() + calleeSaveAreaSize(); - this.outgoingSize = runtime.getMinimumOutgoingSize(); - this.objectStackBlocks = new ArrayList<>(); - this.customArea = allocateStackBlock(runtime.getCustomStackAreaSize(), false); - } - - - private int returnAddressSize() { - return target.arch.returnAddressSize; - } - - private int calleeSaveAreaSize() { - CiCalleeSaveLayout csl = registerConfig.getCalleeSaveLayout(); - return csl != null ? csl.size : 0; - } - - /** - * Gets the frame size of the compiled frame, not including the size of the return address. - * @return The size of the frame (in bytes). - */ - public int frameSize() { - assert frameSize != -1 : "frame size not computed yet"; - return frameSize; - } - - /** - * Gets the total frame size of the compiled frame, including the size of the return address. - * @return The total size of the frame (in bytes). - */ - public int totalFrameSize() { - return frameSize() + returnAddressSize(); - } - - /** - * Sets the frame size for this frame. - * @param frameSize The frame size (in bytes). - */ - public void setFrameSize(int frameSize) { - assert this.frameSize == -1 : "must only be set once"; - this.frameSize = frameSize; - } - - /** - * Computes the frame size for this frame. After this method has been called, methods that change the - * frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can be requested. - */ - public void finish() { - setFrameSize(target.alignFrameSize(outgoingSize + spillSize - returnAddressSize())); - } - - /** - * Computes the offset of a stack slot relative to the frame register. - * This is also the bit index of stack slots in the reference map. - * - * @param slot a stack slot - * @return the offset of the stack slot - */ - public int offsetForStackSlot(CiStackSlot slot) { - assert (!slot.rawAddFrameSize() && slot.rawOffset() < outgoingSize) || - (slot.rawAddFrameSize() && slot.rawOffset() < 0 && -slot.rawOffset() <= spillSize) || - (slot.rawAddFrameSize() && slot.rawOffset() >= 0); - return slot.offset(totalFrameSize()); - } - - /** - * Gets the offset to the stack area where callee-saved registers are stored. - * @return The offset to the callee save area (in bytes). - */ - public int offsetToCalleeSaveArea() { - return frameSize() - calleeSaveAreaSize(); - } - - /** - * Gets the offset of the stack area stack block reserved for use by the VM, or -1 if the VM does not request stack space. - * @return The offset to the custom area (in bytes). - */ - public int offsetToCustomArea() { - return customArea == null ? -1 : offsetForStackSlot(customArea); - } - - /** - * Informs the frame map that the compiled code calls a particular method, which - * may need stack space for outgoing arguments. - * @param cc The calling convention for the called method. - * @param type The type of calling convention. - */ - public void callsMethod(CiCallingConvention cc, Type type) { - // TODO look at the actual stack offsets? - assert type.out; - reserveOutgoing(cc.stackSize); - } - - /** - * Reserves space for stack-based outgoing arguments. - * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments. - */ - public void reserveOutgoing(int argsSize) { - assert frameSize == -1 : "frame size must not yet be fixed"; - outgoingSize = Math.max(outgoingSize, argsSize); - } - - private CiStackSlot getSlot(CiKind kind, int additionalOffset) { - return CiStackSlot.get(kind, -spillSize + additionalOffset, true); - } - - /** - * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned on its natural alignment, - * i.e., an 8-byte spill slot is aligned at an 8-byte boundary. - * @param kind The kind of the spill slot to be reserved. - * @return A spill slot denoting the reserved memory area. - */ - public CiStackSlot allocateSpillSlot(CiKind kind) { - assert frameSize == -1 : "frame size must not yet be fixed"; - int size = target.sizeInBytes(kind); - spillSize = Util.roundUp(spillSize + size, size); - return getSlot(kind, 0); - } - - /** - * Reserves a block of memory in the frame of the method being compiled. The returned block is aligned on a word boundary. - * If the requested size is 0, the method returns {@code null}. - * - * @param size The size to reserve (in bytes). - * @param refs Specifies if the block is all references. If true, the block will be in all reference maps for this method. - * The caller is responsible to initialize the memory block before the first instruction that uses a reference map. - * @return A stack slot describing the begin of the memory block. - */ - public CiStackSlot allocateStackBlock(int size, boolean refs) { - assert frameSize == -1 : "frame size must not yet be fixed"; - if (size == 0) { - return null; - } - spillSize = Util.roundUp(spillSize + size, target.wordSize); - - if (refs) { - assert size % target.wordSize == 0; - CiStackSlot result = getSlot(CiKind.Object, 0); - objectStackBlocks.add(result); - for (int i = target.wordSize; i < size; i += target.wordSize) { - objectStackBlocks.add(getSlot(CiKind.Object, i)); - } - return result; - - } else { - return getSlot(target.wordKind, 0); - } - } - - - private int frameRefMapIndex(CiStackSlot slot) { - assert offsetForStackSlot(slot) % target.wordSize == 0; - return offsetForStackSlot(slot) / target.wordSize; - } - - /** - * Initializes a reference map that covers all registers of the target architecture. - */ - public CiBitMap initRegisterRefMap() { - return new CiBitMap(target.arch.registerReferenceMapBitCount); - } - - /** - * Initializes a reference map. Initially, the size is large enough to cover all the - * slots in the frame. If the method has incoming reference arguments on the stack, - * the reference map might grow later when such a reference is set. - */ - public CiBitMap initFrameRefMap() { - CiBitMap frameRefMap = new CiBitMap(frameSize() / target.wordSize); - for (CiStackSlot slot : objectStackBlocks) { - setReference(slot, null, frameRefMap); - } - return frameRefMap; - } - - /** - * Marks the specified location as a reference in the reference map of the debug information. - * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a - * {@link CiConstant} is automatically tracked. - * - * @param location The location to be added to the reference map. - * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}. - * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}. - */ - public void setReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) { - if (location.kind == CiKind.Object) { - if (isRegister(location)) { - assert registerRefMap.size() == target.arch.registerReferenceMapBitCount; - registerRefMap.set(asRegister(location).number); - } else if (isStackSlot(location)) { - int index = frameRefMapIndex(asStackSlot(location)); - frameRefMap.grow(index + 1); - frameRefMap.set(index); - } else { - assert isConstant(location); - } - } - } - - /** - * Clears the specified location as a reference in the reference map of the debug information. - * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a - * {@link CiConstant} is automatically tracked. - * - * @param location The location to be removed from the reference map. - * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}. - * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}. - */ - public void clearReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) { - if (location.kind == CiKind.Object) { - if (location instanceof CiRegisterValue) { - assert registerRefMap.size() == target.arch.registerReferenceMapBitCount; - registerRefMap.clear(asRegister(location).number); - } else if (isStackSlot(location)) { - int index = frameRefMapIndex(asStackSlot(location)); - if (index < frameRefMap.size()) { - frameRefMap.clear(index); - } - } else { - assert isConstant(location); - } - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,257 +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.max.graal.compiler.lir; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.graph.*; - -/** - * This class implements the overall container for the LIR graph - * and directs its construction, optimization, and finalization. - */ -public class LIR { - - public final ControlFlowGraph cfg; - - /** - * The nodes for the blocks. - * TODO: This should go away, we want all nodes connected with a next-pointer. - */ - private final BlockMap<List<Node>> nodesFor; - - /** - * The linear-scan ordered list of blocks. - */ - private final List<Block> linearScanOrder; - - /** - * The order in which the code is emitted. - */ - private final List<Block> codeEmittingOrder; - - - public final List<SlowPath> slowPaths; - - public final List<SlowPath> deoptimizationStubs; - - /** - * The last slow path emitted, which can be used emit marker bytes. - */ - public SlowPath methodEndMarker; - - private int numVariables; - - public SpillMoveFactory spillMoveFactory; - - public interface SpillMoveFactory { - LIRInstruction createMove(CiValue result, CiValue input); - LIRInstruction createExchange(CiValue input1, CiValue input2); - } - - public interface SlowPath { - void emitCode(TargetMethodAssembler tasm); - } - - /** - * Creates a new LIR instance for the specified compilation. - * @param numLoops number of loops - * @param compilation the compilation - */ - public LIR(ControlFlowGraph cfg, BlockMap<List<Node>> nodesFor, List<Block> linearScanOrder, List<Block> codeEmittingOrder) { - this.cfg = cfg; - this.nodesFor = nodesFor; - this.codeEmittingOrder = codeEmittingOrder; - this.linearScanOrder = linearScanOrder; - - slowPaths = new ArrayList<>(); - deoptimizationStubs = new ArrayList<>(); - } - - public List<Node> nodesFor(Block block) { - return nodesFor.get(block); - } - - /** - * Gets the linear scan ordering of blocks as a list. - * @return the blocks in linear scan order - */ - public List<Block> linearScanOrder() { - return linearScanOrder; - } - - public List<Block> codeEmittingOrder() { - return codeEmittingOrder; - } - - public int numVariables() { - return numVariables; - } - - public int nextVariable() { - return numVariables++; - } - - public void emitCode(TargetMethodAssembler tasm) { - if (GraalOptions.PrintLIR && !TTY.isSuppressed()) { - printLIR(codeEmittingOrder()); - } - - for (Block b : codeEmittingOrder()) { - emitBlock(tasm, b); - } - - // generate code for slow cases - for (SlowPath sp : slowPaths) { - emitSlowPath(tasm, sp); - } - // generate deoptimization stubs - for (SlowPath sp : deoptimizationStubs) { - emitSlowPath(tasm, sp); - } - // generate traps at the end of the method - emitSlowPath(tasm, methodEndMarker); - } - - private void emitBlock(TargetMethodAssembler tasm, Block block) { - if (GraalOptions.PrintLIRWithAssembly) { - TTY.println(block.toString()); - } - - if (GraalOptions.CommentedAssembly) { - tasm.blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); - } - - for (LIRInstruction op : block.lir) { - if (GraalOptions.CommentedAssembly) { - tasm.blockComment(String.format("%d %s", op.id(), op)); - } - if (GraalOptions.PrintLIRWithAssembly && !TTY.isSuppressed()) { - // print out the LIR operation followed by the resulting assembly - TTY.println(op.toStringWithIdPrefix()); - TTY.println(); - } - - emitOp(tasm, op); - - if (GraalOptions.PrintLIRWithAssembly) { - printAssembly(tasm); - } - } - } - - private static void emitOp(TargetMethodAssembler tasm, LIRInstruction op) { - try { - try { - op.emitCode(tasm); - } catch (AssertionError t) { - throw new GraalInternalError(t); - } catch (RuntimeException t) { - throw new GraalInternalError(t); - } - } catch (GraalInternalError e) { - throw e.addContext("lir instruction", op); - } - } - - private static void emitSlowPath(TargetMethodAssembler tasm, SlowPath sp) { - if (GraalOptions.CommentedAssembly) { - tasm.blockComment(String.format("slow case %s", sp.getClass().getName())); - } - sp.emitCode(tasm); - } - - private int lastDecodeStart; - - private void printAssembly(TargetMethodAssembler tasm) { - byte[] currentBytes = tasm.asm.codeBuffer.copyData(lastDecodeStart, tasm.asm.codeBuffer.position()); - if (currentBytes.length > 0) { - String disasm = tasm.runtime.disassemble(currentBytes, lastDecodeStart); - if (disasm.length() != 0) { - TTY.println(disasm); - } else { - TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length); - Util.printBytes(lastDecodeStart, currentBytes, GraalOptions.PrintAssemblyBytesPerLine); - } - } - lastDecodeStart = tasm.asm.codeBuffer.position(); - } - - - public static void printBlock(Block x) { - // print block id - TTY.print("B%d ", x.getId()); - - // print flags - if (x.isLoopHeader()) { - TTY.print("lh "); - } - if (x.isLoopEnd()) { - TTY.print("le "); - } - - // print block bci range - TTY.print("[%d, %d] ", -1, -1); - - // print predecessors and successors - if (x.numberOfPreds() > 0) { - TTY.print("preds: "); - for (int i = 0; i < x.numberOfPreds(); i++) { - TTY.print("B%d ", x.predAt(i).getId()); - } - } - - if (x.numberOfSux() > 0) { - TTY.print("sux: "); - for (int i = 0; i < x.numberOfSux(); i++) { - TTY.print("B%d ", x.suxAt(i).getId()); - } - } - - TTY.println(); - } - - public static void printLIR(List<Block> blocks) { - if (TTY.isSuppressed()) { - return; - } - TTY.println("LIR:"); - int i; - for (i = 0; i < blocks.size(); i++) { - Block bb = blocks.get(i); - printBlock(bb); - TTY.println("__id_Instruction___________________________________________"); - for (LIRInstruction op : bb.lir) { - TTY.println(op.toStringWithIdPrefix()); - TTY.println(); - } - TTY.println(); - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +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.max.graal.compiler.lir; - -import static com.oracle.max.graal.compiler.lir.LIRInstruction.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; - -/** - * This class represents garbage collection and deoptimization information attached to a LIR instruction. - */ -public class LIRDebugInfo { - public final CiFrame topFrame; - private final CiVirtualObject[] virtualObjects; - private final List<CiStackSlot> pointerSlots; - public final LabelRef exceptionEdge; - private CiDebugInfo debugInfo; - - public LIRDebugInfo(CiFrame topFrame, CiVirtualObject[] virtualObjects, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge) { - this.topFrame = topFrame; - this.virtualObjects = virtualObjects; - this.pointerSlots = pointerSlots; - this.exceptionEdge = exceptionEdge; - } - - public boolean hasDebugInfo() { - return debugInfo != null; - } - - public CiDebugInfo 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 (CiFrame cur = topFrame; cur != null; cur = cur.caller()) { - processValues(cur.values, proc); - } - if (virtualObjects != null) { - for (CiVirtualObject 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<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - - private void processValues(CiValue[] values, ValueProcedure proc) { - for (int i = 0; i < values.length; i++) { - CiValue value = values[i]; - if (value instanceof CiMonitorValue) { - CiMonitorValue monitor = (CiMonitorValue) value; - if (processed(monitor.owner)) { - monitor.owner = proc.doValue(monitor.owner, OperandMode.Alive, STATE_FLAGS); - } - - } else if (processed(value)) { - values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS); - } - } - } - - private boolean processed(CiValue 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(CiBitMap registerRefMap, CiBitMap frameRefMap, FrameMap frameMap) { - debugInfo = new CiDebugInfo(topFrame, registerRefMap, frameRefMap); - - // Add additional stack slots for outgoing method parameters. - if (pointerSlots != null) { - for (CiStackSlot v : pointerSlots) { - frameMap.setReference(v, registerRefMap, frameRefMap); - } - } - } - - - @Override - public String toString() { - return debugInfo != null ? debugInfo.toString() : topFrame.toString(); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,446 +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.max.graal.compiler.lir; - -import static com.oracle.max.graal.alloc.util.ValueUtil.*; -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.util.*; - -/** - * The {@code LIRInstruction} class definition. - */ -public abstract class LIRInstruction { - - public static final CiValue[] NO_OPERANDS = {}; - - /** - * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue methods. - * Clients of the class must only call the doValue method that takes additional parameters. - */ - public abstract static class ValueProcedure { - /** - * Iterator method to be overwritten. This version of the iterator does not take additional parameters - * to keep the signature short. - * - * @param value The value that is iterated. - * @return The new value to replace the value that was passed in. - */ - protected CiValue doValue(CiValue value) { - throw Util.shouldNotReachHere("One of the doValue() methods must be overwritten"); - } - - /** - * Iterator method to be overwritten. This version of the iterator gets additional parameters about the - * processed value. - * - * @param value The value that is iterated. - * @param mode The operand mode for the value. - * @param flags A set of flags for the value. - * @return The new value to replace the value that was passed in. - */ - public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - return doValue(value); - } - } - - - /** - * Constants denoting how a LIR instruction uses an operand. - */ - public enum OperandMode { - /** - * The value must have been defined before. It is alive before the instruction until the beginning of the - * instruction, but not necessarily throughout the instruction. A register assigned to it can also be assigend - * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not - * modify the register. - */ - Input, - - /** - * 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, - - /** - * 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, - - /** - * 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, - } - - /** - * Flags for an operand. - */ - public enum OperandFlag { - /** - * The value can be a {@link CiRegisterValue}. - */ - Register, - - /** - * The value can be a {@link CiStackSlot}. - */ - Stack, - - /** - * The value can be a {@link CiAddress}. - */ - Address, - - /** - * The value can be a {@link CiConstant}. - */ - Constant, - - /** - * The value can be {@link CiValue#IllegalValue}. - */ - 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, - - /** - * 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, - } - - /** - * For validity checking of the operand flags defined by instruction subclasses. - */ - private static final EnumMap<OperandMode, EnumSet<OperandFlag>> 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)); - } - - /** - * The opcode of this instruction. - */ - protected final Object code; - - /** - * The output operands for this instruction (modified by the register allocator). - */ - protected final CiValue[] outputs; - - /** - * The input operands for this instruction (modified by the register allocator). - */ - protected final CiValue[] inputs; - - /** - * The alive operands for this instruction (modified by the register allocator). - */ - protected final CiValue[] alives; - - /** - * The temp operands for this instruction (modified by the register allocator). - */ - protected final CiValue[] temps; - - /** - * Used to emit debug information. - */ - public final LIRDebugInfo info; - - /** - * Instruction id for register allocation. - */ - 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. - */ - public LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { - this.code = opcode; - this.outputs = outputs; - this.inputs = inputs; - this.alives = alives; - this.temps = temps; - this.info = info; - this.id = -1; - } - - public abstract void emitCode(TargetMethodAssembler tasm); - - - public final int id() { - return id; - } - - public final void setId(int id) { - this.id = id; - } - - /** - * Gets an input operand of this instruction. - * - * @param index the index of the operand requested. - * @return the {@code index}'th input operand. - */ - protected final CiValue 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 CiValue 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 CiValue temp(int index) { - return temps[index]; - } - - /** - * Gets the result operand for this instruction. - * - * @return return the result operand - */ - protected final CiValue output(int index) { - return outputs[index]; - } - - /** - * Gets the instruction name. - */ - public String name() { - return code.toString(); - } - - public boolean hasOperands() { - return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall(); - } - - private static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - - private void forEach(CiValue[] values, OperandMode mode, ValueProcedure proc) { - for (int i = 0; i < values.length; i++) { - assert ALLOWED_FLAGS.get(mode).containsAll(flagsFor(mode, i)); - - CiValue value = values[i]; - if (isAddress(value)) { - assert flagsFor(mode, i).contains(OperandFlag.Address); - CiAddress address = asAddress(value); - address.base = proc.doValue(address.base, mode, ADDRESS_FLAGS); - address.index = proc.doValue(address.index, mode, ADDRESS_FLAGS); - } else { - values[i] = proc.doValue(values[i], mode, flagsFor(mode, i)); - } - } - } - - 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); - } - } - } - } - - /** - * Returns true when this instruction is a call instruction that destroys all caller-saved registers. - */ - public final boolean hasCall() { - return this instanceof StandardOp.CallOp; - } - - /** - * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be - * assigned to the value. - * <br> - * Subclasses can override this method. The default implementation processes all Input operands as the hints for - * an Output operand, and all Output operands as the hints for an Input operand. - * - * @param value The value the hints are needed for. - * @param mode The operand mode of the value. - * @param proc The procedure invoked for all the hints. If the procedure returns a non-null value, the iteration is stopped - * and the value is returned by this method, i.e., clients can stop the iteration once a suitable hint has been found. - * @return The non-null value returned by the procedure, or null. - */ - public CiValue forEachRegisterHint(CiValue value, OperandMode mode, ValueProcedure proc) { - CiValue[] 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++) { - CiValue result = proc.doValue(hints[i], null, null); - if (result != null) { - return result; - } - } - return null; - } - - /** - * 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 this method will go away when we have named operands, the flags will be specified as annotations instead. - protected abstract EnumSet<OperandFlag> flagsFor(OperandMode mode, int index); - - protected void verify() { - } - - - public final String toStringWithIdPrefix() { - if (id != -1) { - return String.format("%4d %s", id, toString()); - } - 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 (CiValue 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 (CiValue input : inputs) { - buf.append(sep).append(input); - sep = ", "; - } - for (CiValue 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 (CiValue 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 (CiFrame cur = info.topFrame; cur != null; cur = cur.caller()) { - buf.append(sep).append(cur.bci); - sep = ","; - } - buf.append("]"); - } - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString()); - appendDebugInfo(buf); - return buf.toString(); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.lir; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.PhiNode.*; - -public class LIRPhiMapping { - private final Block block; - - private CiValue[][] inputs; - private CiValue[] results; - - public LIRPhiMapping(Block block, LIRGenerator gen) { - this.block = block; - - assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges"; - MergeNode mergeNode = (MergeNode) block.getBeginNode(); - List<PhiNode> phis = mergeNode.phis().snapshot(); - - for (int i = 0; i < phis.size(); i++) { - PhiNode phi = phis.get(i); - if (phi.type() == PhiType.Value) { - gen.setResult(phi, gen.newVariable(phi.kind())); - } - } - } - - public void fillInputs(LIRGenerator gen) { - assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges"; - MergeNode mergeNode = (MergeNode) block.getBeginNode(); - List<PhiNode> phis = mergeNode.phis().snapshot(); - - int numPhis = 0; - for (int i = 0; i < phis.size(); i++) { - if (phis.get(i).type() == PhiType.Value) { - numPhis++; - } - } - int numPreds = block.numberOfPreds(); - - results = new CiValue[numPhis]; - inputs = new CiValue[numPreds][numPhis]; - - int phiIdx = 0; - for (int i = 0; i < phis.size(); i++) { - PhiNode phi = phis.get(i); - if (phi.type() == PhiType.Value) { - results[phiIdx] = gen.operand(phi); - for (int j = 0; j < numPreds; j++) { - assert j == mergeNode.phiPredecessorIndex((FixedNode) block.predAt(j).getEndNode()) : "block predecessors and node predecessors must have same order"; - inputs[j][phiIdx] = gen.operand(phi.valueAt(j)); - } - phiIdx++; - } - } - assert phiIdx == numPhis; - } - - public CiValue[] results() { - return results; - } - - public CiValue[] inputs(Block pred) { - assert pred.numberOfSux() == 1 && pred.suxAt(0) == block; - return inputs[block.getPredecessors().indexOf(pred)]; - } - - private static final EnumSet<OperandFlag> INPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - private static final EnumSet<OperandFlag> OUTPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - - public void forEachInput(Block pred, PhiValueProcedure proc) { - CiValue[] predInputs = inputs(pred); - for (int i = 0; i < predInputs.length; i++) { - predInputs[i] = proc.doValue(predInputs[i], results[i]); - } - } - - public void forEachOutput(ValueProcedure proc) { - for (int i = 0; i < results.length; i++) { - results[i] = proc.doValue(results[i], OperandMode.Output, OUTPUT_FLAGS); - } - } - - public abstract static class PhiValueProcedure extends ValueProcedure { - /** - * Iterator method to be overwritten. This version of the iterator has both the input and output of the phi function as parameters. - * to keep the signature short. - * - * @param input The input value that is iterated. - * @param output The output value that is iterated. - * @return The new value to replace the input value that was passed in. - */ - protected CiValue doValue(CiValue input, CiValue output) { - return doValue(input, OperandMode.Input, INPUT_FLAGS); - } - } - - @Override - public String toString() { - return "PhiMapping for " + block + ": " + Arrays.toString(results); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +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.max.graal.compiler.lir; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.cfg.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.util.*; - -public final class LIRVerifier { - private final LIR lir; - private final FrameMap frameMap; - - private final boolean beforeRegisterAllocation; - - private final BitSet[] blockLiveOut; - private final Object[] variableDefinitions; - - private BitSet liveOutFor(Block block) { - return blockLiveOut[block.getId()]; - } - private void setLiveOutFor(Block block, BitSet liveOut) { - blockLiveOut[block.getId()] = liveOut; - } - - private int maxRegisterNum() { - return frameMap.target.arch.registers.length; - } - - private boolean isAllocatableRegister(CiValue value) { - return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; - } - - public static boolean verify(final LIRInstruction op) { - ValueProcedure allowedProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return allowed(op, value, mode, flags); } }; - - op.forEachInput(allowedProc); - op.forEachAlive(allowedProc); - op.forEachState(allowedProc); - op.forEachTemp(allowedProc); - op.forEachOutput(allowedProc); - - op.verify(); - return true; - } - - public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { - LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap); - verifier.verify(); - return true; - } - - - private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { - this.beforeRegisterAllocation = beforeRegisterAllocation; - this.lir = lir; - this.frameMap = frameMap; - this.blockLiveOut = new BitSet[lir.linearScanOrder().size()]; - this.variableDefinitions = new Object[lir.numVariables()]; - } - - private BitSet curVariablesLive; - private CiValue[] curRegistersLive; - - private Block curBlock; - private Object curInstruction; - private BitSet curRegistersDefined; - - private void verify() { - PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } }; - ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } }; - - curRegistersDefined = new BitSet(); - for (Block block : lir.linearScanOrder()) { - curBlock = block; - curVariablesLive = new BitSet(); - curRegistersLive = new CiValue[maxRegisterNum()]; - - if (block.getDominator() != null) { - curVariablesLive.or(liveOutFor(block.getDominator())); - } - - if (block.phis != null) { - assert beforeRegisterAllocation; - curInstruction = block.phis; - block.phis.forEachOutput(defProc); - } - - assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label"; - if (block.numberOfSux() > 0) { - LIRInstruction last = block.lir.get(block.lir.size() - 1); - assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump"; - } - - for (LIRInstruction op : block.lir) { - curInstruction = op; - - op.forEachInput(useProc); - if (op.hasCall()) { - for (CiRegister register : frameMap.registerConfig.getCallerSaveRegisters()) { - curRegistersLive[register.number] = null; - } - } - curRegistersDefined.clear(); - op.forEachAlive(useProc); - op.forEachState(useProc); - op.forEachTemp(defProc); - op.forEachOutput(defProc); - - curInstruction = null; - } - - for (Block sux : block.getSuccessors()) { - if (sux.phis != null) { - assert beforeRegisterAllocation; - curInstruction = sux.phis; - sux.phis.forEachInput(block, useProc); - } - } - - setLiveOutFor(block, curVariablesLive); - } - } - - private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - allowed(curInstruction, value, mode, flags); - - if (isVariable(value)) { - assert beforeRegisterAllocation; - - int variableIdx = asVariable(value).index; - if (!curVariablesLive.get(variableIdx)) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("live variables: %s", curVariablesLive); - if (variableDefinitions[variableIdx] != null) { - TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); - } - TTY.println("ERROR: Use of variable %s that is not defined in dominator", value); - throw Util.shouldNotReachHere(); - } - - } else if (isAllocatableRegister(value)) { - int regNum = asRegister(value).number; - if (mode == OperandMode.Alive) { - curRegistersDefined.set(regNum); - } - - if (beforeRegisterAllocation && curRegistersLive[regNum] != value) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("live registers: %s", Arrays.toString(curRegistersLive)); - TTY.println("ERROR: Use of fixed register %s that is not defined in this block", value); - throw Util.shouldNotReachHere(); - } - } - return value; - } - - private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { - allowed(curInstruction, value, mode, flags); - - if (isVariable(value)) { - assert beforeRegisterAllocation; - - int variableIdx = asVariable(value).index; - if (variableDefinitions[variableIdx] != null) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("live variables: %s", curVariablesLive); - TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); - TTY.println("ERROR: Variable %s defined multiple times", value); - throw Util.shouldNotReachHere(); - } - assert curInstruction != null; - variableDefinitions[variableIdx] = curInstruction; - assert !curVariablesLive.get(variableIdx); - if (mode == OperandMode.Output) { - curVariablesLive.set(variableIdx); - } - - } else if (isAllocatableRegister(value)) { - int regNum = asRegister(value).number; - if (curRegistersDefined.get(regNum)) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("ERROR: Same register defined twice in the same instruction: %s", value); - throw Util.shouldNotReachHere(); - } - curRegistersDefined.set(regNum); - - if (beforeRegisterAllocation) { - if (mode == OperandMode.Output) { - curRegistersLive[regNum] = value; - } else { - curRegistersLive[regNum] = null; - } - } - } - return value; - } - - private static CiValue allowed(Object op, CiValue value, OperandMode mode, EnumSet<OperandFlag> 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))) { - return value; - } - TTY.println("instruction %s", op); - TTY.println("mode: %s flags: %s", mode, flags); - TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); - throw Util.shouldNotReachHere(); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +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.max.graal.compiler.lir; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.xir.*; -import com.oracle.max.graal.compiler.util.*; - -public abstract class LIRXirInstruction extends LIRInstruction { - - public final CiValue[] 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, - CiValue[] originalOperands, - CiValue outputOperand, - CiValue[] inputs, CiValue[] temps, - int[] inputOperandIndices, int[] tempOperandIndices, - int outputOperandIndex, - LIRDebugInfo info, - LIRDebugInfo infoAfter, - 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 CiValue[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps); - this.infoAfter = infoAfter; - this.snippet = snippet; - this.inputOperandIndices = inputOperandIndices; - this.tempOperandIndices = tempOperandIndices; - this.outputOperandIndex = outputOperandIndex; - this.originalOperands = originalOperands; - this.falseSuccessor = falseSuccessor; - this.trueSuccessor = trueSuccessor; - assert isLegal(outputOperand) || outputOperandIndex == -1; - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - public CiValue[] getOperands() { - for (int i = 0; i < inputOperandIndices.length; i++) { - originalOperands[inputOperandIndices[i]] = alive(i); - } - for (int i = 0; i < tempOperandIndices.length; i++) { - originalOperands[tempOperandIndices[i]] = temp(i); - } - if (outputOperandIndex != -1) { - originalOperands[outputOperandIndex] = output(0); - } - return originalOperands; - } - - @Override - public String name() { - return "XIR: " + snippet.template; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.lir; - -import com.oracle.max.asm.*; -import com.oracle.max.graal.compiler.cfg.*; - -/** - * LIR instructions such as JUMP and BRANCH need to reference their target {@link Block}. However, - * direct references are not possible since the control flow graph (and therefore successors lists) can - * be changed by optimizations - and fixing the instructions is error prone. - * Therefore, we only reference of block B from block A only via the tuple (A, successor-index-of-B), i.e., - * indirectly by storing the index into the successor list of A. - * Note that therefore it is not allowed to reorder the successor list! - * - * Labels of out-of-line stubs can be referenced directly, therefore it is also possible to construct a - * LabelRef for a Label directly via {@link #forLabel}. - */ -public abstract class LabelRef { - - public abstract Label label(); - - /** - * Returns a new reference to a statically defined label. - * @param label The label that is always returned. - * @return The newly created label reference. - */ - public static LabelRef forLabel(final Label label) { - return new LabelRef() { - @Override - public Label label() { - return label; - } - - @Override - public String toString() { - return label.toString(); - } - }; - } - - /** - * Returns a new reference to a successor of the given block. - * This allows to reference the given successor even when the successor list - * is modified between the creation of the reference and the call to {@link #getLabel}. - * @param block The base block that contains the successor list. - * @param suxIndex The index of the successor. - * @return The newly created label reference. - */ - public static LabelRef forSuccessor(final Block block, final int suxIndex) { - return new LabelRef() { - @Override - public Label label() { - return ((StandardOp.LabelOp) block.suxAt(suxIndex).lir.get(0)).getLabel(); - } - - @Override - public String toString() { - return suxIndex < block.numberOfSux() ? block.suxAt(suxIndex).toString() : "?" + block + ":" + suxIndex + "?"; - } - }; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.lir; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.util.*; - -/** - * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR - * operations. - */ -public class StandardOp { - - /** - * Marker interface for a LIR operation that defines the position of a label. - * The first operation of every block must implement this interface. - */ - public interface LabelOp { - Label getLabel(); - } - - /** - * Marker interface for a LIR operation that is an unconditional jump to {@link #destination()}. - * When the LIR is constructed, the last operation of every block must implement this interface. After - * register allocation, unnecessary jumps can be deleted. - * - * TODO Currently, a block can also end with an XIR operation. - */ - public interface JumpOp { - LabelRef destination(); - } - - /** - * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}. - * Conditional jumps may be negated or optimized away after register allocation. - */ - public interface BranchOp { - LabelRef destination(); - void negate(LabelRef newDestination); - } - - /** - * Marker interface for a LIR operation that moves a value from {@link #getInput()} to {@link #getResult()}. - */ - public interface MoveOp { - CiValue getInput(); - CiValue getResult(); - } - - /** - * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved registers. - */ - public interface CallOp { - } - - - /** - * Meta-operation that defines the incoming method parameters. In the LIR, every register and variable must be - * defined before it is used. This operation is the definition point of method parameters, but is otherwise a no-op. - * In particular, it is not the actual method prologue. - */ - public static final class ParametersOp extends LIRInstruction { - public ParametersOp(CiValue[] params) { - super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm) { - // No code to emit. - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw Util.shouldNotReachHere(); - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/Variable.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2010, 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.max.graal.compiler.lir; - -import com.oracle.max.cri.ci.*; - -/** - * Represents a value that is yet to be bound to a machine location (such as - * a {@link CiRegisterValue} or {@link CiStackSlot}) by a register allocator. - */ -public final class Variable extends CiValue { - private static final long serialVersionUID = 4507578431686109809L; - - /** - * The identifier of the variable. This is a non-zero index in a contiguous 0-based name space. - */ - public final int index; - - /** - * The type of register that this variable needs to get assigned. - */ - public final CiRegister.RegisterFlag flag; - - /** - * Creates a new variable. - * @param kind - * @param index - */ - public Variable(CiKind kind, int index, CiRegister.RegisterFlag flag) { - super(kind); - assert kind == kind.stackKind() : "Variables can be only created for stack kinds"; - assert index >= 0; - this.index = index; - this.flag = flag; - } - - @Override - public int hashCode() { - return (index << 4) | kind.ordinal(); - } - - @Override - public String toString() { - return "v" + index + kindSuffix(); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationEvent.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.observer; - -import java.util.*; - -/** - * An event that occurred during compilation. Instances of this class provide information about the event and the state - * of the compilation when the event was raised. Depending on the state of the compiler and the compilation phase, - * different types of objects are provided in the {@link #debugObjects}. The observer should filter events that it is - * interested in by checking if an object of a specific type is provided by the event. - */ -public class CompilationEvent { - - /** - * Marker object for the {@link #debugObject} array: When this object is present, the event is the result of a compilation error. - */ - public static final Object ERROR = new Object() {}; - - public final String label; - private List<Object> debugObjects; - - protected CompilationEvent(String label, ArrayList<Object> debugObjects) { - this.label = label; - this.debugObjects = debugObjects; - } - - @SuppressWarnings("unchecked") - public <T> T debugObject(Class<T> type) { - for (ListIterator<Object> iter = debugObjects.listIterator(debugObjects.size()); iter.hasPrevious();) { - Object o = iter.previous(); - if (type.isInstance(o)) { - return (T) o; - } - } - return null; - } - - public boolean hasDebugObject(Object search) { - for (ListIterator<Object> iter = debugObjects.listIterator(debugObjects.size()); iter.hasPrevious();) { - Object o = iter.previous(); - if (o == search) { - return true; - } - } - return false; - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/CompilationObserver.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.observer; - - -/** - * Interface for classes that observe events of an {@link ObservableCompiler}. - */ -public interface CompilationObserver { - - /** - * Called when compilation of a method has started. This is always the first event raised for a particular - * method compilation. - * - * @param event Information associated with the event and current state of the compilation. - */ - void compilationStarted(CompilationEvent event); - - /** - * Called when an event has occurred, for example that a particular phase in the compilation has been entered. - * - * @param event Information associated with the event and current state of the compilation. - */ - void compilationEvent(CompilationEvent event); - - /** - * Called when compilation of a method has completed (successfully or not). This is always the last event raised for - * a particular method compilation. - * - * @param event Information associated with the event and current state of the compilation. - */ - void compilationFinished(CompilationEvent event); - -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/ObservableContext.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.observer; - -import java.util.*; - -/** - * Base class for compilers that notify subscribed {@link CompilationObserver CompilationObservers} of - * {@link CompilationEvent CompilationEvents} that occur during their compilations. - */ -public class ObservableContext { - - private List<CompilationObserver> observers; - - private ThreadLocal<StringBuilder> scopeName = new ThreadLocal<StringBuilder>() { - @Override - protected StringBuilder initialValue() { - return new StringBuilder(); - } - }; - - private ThreadLocal<ArrayList<Object>> debugObjects = new ThreadLocal<ArrayList<Object>>() { - @Override - protected ArrayList<Object> initialValue() { - return new ArrayList<>(); - } - }; - - /** - * @return {@code true} if one or more observers are subscribed to receive notifications from this compiler, - * {@code false} otherwise. - */ - public boolean isObserved() { - return observers != null; - } - - /** - * Add the specified observer to receive events from this compiler. - * - * @param observer The observer to add. - */ - public void addCompilationObserver(CompilationObserver observer) { - assert observer != null; - - if (observers == null) { - observers = new LinkedList<>(); - } - observers.add(observer); - } - - public void fireCompilationStarted(Object... additionalDebugObjects) { - if (isObserved()) { - addDebugObjects(null, additionalDebugObjects); - CompilationEvent event = new CompilationEvent("started", debugObjects.get()); - for (CompilationObserver observer : observers) { - observer.compilationStarted(event); - } - removeDebugObjects(null, additionalDebugObjects); - } - } - - public void fireCompilationEvent(String label, Object... additionalDebugObjects) { - if (isObserved()) { - addDebugObjects(null, additionalDebugObjects); - CompilationEvent event = new CompilationEvent(label, debugObjects.get()); - for (CompilationObserver observer : observers) { - observer.compilationEvent(event); - } - removeDebugObjects(null, additionalDebugObjects); - } - } - - public void fireCompilationFinished(Object... additionalDebugObjects) { - if (isObserved()) { - addDebugObjects(null, additionalDebugObjects); - CompilationEvent event = new CompilationEvent("finished", debugObjects.get()); - for (CompilationObserver observer : observers) { - observer.compilationFinished(event); - } - removeDebugObjects(null, additionalDebugObjects); - } - } - - /** - * Remove the specified observer so that it no longer receives events from this compiler. - * - * @param observer The observer to remove. - */ - public void removeCompilationObserver(CompilationObserver observer) { - if (observers != null) { - observers.remove(observer); - if (observers.size() == 0) { - observers = null; - } - } - } - - public void clear() { - if (observers != null) { - observers = null; - } - } - - public void addDebugObjects(String name, Object[] additionalDebugObjects) { - if (name != null) { - if (scopeName.get().length() > 0) { - scopeName.get().append('.'); - } - scopeName.get().append(name); - } - for (Object obj : additionalDebugObjects) { - debugObjects.get().add(obj); - } - } - - public void removeDebugObjects(String name, Object[] additionalDebugObjects) { - if (name != null) { - scopeName.get().setLength(Math.max(0, scopeName.get().length() - name.length())); - } - for (int i = 0; i < additionalDebugObjects.length; i++) { - debugObjects.get().remove(debugObjects.get().size() - 1); - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/observer/package-info.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * Classes and interfaces for observing compilations. - */ -package com.oracle.max.graal.compiler.observer;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Wed Feb 08 21:15:00 2012 -0800 @@ -87,7 +87,7 @@ graph.removeFloating((FloatingNode) node); } else { // case 2 - assert canonical instanceof FloatingNode || (canonical instanceof FixedNode && canonical.predecessor() != null) : node + " -> " + canonical + + assert !(canonical instanceof FixedNode) || canonical.predecessor() != null : node + " -> " + canonical + " : replacement should be floating or fixed and connected"; graph.replaceFloating((FloatingNode) node, canonical); }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java Wed Feb 08 21:15:00 2012 -0800 @@ -25,9 +25,9 @@ import java.util.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.PhiNode.PhiType; import com.oracle.max.graal.nodes.extended.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Wed Feb 08 21:15:00 2012 -0800 @@ -197,7 +197,7 @@ } else if (GraalOptions.InliningPolicy == 3) { return new GreedySizeBasedInliningPolicy(); } else { - Util.shouldNotReachHere(); + GraalInternalError.shouldNotReachHere(); return null; } }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Wed Feb 08 21:15:00 2012 -0800 @@ -23,9 +23,9 @@ package com.oracle.max.graal.compiler.phases; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.cri.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.spi.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java Wed Feb 08 21:15:00 2012 -0800 @@ -22,7 +22,7 @@ */ package com.oracle.max.graal.compiler.schedule; -import com.oracle.max.graal.compiler.cfg.*; +import com.oracle.max.graal.lir.cfg.*; /** * The {@code BlockClosure} interface represents a closure for iterating over blocks.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/SchedulePhase.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/SchedulePhase.java Wed Feb 08 21:15:00 2012 -0800 @@ -27,10 +27,10 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.graph.Node.Verbosity; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.extended.*; import com.oracle.max.graal.nodes.virtual.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java Wed Feb 08 21:15:00 2012 -0800 @@ -29,8 +29,8 @@ import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; /** * The {@code Backend} class represents a compiler backend for Graal.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Arithmetic.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,559 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64Arithmetic { - IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, - LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, - FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR, - DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR, - INEG, LNEG, - I2L, L2I, I2B, I2C, I2S, - F2D, D2F, - I2F, I2D, F2I, D2I, - L2F, L2D, F2L, D2L, - MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; - - - public static class Op1Reg extends AMD64LIRInstruction { - public Op1Reg(AMD64Arithmetic opcode, CiValue result, CiValue x) { - super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue result = output(0); - CiValue x = input(0); - - emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - public static class Op1Stack extends AMD64LIRInstruction { - public Op1Stack(AMD64Arithmetic opcode, CiValue result, CiValue x) { - super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue result = output(0); - CiValue x = input(0); - - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result); - } - - @Override - public EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - public static class Op2Stack extends AMD64LIRInstruction { - public Op2Stack(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { - super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue result = output(0); - CiValue x = input(0); - CiValue y = alive(0); - - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - @Override - public void verify() { - CiValue result = output(0); - CiValue x = input(0); - CiValue y = alive(0); - - super.verify(); - assert differentRegisters(result, y) || sameRegister(x, y); - verifyKind((AMD64Arithmetic) code, result, x, y); - } - } - - public static class Op2Reg extends AMD64LIRInstruction { - public Op2Reg(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { - super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue result = output(0); - CiValue x = input(0); - CiValue y = alive(0); - - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - @Override - public void verify() { - CiValue result = output(0); - CiValue x = input(0); - CiValue y = alive(0); - - super.verify(); - assert differentRegisters(result, y) || sameRegister(x, y); - verifyKind((AMD64Arithmetic) code, result, x, y); - } - } - - public static class Op2RegCommutative extends AMD64LIRInstruction { - public Op2RegCommutative(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { - super(opcode, new CiValue[] {result}, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue result = output(0); - CiValue x = input(0); - CiValue y = input(1); - - if (sameRegister(result, y)) { - emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); - } else { - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); - } - } - - @Override - public EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - @Override - protected void verify() { - CiValue result = output(0); - CiValue x = input(0); - CiValue y = input(1); - - super.verify(); - verifyKind((AMD64Arithmetic) code, result, x, y); - } - } - - public static class ShiftOp extends AMD64LIRInstruction { - public ShiftOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { - super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue result = output(0); - CiValue x = input(0); - CiValue y = alive(0); - - AMD64Move.move(tasm, masm, result, x); - emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); - } - - @Override - public EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - @Override - public void verify() { - CiValue result = output(0); - CiValue x = input(0); - CiValue 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); - assert y.kind.stackKind() == CiKind.Int; - } - } - - public static class DivOp extends AMD64LIRInstruction { - public DivOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y, LIRDebugInfo info) { - super(opcode, new CiValue[] {result}, info, new CiValue[] {x}, new CiValue[] {y}, new CiValue[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)}); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue result = output(0); - CiValue y = alive(0); - - emit(tasm, masm, (AMD64Arithmetic) code, result, y, info); - } - - @Override - public EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - @Override - protected void verify() { - CiValue result = output(0); - CiValue x = input(0); - CiValue 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); - } - } - - - @SuppressWarnings("unused") - protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue result) { - switch (opcode) { - case INEG: masm.negl(asIntReg(result)); break; - case LNEG: masm.negq(asLongReg(result)); break; - case L2I: masm.andl(asIntReg(result), 0xFFFFFFFF); break; - case I2B: masm.signExtendByte(asIntReg(result)); break; - case I2C: masm.andl(asIntReg(result), 0xFFFF); break; - case I2S: masm.signExtendShort(asIntReg(result)); break; - default: throw Util.shouldNotReachHere(); - } - } - - protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue dst, CiValue src, LIRDebugInfo info) { - int exceptionOffset = -1; - if (isRegister(src)) { - switch (opcode) { - case IADD: masm.addl(asIntReg(dst), asIntReg(src)); break; - case ISUB: masm.subl(asIntReg(dst), asIntReg(src)); break; - case IAND: masm.andl(asIntReg(dst), asIntReg(src)); break; - case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break; - case IOR: masm.orl(asIntReg(dst), asIntReg(src)); break; - case IXOR: masm.xorl(asIntReg(dst), asIntReg(src)); break; - case ISHL: masm.shll(asIntReg(dst)); break; - case ISHR: masm.sarl(asIntReg(dst)); break; - case IUSHR:masm.shrl(asIntReg(dst)); break; - - case LADD: masm.addq(asLongReg(dst), asLongReg(src)); break; - case LSUB: masm.subq(asLongReg(dst), asLongReg(src)); break; - case LMUL: masm.imulq(asLongReg(dst), asLongReg(src)); break; - case LAND: masm.andq(asLongReg(dst), asLongReg(src)); break; - case LOR: masm.orq(asLongReg(dst), asLongReg(src)); break; - case LXOR: masm.xorq(asLongReg(dst), asLongReg(src)); break; - case LSHL: masm.shlq(asLongReg(dst)); break; - case LSHR: masm.sarq(asLongReg(dst)); break; - case LUSHR:masm.shrq(asLongReg(dst)); break; - - case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break; - case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break; - case FMUL: masm.mulss(asFloatReg(dst), asFloatReg(src)); break; - case FDIV: masm.divss(asFloatReg(dst), asFloatReg(src)); break; - case FAND: masm.andps(asFloatReg(dst), asFloatReg(src)); break; - case FOR: masm.orps(asFloatReg(dst), asFloatReg(src)); break; - case FXOR: masm.xorps(asFloatReg(dst), asFloatReg(src)); break; - - case DADD: masm.addsd(asDoubleReg(dst), asDoubleReg(src)); break; - case DSUB: masm.subsd(asDoubleReg(dst), asDoubleReg(src)); break; - case DMUL: masm.mulsd(asDoubleReg(dst), asDoubleReg(src)); break; - case DDIV: masm.divsd(asDoubleReg(dst), asDoubleReg(src)); break; - case DAND: masm.andpd(asDoubleReg(dst), asDoubleReg(src)); break; - case DOR: masm.orpd(asDoubleReg(dst), asDoubleReg(src)); break; - case DXOR: masm.xorpd(asDoubleReg(dst), asDoubleReg(src)); break; - - case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break; - case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break; - case D2F: masm.cvtsd2ss(asFloatReg(dst), asDoubleReg(src)); break; - case I2F: masm.cvtsi2ssl(asFloatReg(dst), asIntReg(src)); break; - case I2D: masm.cvtsi2sdl(asDoubleReg(dst), asIntReg(src)); break; - case L2F: masm.cvtsi2ssq(asFloatReg(dst), asLongReg(src)); break; - case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break; - case F2I: - masm.cvttss2sil(asIntReg(dst), asFloatReg(src)); - emitConvertFixup(tasm, masm, dst, src); - break; - case D2I: - masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src)); - emitConvertFixup(tasm, masm, dst, src); - break; - case F2L: - masm.cvttss2siq(asLongReg(dst), asFloatReg(src)); - emitConvertFixup(tasm, masm, dst, src); - break; - case D2L: - masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src)); - emitConvertFixup(tasm, masm, dst, src); - break; - case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break; - case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break; - case MOV_F2I: masm.movdl(asIntReg(dst), asFloatReg(src)); break; - case MOV_D2L: masm.movdq(asLongReg(dst), asDoubleReg(src)); break; - - case IDIV: - case IREM: - masm.cdql(); - exceptionOffset = masm.codeBuffer.position(); - masm.idivl(asRegister(src)); - break; - - case LDIV: - case LREM: - Label continuation = new Label(); - if (opcode == LDIV) { - // check for special case of Long.MIN_VALUE / -1 - Label normalCase = new Label(); - masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE); - masm.cmpq(AMD64.rax, AMD64.rdx); - masm.jcc(ConditionFlag.notEqual, normalCase); - masm.cmpl(asRegister(src), -1); - masm.jcc(ConditionFlag.equal, continuation); - masm.bind(normalCase); - } - - masm.cdqq(); - exceptionOffset = masm.codeBuffer.position(); - masm.idivq(asRegister(src)); - masm.bind(continuation); - break; - - case IUDIV: - case IUREM: - // Must zero the high 64-bit word (in RDX) of the dividend - masm.xorq(AMD64.rdx, AMD64.rdx); - exceptionOffset = masm.codeBuffer.position(); - masm.divl(asRegister(src)); - break; - - case LUDIV: - case LUREM: - // Must zero the high 64-bit word (in RDX) of the dividend - masm.xorq(AMD64.rdx, AMD64.rdx); - exceptionOffset = masm.codeBuffer.position(); - masm.divq(asRegister(src)); - break; - default: - throw Util.shouldNotReachHere(); - } - } else if (isConstant(src)) { - switch (opcode) { - case IADD: masm.incrementl(asIntReg(dst), tasm.asIntConst(src)); break; - case ISUB: masm.decrementl(asIntReg(dst), tasm.asIntConst(src)); break; - case IMUL: masm.imull(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break; - case IAND: masm.andl(asIntReg(dst), tasm.asIntConst(src)); break; - case IOR: masm.orl(asIntReg(dst), tasm.asIntConst(src)); break; - case IXOR: masm.xorl(asIntReg(dst), tasm.asIntConst(src)); break; - case ISHL: masm.shll(asIntReg(dst), tasm.asIntConst(src) & 31); break; - case ISHR: masm.sarl(asIntReg(dst), tasm.asIntConst(src) & 31); break; - case IUSHR:masm.shrl(asIntReg(dst), tasm.asIntConst(src) & 31); break; - - case LADD: masm.addq(asLongReg(dst), tasm.asIntConst(src)); break; - case LSUB: masm.subq(asLongReg(dst), tasm.asIntConst(src)); break; - case LMUL: masm.imulq(asLongReg(dst), asLongReg(dst), tasm.asIntConst(src)); break; - case LAND: masm.andq(asLongReg(dst), tasm.asIntConst(src)); break; - case LOR: masm.orq(asLongReg(dst), tasm.asIntConst(src)); break; - case LXOR: masm.xorq(asLongReg(dst), tasm.asIntConst(src)); break; - case LSHL: masm.shlq(asLongReg(dst), tasm.asIntConst(src) & 63); break; - case LSHR: masm.sarq(asLongReg(dst), tasm.asIntConst(src) & 63); break; - case LUSHR:masm.shrq(asLongReg(dst), tasm.asIntConst(src) & 63); break; - - case FADD: masm.addss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; - case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; - case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; - case FAND: masm.andps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; - case FOR: masm.orps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; - case FXOR: masm.xorps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; - case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; - - case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DAND: masm.andpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; - case DOR: masm.orpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; - case DXOR: masm.xorpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; - default: throw Util.shouldNotReachHere(); - } - } else { - switch (opcode) { - case IADD: masm.addl(asIntReg(dst), tasm.asIntAddr(src)); break; - case ISUB: masm.subl(asIntReg(dst), tasm.asIntAddr(src)); break; - case IAND: masm.andl(asIntReg(dst), tasm.asIntAddr(src)); break; - case IOR: masm.orl(asIntReg(dst), tasm.asIntAddr(src)); break; - case IXOR: masm.xorl(asIntReg(dst), tasm.asIntAddr(src)); break; - - case LADD: masm.addq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LSUB: masm.subq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LAND: masm.andq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LOR: masm.orq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LXOR: masm.xorq(asLongReg(dst), tasm.asLongAddr(src)); break; - - case FADD: masm.addss(asFloatReg(dst), tasm.asFloatAddr(src)); break; - case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatAddr(src)); break; - case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatAddr(src)); break; - case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatAddr(src)); break; - - case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; - case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; - case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; - case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; - default: throw Util.shouldNotReachHere(); - } - } - - if (info != null) { - assert exceptionOffset != -1; - tasm.recordImplicitException(exceptionOffset, info); - } - } - - private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) { - ConvertSlowPath slowPath = new ConvertSlowPath(result, x); - tasm.slowPaths.add(slowPath); - switch (result.kind) { - case Int: masm.cmpl(asIntReg(result), Integer.MIN_VALUE); break; - case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(CiConstant.forLong(java.lang.Long.MIN_VALUE))); break; - default: throw Util.shouldNotReachHere(); - } - masm.jcc(ConditionFlag.equal, slowPath.start); - masm.bind(slowPath.continuation); - } - - private static class ConvertSlowPath extends AMD64SlowPath { - public final Label start = new Label(); - public final Label continuation = new Label(); - private final CiValue result; - private final CiValue x; - - public ConvertSlowPath(CiValue result, CiValue x) { - this.result = result; - this.x = x; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.bind(start); - switch (x.kind) { - case Float: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(CiConstant.FLOAT_0)); break; - case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(CiConstant.DOUBLE_0)); break; - default: throw Util.shouldNotReachHere(); - } - Label nan = new Label(); - masm.jcc(ConditionFlag.parity, nan); - masm.jcc(ConditionFlag.below, continuation); - - // input is > 0 -> return maxInt - // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff - switch (result.kind) { - case Int: masm.decrementl(asIntReg(result), 1); break; - case Long: masm.decrementq(asLongReg(result), 1); break; - default: throw Util.shouldNotReachHere(); - } - masm.jmp(continuation); - - // input is NaN -> return 0 - masm.bind(nan); - masm.xorptr(asRegister(result), asRegister(result)); - masm.jmp(continuation); - } - } - - - private static void verifyKind(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { - assert (opcode.name().startsWith("I") && result.kind == CiKind.Int && x.kind.stackKind() == CiKind.Int && y.kind.stackKind() == CiKind.Int) - || (opcode.name().startsWith("L") && result.kind == CiKind.Long && x.kind == CiKind.Long && y.kind == CiKind.Long) - || (opcode.name().startsWith("F") && result.kind == CiKind.Float && x.kind == CiKind.Float && y.kind == CiKind.Float) - || (opcode.name().startsWith("D") && result.kind == CiKind.Double && x.kind == CiKind.Double && y.kind == CiKind.Double); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java Wed Feb 08 21:15:00 2012 -0800 @@ -28,9 +28,9 @@ import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.target.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; /** * The {@code X86Backend} class represents the backend for the AMD64 architecture.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Call.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiTargetMethod.Mark; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public class AMD64Call { - - public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { - private final Object targetMethod; - private final Map<XirMark, Mark> marks; - - public DirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, LIRDebugInfo info, Map<XirMark, Mark> marks) { - super("CALL_DIRECT", new CiValue[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - this.targetMethod = targetMethod; - this.marks = marks; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - callAlignment(tasm, masm); - if (marks != null) { - marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); - } - directCall(tasm, masm, targetMethod, info); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { - private final Object targetMethod; - private final Map<XirMark, Mark> marks; - - private static CiValue[] concat(CiValue[] parameters, CiValue targetAddress) { - CiValue[] result = Arrays.copyOf(parameters, parameters.length + 1); - result[result.length - 1] = targetAddress; - return result; - } - - public IndirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, CiValue targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) { - super("CALL_INDIRECT", new CiValue[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - this.targetMethod = targetMethod; - this.marks = marks; - } - - private CiValue 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<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static void callAlignment(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (GraalOptions.AlignCallsForPatching) { - // make sure that the displacement word of the call ends up word aligned - int offset = masm.codeBuffer.position(); - offset += tasm.target.arch.machineCodeCallDisplacementOffset; - while (offset++ % tasm.target.wordSize != 0) { - masm.nop(); - } - } - } - - public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) { - int before = masm.codeBuffer.position(); - if (target instanceof CiRuntimeCall) { - long maxOffset = tasm.runtime.getMaxCallTargetOffset((CiRuntimeCall) target); - if (maxOffset != (int) maxOffset) { - // offset might not fit a 32-bit immediate, generate an - // indirect call with a 64-bit immediate - CiRegister scratch = tasm.frameMap.registerConfig.getScratchRegister(); - // TODO(cwi): we want to get rid of a generally reserved scratch register. - masm.movq(scratch, 0L); - masm.call(scratch); - } else { - masm.call(); - } - } else { - masm.call(); - } - int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), info); - tasm.recordExceptionHandlers(after, info); - masm.ensureUniquePC(); - } - - public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) { - int before = masm.codeBuffer.position(); - masm.jmp(0, true); - int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), null); - masm.ensureUniquePC(); - } - - public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiRegister dst, Object target, LIRDebugInfo info) { - int before = masm.codeBuffer.position(); - masm.call(dst); - int after = masm.codeBuffer.position(); - tasm.recordIndirectCall(before, after, tasm.runtime.asCallTarget(target), info); - tasm.recordExceptionHandlers(after, info); - masm.ensureUniquePC(); - } - - public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (GraalOptions.GenAssertionCode) { - directCall(tasm, masm, CiRuntimeCall.Debug, null); - masm.hlt(); - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Compare.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64Compare { - ICMP, LCMP, ACMP, FCMP, DCMP; - - public static class CompareOp extends AMD64LIRInstruction { - public CompareOp(AMD64Compare opcode, CiValue x, CiValue y) { - super(opcode, LIRInstruction.NO_OPERANDS, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - CiValue x = input(0); - CiValue y = input(1); - emit(tasm, masm, (AMD64Compare) code, x, y); - } - - @Override - public EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - @Override - protected void verify() { - CiValue x = input(0); - CiValue y = input(1); - - super.verify(); - assert (name().startsWith("I") && x.kind == CiKind.Int && y.kind.stackKind() == CiKind.Int) - || (name().startsWith("I") && x.kind == CiKind.Jsr && y.kind == CiKind.Jsr) - || (name().startsWith("L") && x.kind == CiKind.Long && y.kind == CiKind.Long) - || (name().startsWith("A") && x.kind == CiKind.Object && y.kind == CiKind.Object) - || (name().startsWith("F") && x.kind == CiKind.Float && y.kind == CiKind.Float) - || (name().startsWith("D") && x.kind == CiKind.Double && y.kind == CiKind.Double); - } - } - - protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Compare opcode, CiValue x, CiValue y) { - if (isRegister(y)) { - switch (opcode) { - case ICMP: masm.cmpl(asIntReg(x), asIntReg(y)); break; - case LCMP: masm.cmpq(asLongReg(x), asLongReg(y)); break; - case ACMP: masm.cmpptr(asObjectReg(x), asObjectReg(y)); break; - case FCMP: masm.ucomiss(asFloatReg(x), asFloatReg(y)); break; - case DCMP: masm.ucomisd(asDoubleReg(x), asDoubleReg(y)); break; - default: throw Util.shouldNotReachHere(); - } - } else if (isConstant(y)) { - switch (opcode) { - case ICMP: masm.cmpl(asIntReg(x), tasm.asIntConst(y)); break; - case LCMP: masm.cmpq(asLongReg(x), tasm.asIntConst(y)); break; - case ACMP: - if (((CiConstant) y).isNull()) { - masm.cmpq(asObjectReg(x), 0); break; - } else { - throw Util.shouldNotReachHere("Only null object constants are allowed in comparisons"); - } - case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(y)); break; - case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(y)); break; - default: throw Util.shouldNotReachHere(); - } - } else { - switch (opcode) { - case ICMP: masm.cmpl(asIntReg(x), tasm.asIntAddr(y)); break; - case LCMP: masm.cmpq(asLongReg(x), tasm.asLongAddr(y)); break; - case ACMP: masm.cmpptr(asObjectReg(x), tasm.asObjectAddr(y)); break; - case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatAddr(y)); break; - case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleAddr(y)); break; - default: throw Util.shouldNotReachHere(); - } - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareToIntOpcode.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -/** - * Implementation of the Java bytecodes that compare a long, float, or double value and produce the - * integer constants -1, 0, 1 on less, equal, or greater, respectively. For floating point compares, - * unordered can be either greater {@link #CMP2INT_UG} or less {@link #CMP2INT_UL}. - */ -public enum AMD64CompareToIntOpcode { - CMP2INT, CMP2INT_UG, CMP2INT_UL; - - public LIRInstruction create(CiValue result) { - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(masm, output(0)); - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw Util.shouldNotReachHere(); - } - }; - } - - private void emit(AMD64MacroAssembler masm, CiValue result) { - CiRegister dest = asIntReg(result); - Label high = new Label(); - Label low = new Label(); - Label done = new Label(); - - // comparison is done by a separate LIR instruction before - switch (this) { - case CMP2INT: - masm.jcc(ConditionFlag.greater, high); - masm.jcc(ConditionFlag.less, low); - break; - case CMP2INT_UG: - masm.jcc(ConditionFlag.parity, high); - masm.jcc(ConditionFlag.above, high); - masm.jcc(ConditionFlag.below, low); - break; - case CMP2INT_UL: - masm.jcc(ConditionFlag.parity, low); - masm.jcc(ConditionFlag.above, high); - masm.jcc(ConditionFlag.below, low); - break; - default: - throw Util.shouldNotReachHere(); - } - - // equal -> 0 - masm.xorptr(dest, dest); - masm.jmp(done); - - // greater -> 1 - masm.bind(high); - masm.xorptr(dest, dest); - masm.incrementl(dest, 1); - masm.jmp(done); - - // less -> -1 - masm.bind(low); - masm.xorptr(dest, dest); - masm.decrementl(dest, 1); - - masm.bind(done); - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,448 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiAddress.Scale; -import com.oracle.max.cri.ci.CiTargetMethod.JumpTable; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.nodes.calc.*; - -public class AMD64ControlFlow { - - public static class LabelOp extends AMD64LIRInstruction implements StandardOp.LabelOp { - private final Label label; - private final boolean align; - - public LabelOp(Label label, boolean align) { - super("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - this.label = label; - this.align = align; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (align) { - masm.align(tasm.target.wordSize); - } - masm.bind(label); - } - - @Override - public String operationString() { - return label.toString(); - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - throw Util.shouldNotReachHere(); - } - - @Override - public Label getLabel() { - return label; - } - } - - - public static class ReturnOp extends AMD64LIRInstruction { - public ReturnOp(CiValue input) { - super("RETURN", LIRInstruction.NO_OPERANDS, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.ret(0); - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - } - throw Util.shouldNotReachHere(); - } - } - - - public static class JumpOp extends AMD64LIRInstruction implements StandardOp.JumpOp { - private final LabelRef destination; - - public JumpOp(LabelRef destination, LIRDebugInfo info) { - super("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - this.destination = destination; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.jmp(destination.label()); - } - - @Override - public LabelRef destination() { - return destination; - } - - @Override - public String operationString() { - return "[" + destination + "]"; - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - throw Util.shouldNotReachHere(); - } - } - - - public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp { - protected Condition condition; - protected LabelRef destination; - - public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) { - super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - this.condition = condition; - this.destination = destination; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.jcc(intCond(condition), destination.label()); - } - - @Override - public LabelRef destination() { - return destination; - } - - @Override - public void negate(LabelRef newDestination) { - destination = newDestination; - condition = condition.negate(); - } - - @Override - public String operationString() { - return condition.operator + " [" + destination + "]"; - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - throw Util.shouldNotReachHere(); - } - } - - - public static class FloatBranchOp extends BranchOp { - protected boolean unorderedIsTrue; - - public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRDebugInfo info) { - super(condition, destination, info); - this.unorderedIsTrue = unorderedIsTrue; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - floatJcc(masm, condition, unorderedIsTrue, destination.label()); - } - - @Override - public void negate(LabelRef newDestination) { - super.negate(newDestination); - unorderedIsTrue = !unorderedIsTrue; - } - - @Override - public String operationString() { - return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse"); - } - } - - - public static class TableSwitchOp extends AMD64LIRInstruction { - private final int lowKey; - private final LabelRef defaultTarget; - private final LabelRef[] targets; - - 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 CiValue[] {index}, new CiValue[] {scratch}); - this.lowKey = lowKey; - this.defaultTarget = defaultTarget; - this.targets = targets; - } - - @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<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static class CondMoveOp extends AMD64LIRInstruction { - private final Condition condition; - - public CondMoveOp(Variable result, Condition condition, Variable trueValue, CiValue falseValue) { - super("CMOVE", new CiValue[] {result}, null, new CiValue[] {falseValue}, new CiValue[] {trueValue}, LIRInstruction.NO_OPERANDS); - this.condition = condition; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0)); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - - @Override - public String operationString() { - return condition.toString() + " " + super.operationString(); - } - } - - - public static class FloatCondMoveOp extends AMD64LIRInstruction { - private final Condition condition; - private final boolean unorderedIsTrue; - - public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { - super("FLOAT_CMOVE", new CiValue[] {result}, null, LIRInstruction.NO_OPERANDS, new CiValue[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS); - this.condition = condition; - this.unorderedIsTrue = unorderedIsTrue; - } - - @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<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - private static void tableswitch(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, CiRegister value, CiRegister scratch) { - Buffer buf = masm.codeBuffer; - // Compare index against jump table bounds - int highKey = lowKey + targets.length - 1; - if (lowKey != 0) { - // subtract the low value from the switch value - masm.subl(value, lowKey); - masm.cmpl(value, highKey - lowKey); - } else { - masm.cmpl(value, highKey); - } - - // Jump to default target if index is not within the jump table - masm.jcc(ConditionFlag.above, defaultTarget.label()); - - // Set scratch to address of jump table - int leaPos = buf.position(); - masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), 0)); - int afterLea = buf.position(); - - // Load jump table entry into scratch and jump to it - masm.movslq(value, new CiAddress(CiKind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); - masm.addq(scratch, value); - masm.jmp(scratch); - - // Inserting padding so that jump table address is 4-byte aligned - if ((buf.position() & 0x3) != 0) { - masm.nop(4 - (buf.position() & 0x3)); - } - - // Patch LEA instruction above now that we know the position of the jump table - int jumpTablePos = buf.position(); - buf.setPosition(leaPos); - masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); - buf.setPosition(jumpTablePos); - - // Emit jump table entries - for (LabelRef target : targets) { - Label label = target.label(); - int offsetToJumpTableBase = buf.position() - jumpTablePos; - if (label.isBound()) { - int imm32 = label.position() - jumpTablePos; - buf.emitInt(imm32); - } else { - label.addPatchAt(buf.position()); - - buf.emitByte(0); // psuedo-opcode for jump table entry - buf.emitShort(offsetToJumpTableBase); - buf.emitByte(0); // padding to make jump table entry 4 bytes wide - } - } - - JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); - tasm.targetMethod.addAnnotation(jt); - } - - private static void floatJcc(AMD64MacroAssembler masm, Condition condition, boolean unorderedIsTrue, Label label) { - ConditionFlag cond = floatCond(condition); - Label endLabel = new Label(); - if (unorderedIsTrue && !trueOnUnordered(cond)) { - masm.jcc(ConditionFlag.parity, label); - } else if (!unorderedIsTrue && trueOnUnordered(cond)) { - masm.jcc(ConditionFlag.parity, endLabel); - } - masm.jcc(cond, label); - masm.bind(endLabel); - } - - private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, boolean isFloat, Condition condition, boolean unorderedIsTrue, CiValue trueValue, CiValue falseValue) { - ConditionFlag cond = isFloat ? floatCond(condition) : intCond(condition); - // check that we don't overwrite an input operand before it is used. - assert !result.equals(trueValue); - - AMD64Move.move(tasm, masm, result, falseValue); - cmove(tasm, masm, result, cond, trueValue); - - if (isFloat) { - if (unorderedIsTrue && !trueOnUnordered(cond)) { - cmove(tasm, masm, result, ConditionFlag.parity, trueValue); - } else if (!unorderedIsTrue && trueOnUnordered(cond)) { - cmove(tasm, masm, result, ConditionFlag.parity, falseValue); - } - } - } - - private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, ConditionFlag cond, CiValue other) { - if (isRegister(other)) { - assert asRegister(other) != asRegister(result) : "other already overwritten by previous move"; - switch (other.kind) { - case Int: masm.cmovl(cond, asRegister(result), asRegister(other)); break; - case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break; - default: throw Util.shouldNotReachHere(); - } - } else { - switch (other.kind) { - case Int: masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break; - case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break; - default: throw Util.shouldNotReachHere(); - } - } - } - - private static ConditionFlag intCond(Condition cond) { - switch (cond) { - case EQ: return ConditionFlag.equal; - case NE: return ConditionFlag.notEqual; - case LT: return ConditionFlag.less; - case LE: return ConditionFlag.lessEqual; - case GE: return ConditionFlag.greaterEqual; - case GT: return ConditionFlag.greater; - case BE: return ConditionFlag.belowEqual; - case AE: return ConditionFlag.aboveEqual; - case AT: return ConditionFlag.above; - case BT: return ConditionFlag.below; - case OF: return ConditionFlag.overflow; - case NOF: return ConditionFlag.noOverflow; - default: throw Util.shouldNotReachHere(); - } - } - - private static ConditionFlag floatCond(Condition cond) { - switch (cond) { - case EQ: return ConditionFlag.equal; - case NE: return ConditionFlag.notEqual; - case BT: return ConditionFlag.below; - case BE: return ConditionFlag.belowEqual; - case AE: return ConditionFlag.aboveEqual; - case AT: return ConditionFlag.above; - default: throw Util.shouldNotReachHere(); - } - } - - private static boolean trueOnUnordered(ConditionFlag condition) { - switch(condition) { - case aboveEqual: - case notEqual: - case above: - case less: - case overflow: - return false; - case equal: - case belowEqual: - case below: - case greaterEqual: - case noOverflow: - return true; - default: - throw Util.shouldNotReachHere(); - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Wed Feb 08 21:15:00 2012 -0800 @@ -28,9 +28,10 @@ import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.amd64.*; +import com.oracle.max.graal.lir.asm.*; import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction; public class AMD64DeoptimizationStub extends AMD64SlowPath { @@ -79,7 +80,7 @@ code = 4; break; default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } masm.movq(scratch, code); // TODO Why use scratch register here? Is it an implicit calling convention that the runtime function reads this register?
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Feb 08 21:15:00 2012 -0800 @@ -24,9 +24,9 @@ package com.oracle.max.graal.compiler.target.amd64; import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64Compare.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64CompareToIntOpcode.*; +import static com.oracle.max.graal.lir.amd64.AMD64Arithmetic.*; +import static com.oracle.max.graal.lir.amd64.AMD64Compare.*; +import static com.oracle.max.graal.lir.amd64.AMD64CompareToIntOpcode.*; import java.util.*; @@ -38,35 +38,35 @@ import com.oracle.max.cri.xir.CiXirAssembler.XirMark; import com.oracle.max.cri.xir.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.DivOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Reg; -import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Stack; -import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2Reg; -import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2Stack; -import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.ShiftOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Call.DirectCallOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Call.IndirectCallOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Compare.CompareOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.BranchOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.CondMoveOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.FloatBranchOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.FloatCondMoveOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.JumpOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.LabelOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.ReturnOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.TableSwitchOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.CompareAndSwapOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.LeaOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.LoadOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.MembarOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.MoveFromRegOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.MoveToRegOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.NullCheckOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.SpillMoveOp; -import com.oracle.max.graal.compiler.target.amd64.AMD64Move.StoreOp; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.StandardOp.JumpOp; +import com.oracle.max.graal.lir.StandardOp.LabelOp; +import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.DivOp; +import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op1Reg; +import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op1Stack; +import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op2Reg; +import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op2Stack; +import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.ShiftOp; +import com.oracle.max.graal.lir.amd64.AMD64Call.DirectCallOp; +import com.oracle.max.graal.lir.amd64.AMD64Call.IndirectCallOp; +import com.oracle.max.graal.lir.amd64.AMD64Compare.CompareOp; +import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.BranchOp; +import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; +import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp; +import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.FloatCondMoveOp; +import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.ReturnOp; +import com.oracle.max.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.CompareAndSwapOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.LeaOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.LoadOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.MembarOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.MoveFromRegOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.MoveToRegOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.NullCheckOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.SpillMoveOp; +import com.oracle.max.graal.lir.amd64.AMD64Move.StoreOp; import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.calc.*; @@ -222,7 +222,7 @@ case Object: append(new BranchOp(cond, label, info)); break; case Float: case Double: append(new FloatBranchOp(cond, unorderedIsTrue, label, info)); break; - default: throw Util.shouldNotReachHere("" + left.kind); + default: throw GraalInternalError.shouldNotReachHere("" + left.kind); } } @@ -253,7 +253,7 @@ case Object: append(new CompareOp(ACMP, left, right)); break; case Float: append(new CompareOp(FCMP, left, right)); break; case Double: append(new CompareOp(DCMP, left, right)); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } } @@ -265,7 +265,7 @@ case Long: append(new Op1Stack(LNEG, result, input)); break; case Float: append(new Op2Reg(FXOR, result, input, CiConstant.forFloat(Float.intBitsToFloat(0x80000000)))); break; case Double: append(new Op2Reg(DXOR, result, input, CiConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -278,7 +278,7 @@ case Long: append(new Op2Stack(LADD, result, a, loadNonConst(b))); break; case Float: append(new Op2Stack(FADD, result, a, loadNonConst(b))); break; case Double: append(new Op2Stack(DADD, result, a, loadNonConst(b))); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -291,7 +291,7 @@ case Long: append(new Op2Stack(LSUB, result, a, loadNonConst(b))); break; case Float: append(new Op2Stack(FSUB, result, a, loadNonConst(b))); break; case Double: append(new Op2Stack(DSUB, result, a, loadNonConst(b))); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -304,7 +304,7 @@ case Long: append(new Op2Reg(LMUL, result, a, loadNonConst(b))); break; case Float: append(new Op2Stack(FMUL, result, a, loadNonConst(b))); break; case Double: append(new Op2Stack(DMUL, result, a, loadNonConst(b))); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -331,7 +331,7 @@ return result; } default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } } @@ -351,7 +351,7 @@ case Double: return emitCallToRuntime(CiRuntimeCall.ArithmeticDrem, false, a, b); default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } } @@ -367,7 +367,7 @@ append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state())); return emitMove(RAX_L); default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } } @@ -383,7 +383,7 @@ append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state())); return emitMove(RDX_L); default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } } @@ -394,7 +394,7 @@ switch(a.kind) { case Int: append(new Op2Stack(IAND, result, a, loadNonConst(b))); break; case Long: append(new Op2Stack(LAND, result, a, loadNonConst(b))); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -405,7 +405,7 @@ switch(a.kind) { case Int: append(new Op2Stack(IOR, result, a, loadNonConst(b))); break; case Long: append(new Op2Stack(LOR, result, a, loadNonConst(b))); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -416,7 +416,7 @@ switch(a.kind) { case Int: append(new Op2Stack(IXOR, result, a, loadNonConst(b))); break; case Long: append(new Op2Stack(LXOR, result, a, loadNonConst(b))); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -428,7 +428,7 @@ switch (a.kind) { case Int: append(new ShiftOp(ISHL, result, a, loadShiftCount(b))); break; case Long: append(new ShiftOp(LSHL, result, a, loadShiftCount(b))); break; - default: Util.shouldNotReachHere(); + default: GraalInternalError.shouldNotReachHere(); } return result; } @@ -439,7 +439,7 @@ switch (a.kind) { case Int: append(new ShiftOp(ISHR, result, a, loadShiftCount(b))); break; case Long: append(new ShiftOp(LSHR, result, a, loadShiftCount(b))); break; - default: Util.shouldNotReachHere(); + default: GraalInternalError.shouldNotReachHere(); } return result; } @@ -450,7 +450,7 @@ switch (a.kind) { case Int: append(new ShiftOp(IUSHR, result, a, loadShiftCount(b))); break; case Long: append(new ShiftOp(LUSHR, result, a, loadShiftCount(b))); break; - default: Util.shouldNotReachHere(); + default: GraalInternalError.shouldNotReachHere(); } return result; } @@ -489,7 +489,7 @@ case MOV_L2D: append(new Op1Reg(MOV_L2D, result, input)); break; case MOV_F2I: append(new Op1Reg(MOV_F2I, result, input)); break; case MOV_D2L: append(new Op1Reg(MOV_D2L, result, input)); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } return result; } @@ -618,7 +618,7 @@ append(CMP2INT.create(result)); break; default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } setResult(x, result); }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRInstruction.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.target.amd64; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; - -/** - * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method. - */ -public abstract class AMD64LIRInstruction extends LIRInstruction { - - public AMD64LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { - super(opcode, outputs, info, inputs, alives, temps); - } - - @Override - public final void emitCode(TargetMethodAssembler tasm) { - emitCode(tasm, (AMD64MacroAssembler) tasm.asm); - } - - public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm); -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MethodEndStub.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MethodEndStub.java Wed Feb 08 21:15:00 2012 -0800 @@ -24,7 +24,8 @@ import com.oracle.max.asm.target.amd64.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.lir.amd64.*; +import com.oracle.max.graal.lir.asm.*; public class AMD64MethodEndStub extends AMD64SlowPath { @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Move.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,485 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static java.lang.Double.*; -import static java.lang.Float.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.StandardOp.MoveOp; -import com.oracle.max.graal.compiler.util.*; - -public class AMD64Move { - - public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp { - public SpillMoveOp(CiValue result, CiValue input) { - super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - move(tasm, masm, getResult(), getInput()); - } - - @Override - public CiValue getInput() { - return input(0); - } - @Override - public CiValue getResult() { - return output(0); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp { - public MoveToRegOp(CiValue result, CiValue input) { - super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - move(tasm, masm, getResult(), getInput()); - } - - @Override - public CiValue getInput() { - return input(0); - } - @Override - public CiValue getResult() { - return output(0); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp { - public MoveFromRegOp(CiValue result, CiValue input) { - super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - move(tasm, masm, getResult(), getInput()); - } - - @Override - public CiValue getInput() { - return input(0); - } - @Override - public CiValue getResult() { - return output(0); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static class LoadOp extends AMD64LIRInstruction { - public LoadOp(CiValue result, CiValue address, LIRDebugInfo info) { - super("LOAD", new CiValue[] {result}, info, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - load(tasm, masm, output(0), (CiAddress) input(0), info); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static class StoreOp extends AMD64LIRInstruction { - public StoreOp(CiValue address, CiValue input, LIRDebugInfo info) { - super("STORE", LIRInstruction.NO_OPERANDS, info, new CiValue[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - store(tasm, masm, (CiAddress) input(0), input(1), info); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static class LeaOp extends AMD64LIRInstruction { - public LeaOp(CiValue result, CiValue address) { - super("LEA", new CiValue[] {result}, null, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0))); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - public static class MembarOp extends AMD64LIRInstruction { - 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; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.membar(barriers); - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - throw Util.shouldNotReachHere(); - } - } - - - public static class NullCheckOp extends AMD64LIRInstruction { - public NullCheckOp(Variable input, LIRDebugInfo info) { - super("NULL_CHECK", LIRInstruction.NO_OPERANDS, info, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - masm.nullCheck(asRegister(input(0))); - } - - @Override - protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register); - } - throw Util.shouldNotReachHere(); - } - } - - - public static class CompareAndSwapOp extends AMD64LIRInstruction { - public CompareAndSwapOp(CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { - super("CAS", new CiValue[] {result}, null, new CiValue[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2)); - } - - @Override - protected EnumSet<OperandFlag> 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 Util.shouldNotReachHere(); - } - } - - - protected static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { - if (isRegister(input)) { - if (isRegister(result)) { - reg2reg(masm, result, input); - } else if (isStackSlot(result)) { - reg2stack(tasm, masm, result, input); - } else { - throw Util.shouldNotReachHere(); - } - } else if (isStackSlot(input)) { - if (isRegister(result)) { - stack2reg(tasm, masm, result, input); - } else { - throw Util.shouldNotReachHere(); - } - } else if (isConstant(input)) { - if (isRegister(result)) { - const2reg(tasm, masm, result, (CiConstant) input); - } else if (isStackSlot(result)) { - const2stack(tasm, masm, result, (CiConstant) input); - } else { - throw Util.shouldNotReachHere(); - } - } else { - throw Util.shouldNotReachHere(); - } - } - - private static void reg2reg(AMD64MacroAssembler masm, CiValue result, CiValue input) { - if (input.equals(result)) { - return; - } - switch (result.kind) { - case Jsr: - case Int: masm.movl(asRegister(result), asRegister(input)); break; - case Long: masm.movq(asRegister(result), asRegister(input)); break; - case Float: masm.movflt(asFloatReg(result), asFloatReg(input)); break; - case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break; - case Object: masm.movq(asRegister(result), asRegister(input)); break; - default: throw Util.shouldNotReachHere("kind=" + result.kind); - } - } - - private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { - switch (result.kind) { - case Jsr: - case Int: masm.movl(tasm.asAddress(result), asRegister(input)); break; - case Long: masm.movq(tasm.asAddress(result), asRegister(input)); break; - case Float: masm.movflt(tasm.asAddress(result), asFloatReg(input)); break; - case Double: masm.movsd(tasm.asAddress(result), asDoubleReg(input)); break; - case Object: masm.movq(tasm.asAddress(result), asRegister(input)); break; - default: throw Util.shouldNotReachHere(); - } - } - - private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { - switch (result.kind) { - case Jsr: - case Int: masm.movl(asRegister(result), tasm.asAddress(input)); break; - case Long: masm.movq(asRegister(result), tasm.asAddress(input)); break; - case Float: masm.movflt(asFloatReg(result), tasm.asAddress(input)); break; - case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break; - case Object: masm.movq(asRegister(result), tasm.asAddress(input)); break; - default: throw Util.shouldNotReachHere(); - } - } - - private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { - switch (result.kind) { - case Jsr: - case Int: - // Do not optimize with an XOR as this instruction may be between - // a CMP and a Jcc in which case the XOR will modify the condition - // flags and interfere with the Jcc. - masm.movl(asRegister(result), tasm.asIntConst(c)); - break; - case Long: - // Do not optimize with an XOR as this instruction may be between - // a CMP and a Jcc in which case the XOR will modify the condition - // flags and interfere with the Jcc. - masm.movq(asRegister(result), c.asLong()); - break; - case Float: - // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f - if (Float.floatToRawIntBits(c.asFloat()) == Float.floatToRawIntBits(0.0f)) { - masm.xorps(asFloatReg(result), asFloatReg(result)); - } else { - masm.movflt(asFloatReg(result), tasm.asFloatConstRef(c)); - } - break; - case Double: - // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d - if (Double.doubleToRawLongBits(c.asDouble()) == Double.doubleToRawLongBits(0.0d)) { - masm.xorpd(asDoubleReg(result), asDoubleReg(result)); - } else { - masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(c)); - } - break; - case Object: - // Do not optimize with an XOR as this instruction may be between - // a CMP and a Jcc in which case the XOR will modify the condition - // flags and interfere with the Jcc. - if (c.isNull()) { - masm.movq(asRegister(result), 0x0L); - } else if (tasm.target.inlineObjects) { - tasm.recordDataReferenceInCode(c, 0); - masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); - } else { - masm.movq(asRegister(result), tasm.recordDataReferenceInCode(c, 0)); - } - break; - default: - throw Util.shouldNotReachHere(); - } - } - - private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { - switch (result.kind) { - case Jsr: - case Int: masm.movl(tasm.asAddress(result), c.asInt()); break; - case Long: masm.movlong(tasm.asAddress(result), c.asLong()); break; - case Float: masm.movl(tasm.asAddress(result), floatToRawIntBits(c.asFloat())); break; - case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(c.asDouble())); break; - case Object: - if (c.isNull()) { - masm.movlong(tasm.asAddress(result), 0L); - } else { - throw Util.shouldNotReachHere("Non-null object constants must be in register"); - } - break; - default: - throw Util.shouldNotReachHere(); - } - } - - - protected static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress loadAddr, LIRDebugInfo info) { - if (info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - } - switch (loadAddr.kind) { - case Boolean: - case Byte: masm.movsxb(asRegister(result), loadAddr); break; - case Char: masm.movzxl(asRegister(result), loadAddr); break; - case Short: masm.movswl(asRegister(result), loadAddr); break; - case Int: masm.movslq(asRegister(result), loadAddr); break; - case Long: masm.movq(asRegister(result), loadAddr); break; - case Float: masm.movflt(asFloatReg(result), loadAddr); break; - case Double: masm.movdbl(asDoubleReg(result), loadAddr); break; - case Object: masm.movq(asRegister(result), loadAddr); break; - default: throw Util.shouldNotReachHere(); - } - } - - protected static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiAddress storeAddr, CiValue input, LIRDebugInfo info) { - if (info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - } - - if (isRegister(input)) { - switch (storeAddr.kind) { - case Boolean: - case Byte: masm.movb(storeAddr, asRegister(input)); break; - case Char: - case Short: masm.movw(storeAddr, asRegister(input)); break; - case Int: masm.movl(storeAddr, asRegister(input)); break; - case Long: masm.movq(storeAddr, asRegister(input)); break; - case Float: masm.movflt(storeAddr, asFloatReg(input)); break; - case Double: masm.movsd(storeAddr, asDoubleReg(input)); break; - case Object: masm.movq(storeAddr, asRegister(input)); break; - default: throw Util.shouldNotReachHere(); - } - } else if (isConstant(input)) { - CiConstant c = (CiConstant) input; - switch (storeAddr.kind) { - case Boolean: - case Byte: masm.movb(storeAddr, c.asInt() & 0xFF); break; - case Char: - case Short: masm.movw(storeAddr, c.asInt() & 0xFFFF); break; - case Jsr: - case Int: masm.movl(storeAddr, c.asInt()); break; - case Long: - if (Util.isInt(c.asLong())) { - masm.movslq(storeAddr, (int) c.asLong()); - } else { - throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - case Float: masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break; - case Double: throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); - case Object: - if (c.isNull()) { - masm.movptr(storeAddr, 0); - } else { - throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - default: - throw Util.shouldNotReachHere(); - } - - } else { - throw Util.shouldNotReachHere(); - } - } - - protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { - assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; - - if (tasm.target.isMP) { - masm.lock(); - } - switch (cmpValue.kind) { - case Int: masm.cmpxchgl(asRegister(newValue), address); break; - case Long: - case Object: masm.cmpxchgq(asRegister(newValue), address); break; - default: throw Util.shouldNotReachHere(); - } - } -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64SlowPath.java Wed Feb 08 21:13:35 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; - -/** - * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method. - */ -public abstract class AMD64SlowPath implements LIR.SlowPath { - @Override - public final void emitCode(TargetMethodAssembler tasm) { - emitCode(tasm, (AMD64MacroAssembler) tasm.asm); - } - - public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm); -}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOp.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOp.java Wed Feb 08 21:15:00 2012 -0800 @@ -39,9 +39,10 @@ import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; import com.oracle.max.cri.xir.CiXirAssembler.XirMark; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.amd64.*; +import com.oracle.max.graal.lir.asm.*; public class AMD64XirOp extends LIRXirInstruction { public AMD64XirOp(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, @@ -480,7 +481,7 @@ break; } default: - throw Util.shouldNotReachHere("Unknown XIR operation " + inst.op); + throw GraalInternalError.shouldNotReachHere("Unknown XIR operation " + inst.op); } } } @@ -493,7 +494,7 @@ case Long: code = longOp; break; case Float: code = floatOp; break; case Double: code = doubleOp; break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } assert left == result; if (isRegister(right) && right.kind != result.kind) { @@ -514,7 +515,7 @@ case Object: code = AMD64Compare.ACMP; break; case Float: code = AMD64Compare.FCMP; break; case Double: code = AMD64Compare.DCMP; break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } AMD64Compare.emit(tasm, masm, code, x, y); masm.jcc(cflag, label);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java Wed Feb 08 21:15:00 2012 -0800 @@ -42,22 +42,6 @@ public static final char SUB_SECTION_CHARACTER = '='; public static final char SEPERATOR_CHARACTER = '-'; - public static RuntimeException unimplemented() { - throw new GraalInternalError("unimplemented"); - } - - public static RuntimeException unimplemented(String msg, Object... args) { - throw new GraalInternalError("unimplemented: " + msg, args); - } - - public static RuntimeException shouldNotReachHere() { - throw new GraalInternalError("should not reach here"); - } - - public static RuntimeException shouldNotReachHere(String msg, Object... args) { - throw new GraalInternalError("should not reach here: " + msg, args); - } - public static <T> boolean replaceInList(T a, T b, List<T> list) { final int max = list.size(); for (int i = 0; i < max; i++) {
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java Wed Feb 08 21:15:00 2012 -0800 @@ -26,8 +26,8 @@ import java.util.*; import java.util.concurrent.*; +public class Debug { -public class Debug { private static boolean ENABLED = false; public static void enable() { @@ -73,7 +73,7 @@ public static void scope(String name, Object context, Runnable runnable) { if (ENABLED) { - DebugScope.getInstance().scope(name, runnable, null, false, new Object[]{context}); + DebugScope.getInstance().scope(name, runnable, null, false, new Object[] {context}); } else { runnable.run(); } @@ -89,7 +89,7 @@ public static <T> T scope(String name, Object context, Callable<T> callable) { if (ENABLED) { - return DebugScope.getInstance().scope(name, null, callable, false, new Object[]{context}); + return DebugScope.getInstance().scope(name, null, callable, false, new Object[] {context}); } else { return DebugScope.call(callable); } @@ -130,6 +130,18 @@ } } + @SuppressWarnings("unchecked") + public static <T> T contextLookup(Class<T> clazz) { + if (ENABLED) { + for (Object o : context()) { + if (clazz.isInstance(o)) { + return ((T) o); + } + } + } + return null; + } + public static DebugMetric metric(String name) { if (ENABLED) { return new MetricImpl(name); @@ -168,8 +180,8 @@ } @Override - public RuntimeException interceptException(RuntimeException e) { - return e; + public RuntimeException interceptException(Throwable e) { + return null; } @Override @@ -180,8 +192,12 @@ } private static final DebugMetric VOID_METRIC = new DebugMetric() { - public void increment() { } - public void add(int value) { } + + public void increment() { + } + + public void add(int value) { + } }; public static DebugTimer timer(String name) { @@ -193,6 +209,9 @@ } private static final DebugTimer VOID_TIMER = new DebugTimer() { - public TimerCloseable start() { return TimerImpl.VOID_CLOSEABLE; } + + public TimerCloseable start() { + return TimerImpl.VOID_CLOSEABLE; + } }; }
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/DebugConfig.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/DebugConfig.java Wed Feb 08 21:15:00 2012 -0800 @@ -30,6 +30,6 @@ boolean isMeterEnabled(); boolean isDumpEnabled(); boolean isTimeEnabled(); - RuntimeException interceptException(RuntimeException e); + RuntimeException interceptException(Throwable e); Collection<? extends DebugDumpHandler> dumpHandlers(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/DebugDumpScope.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,36 @@ +/* + * 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.max.graal.debug; + +public final class DebugDumpScope { + + private final String name; + + public DebugDumpScope(String name) { + this.name = name; + } + + public String getName() { + return name; + } +}
--- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java Wed Feb 08 21:15:00 2012 -0800 @@ -32,7 +32,7 @@ private static ThreadLocal<DebugScope> instanceTL = new ThreadLocal<>(); private static ThreadLocal<DebugConfig> configTL = new ThreadLocal<>(); - private static ThreadLocal<RuntimeException> lastExceptionThrownTL = new ThreadLocal<>(); + private static ThreadLocal<Throwable> lastExceptionThrownTL = new ThreadLocal<>(); private static DebugTimer scopeTime = Debug.timer("ScopeTime"); private static DebugMetric scopeCount = Debug.metric("ScopeCount"); @@ -73,6 +73,7 @@ this.parent = parent; this.context = context; this.qualifiedName = qualifiedName; + assert context != null; } public boolean isDumpEnabled() { @@ -128,7 +129,7 @@ if (!sandbox && newChild.hasValueMap()) { getValueMap().addChild(newChild.getValueMap()); } - newChild.deactivate(); + newChild.context = null; instanceTL.set(oldContext); setConfig(oldConfig); } @@ -142,13 +143,18 @@ if (callable != null) { return call(callable); } - } catch (RuntimeException e) { + } catch (Throwable e) { if (e == lastExceptionThrownTL.get()) { throw e; } else { RuntimeException newException = interceptException(e); - lastExceptionThrownTL.set(newException); - throw newException; + if (newException == null) { + lastExceptionThrownTL.set(e); + throw e; + } else { + lastExceptionThrownTL.set(newException); + throw newException; + } } } return null; @@ -169,11 +175,7 @@ } } - private void deactivate() { - context = null; - } - - private RuntimeException interceptException(final RuntimeException e) { + private RuntimeException interceptException(final Throwable e) { final DebugConfig config = getConfig(); if (config != null) { return scope("InterceptException", null, new Callable<RuntimeException>() { @@ -183,12 +185,12 @@ try { return config.interceptException(e); } catch (Throwable t) { - return e; + return new RuntimeException("Exception while intercepting exception", e); } } }, false, new Object[] {e}); } - return e; + return null; } private DebugValueMap getValueMap() {
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/GraalInternalError.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/GraalInternalError.java Wed Feb 08 21:15:00 2012 -0800 @@ -30,13 +30,30 @@ public class GraalInternalError extends Error { /** - * + * */ private static final long serialVersionUID = 8776065085829593278L; private Node node; private Graph graph; private final ArrayList<String> context = new ArrayList<>(); + public static RuntimeException unimplemented() { + throw new GraalInternalError("unimplemented"); + } + + public static RuntimeException unimplemented(String msg) { + throw new GraalInternalError("unimplemented: %s", msg); + } + + public static RuntimeException shouldNotReachHere() { + throw new GraalInternalError("should not reach here"); + } + + public static RuntimeException shouldNotReachHere(String msg) { + throw new GraalInternalError("should not reach here: %s", msg); + } + + /** * This constructor creates a {@link GraalInternalError} with a message assembled via {@link String#format(String, Object...)}. * It always uses the ENGLISH locale in order to always generate the same output.
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/Compiler.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/Compiler.java Wed Feb 08 21:15:00 2012 -0800 @@ -34,7 +34,7 @@ CompilerToVM getVMEntries(); VMToCompiler getVMExits(); GraalCompiler getCompiler(); - RiType lookupType(String returnType, HotSpotTypeResolved accessingClass); + RiType lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve); HotSpotVMConfig getConfig(); GraalRuntime getRuntime(); CiTarget getTarget();
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -176,7 +176,7 @@ } @Override - public RiType lookupType(String returnType, HotSpotTypeResolved accessingClass) { + public RiType lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve) { if (returnType.length() == 1 && vmExits instanceof VMToCompilerImpl) { VMToCompilerImpl exitsNative = (VMToCompilerImpl) vmExits; CiKind kind = CiKind.fromPrimitiveOrVoidTypeChar(returnType.charAt(0)); @@ -207,7 +207,7 @@ return exitsNative.typeVoid; } } - return vmEntries.RiSignature_lookupType(returnType, accessingClass); + return vmEntries.RiSignature_lookupType(returnType, accessingClass, eagerResolve); } @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java Wed Feb 08 21:15:00 2012 -0800 @@ -49,6 +49,7 @@ this.dumpFilter = dumpFilter; this.methodFilter = methodFilter; dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort)); + dumpHandlers.add(new CFGPrinterObserver()); } public boolean isLogEnabled() { @@ -120,9 +121,9 @@ } @Override - public RuntimeException interceptException(RuntimeException e) { + public RuntimeException interceptException(Throwable e) { if (e instanceof CiBailout) { - return e; + return null; } Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers)); // sync "Exception occured in scope: " with mx/sanitycheck.py::Test.__init__ @@ -135,7 +136,7 @@ Debug.dump(o, "Exception graph"); } } - return e; + return null; } @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java Wed Feb 08 21:15:00 2012 -0800 @@ -53,7 +53,7 @@ boolean HotSpotMethodData_isMature(HotSpotMethodData methodData); - RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); + RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve); Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -60,7 +60,7 @@ public native int RiMethod_invocationCount(HotSpotMethodResolved method); @Override - public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); + public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass, boolean eagerResolve); @Override public native Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -239,19 +239,13 @@ // to add something to its own queue. return; } - } else { - if (GraalOptions.Debug) { - Debug.enable(); - HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter); - Debug.setConfig(hotspotDebugConfig); - } } Runnable runnable = new Runnable() { public void run() { try { - PhasePlan plan = getDefaultPhasePlan(); + final PhasePlan plan = getDefaultPhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime()); plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); long startTime = 0; @@ -265,7 +259,12 @@ CiTargetMethod result = null; TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method); try { - result = compiler.getCompiler().compileMethod(method, -1, plan); + result = Debug.scope("Compiling", method, new Callable<CiTargetMethod>() { + @Override + public CiTargetMethod call() throws Exception { + return compiler.getCompiler().compileMethod(method, -1, plan); + } + }); } finally { filter.remove(); if (printCompilation) {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRegisterConfig.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRegisterConfig.java Wed Feb 08 21:15:00 2012 -0800 @@ -28,10 +28,10 @@ import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiCallingConvention.*; -import com.oracle.max.cri.ci.CiRegister.*; +import com.oracle.max.cri.ci.CiCallingConvention.Type; +import com.oracle.max.cri.ci.CiRegister.RegisterFlag; import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.hotspot.*; public class HotSpotRegisterConfig implements RiRegisterConfig { @@ -146,7 +146,7 @@ } break; default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } if (locations[i] == null) {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java Wed Feb 08 21:15:00 2012 -0800 @@ -437,7 +437,7 @@ private CiTargetMethod createCallbackStub(RiResolvedMethod method, CiGenericCallback callback) { StructuredGraph graph = new StructuredGraph(); - FrameStateBuilder frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph); + FrameStateBuilder frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph, false); ValueNode local0 = frameState.loadLocal(0); FrameState initialFrameState = frameState.create(0);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotSignature.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotSignature.java Wed Feb 08 21:15:00 2012 -0800 @@ -117,13 +117,13 @@ } @Override - public RiType argumentTypeAt(int index, RiType accessingClass) { + public RiType argumentTypeAt(int index, RiResolvedType accessingClass) { if (argumentTypes == null) { argumentTypes = new RiType[arguments.size()]; } RiType type = argumentTypes[index]; if (type == null) { - type = compiler.lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass); + type = compiler.lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass, false); argumentTypes[index] = type; } return type; @@ -142,7 +142,7 @@ @Override public RiType returnType(RiType accessingClass) { if (returnTypeCache == null) { - returnTypeCache = compiler.lookupType(returnType, (HotSpotTypeResolved) accessingClass); + returnTypeCache = compiler.lookupType(returnType, (HotSpotTypeResolved) accessingClass, false); } return returnTypeCache; }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypePrimitive.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypePrimitive.java Wed Feb 08 21:15:00 2012 -0800 @@ -26,7 +26,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.hotspot.Compiler; /** @@ -74,7 +74,7 @@ @Override public CiConstant getEncoding(Representation r) { - throw Util.unimplemented("HotSpotTypePrimitive.getEncoding"); + throw GraalInternalError.unimplemented("HotSpotTypePrimitive.getEncoding"); } @Override @@ -166,4 +166,9 @@ public Class< ? > toJava() { return kind.toJavaClass(); } + + @Override + public RiResolvedType resolve(RiResolvedType accessingClass) { + return this; + } }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -253,4 +253,9 @@ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { return toJava().getAnnotation(annotationClass); } + + @Override + public RiResolvedType resolve(RiResolvedType accessingClass) { + return this; + } }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeUnresolved.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeUnresolved.java Wed Feb 08 21:15:00 2012 -0800 @@ -31,9 +31,6 @@ */ public class HotSpotTypeUnresolved extends HotSpotType { - /** - * - */ private static final long serialVersionUID = -2320936267633521314L; public final String simpleName; public final int dimensions; @@ -46,13 +43,14 @@ assert name.length() > 0 : "name cannot be empty"; int dims = 0; + int startIndex = 0; + while (name.charAt(startIndex) == '[') { + startIndex++; + dims++; + } + // Decode name if necessary. if (name.charAt(name.length() - 1) == ';') { - int startIndex = 0; - while (name.charAt(startIndex) == '[') { - startIndex++; - dims++; - } assert name.charAt(startIndex) == 'L'; this.simpleName = name.substring(startIndex + 1, name.length() - 1); this.name = name; @@ -116,4 +114,9 @@ public CiKind getRepresentationKind(RiType.Representation r) { return CiKind.Object; } + + @Override + public RiResolvedType resolve(RiResolvedType accessingClass) { + return (RiResolvedType) compiler.lookupType(name, (HotSpotTypeResolved) accessingClass, true); + } }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Wed Feb 08 21:15:00 2012 -0800 @@ -1173,7 +1173,7 @@ private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) { @Override protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); + asm.restart(CiKind.Void); XirParameter objHub = asm.createInputParameter("objectHub", CiKind.Object); XirOperand hub = asm.createConstantInputParameter("hub", CiKind.Object); XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); @@ -1188,7 +1188,7 @@ // if we get an exact match: continue. asm.jneq(falseSucc, objHub, checkHub); - return asm.finishTemplate(objHub, "typeCheck"); + return asm.finishTemplate("typeCheck"); } };
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java Wed Feb 08 21:15:00 2012 -0800 @@ -28,10 +28,10 @@ import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.target.amd64.*; -import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.amd64.*; +import com.oracle.max.graal.lir.asm.*; /** * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance. @@ -72,6 +72,6 @@ } else if (mode == OperandMode.Temp) { return EnumSet.of(OperandFlag.Register); } - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/FrameStateBuilder.java Wed Feb 08 21:15:00 2012 -0800 @@ -47,7 +47,7 @@ private final RiResolvedMethod method; - public FrameStateBuilder(RiResolvedMethod method, int maxLocals, int maxStackSize, StructuredGraph graph) { + public FrameStateBuilder(RiResolvedMethod method, int maxLocals, int maxStackSize, StructuredGraph graph, boolean eagerResolve) { assert graph != null; this.method = method; this.graph = graph; @@ -67,9 +67,12 @@ } RiSignature sig = method.signature(); int max = sig.argumentCount(false); - RiType accessingClass = method.holder(); + RiResolvedType accessingClass = method.holder(); for (int i = 0; i < max; i++) { RiType type = sig.argumentTypeAt(i, accessingClass); + if (eagerResolve) { + type = type.resolve(accessingClass); + } CiKind kind = type.kind(false).stackKind(); Stamp stamp; if (kind == CiKind.Object && type instanceof RiResolvedType) {
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Wed Feb 08 21:15:00 2012 -0800 @@ -128,7 +128,7 @@ methodSynchronizedObject = null; exceptionHandlers = null; this.currentGraph = graph; - this.frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph); + this.frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph, config.eagerResolving()); build(); } @@ -500,7 +500,7 @@ break; } default: - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Arithmetic.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; + +public enum AMD64Arithmetic { + IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, + LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, + FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR, + DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR, + INEG, LNEG, + I2L, L2I, I2B, I2C, I2S, + F2D, D2F, + I2F, I2D, F2I, D2I, + L2F, L2D, F2L, D2L, + MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + + + public static class Op1Reg extends AMD64LIRInstruction { + public Op1Reg(AMD64Arithmetic opcode, CiValue result, CiValue x) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + + emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); + } + + @Override + protected EnumSet<OperandFlag> 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, CiValue result, CiValue x) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result); + } + + @Override + public EnumSet<OperandFlag> 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(); + } + } + + public static class Op2Stack extends AMD64LIRInstruction { + public Op2Stack(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + } + + @Override + protected EnumSet<OperandFlag> 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() { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + super.verify(); + assert differentRegisters(result, y) || sameRegister(x, y); + verifyKind((AMD64Arithmetic) code, result, x, y); + } + } + + public static class Op2Reg extends AMD64LIRInstruction { + public Op2Reg(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + + @Override + public void verify() { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + super.verify(); + assert differentRegisters(result, y) || sameRegister(x, y); + verifyKind((AMD64Arithmetic) code, result, x, y); + } + } + + public static class Op2RegCommutative extends AMD64LIRInstruction { + public Op2RegCommutative(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = input(1); + + if (sameRegister(result, y)) { + emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); + } else { + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + } + } + + @Override + public EnumSet<OperandFlag> 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() { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = input(1); + + super.verify(); + verifyKind((AMD64Arithmetic) code, result, x, y); + } + } + + public static class ShiftOp extends AMD64LIRInstruction { + public ShiftOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + } + + @Override + public EnumSet<OperandFlag> 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(); + } + + @Override + public void verify() { + CiValue result = output(0); + CiValue x = input(0); + CiValue 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); + assert y.kind.stackKind() == CiKind.Int; + } + } + + public static class DivOp extends AMD64LIRInstruction { + public DivOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y, LIRDebugInfo info) { + super(opcode, new CiValue[] {result}, info, new CiValue[] {x}, new CiValue[] {y}, new CiValue[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)}); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue y = alive(0); + + emit(tasm, masm, (AMD64Arithmetic) code, result, y, info); + } + + @Override + public EnumSet<OperandFlag> 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(); + } + + @Override + protected void verify() { + CiValue result = output(0); + CiValue x = input(0); + CiValue 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); + } + } + + + @SuppressWarnings("unused") + protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue result) { + switch (opcode) { + case INEG: masm.negl(asIntReg(result)); break; + case LNEG: masm.negq(asLongReg(result)); break; + case L2I: masm.andl(asIntReg(result), 0xFFFFFFFF); break; + case I2B: masm.signExtendByte(asIntReg(result)); break; + case I2C: masm.andl(asIntReg(result), 0xFFFF); break; + case I2S: masm.signExtendShort(asIntReg(result)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue dst, CiValue src, LIRDebugInfo info) { + int exceptionOffset = -1; + if (isRegister(src)) { + switch (opcode) { + case IADD: masm.addl(asIntReg(dst), asIntReg(src)); break; + case ISUB: masm.subl(asIntReg(dst), asIntReg(src)); break; + case IAND: masm.andl(asIntReg(dst), asIntReg(src)); break; + case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break; + case IOR: masm.orl(asIntReg(dst), asIntReg(src)); break; + case IXOR: masm.xorl(asIntReg(dst), asIntReg(src)); break; + case ISHL: masm.shll(asIntReg(dst)); break; + case ISHR: masm.sarl(asIntReg(dst)); break; + case IUSHR:masm.shrl(asIntReg(dst)); break; + + case LADD: masm.addq(asLongReg(dst), asLongReg(src)); break; + case LSUB: masm.subq(asLongReg(dst), asLongReg(src)); break; + case LMUL: masm.imulq(asLongReg(dst), asLongReg(src)); break; + case LAND: masm.andq(asLongReg(dst), asLongReg(src)); break; + case LOR: masm.orq(asLongReg(dst), asLongReg(src)); break; + case LXOR: masm.xorq(asLongReg(dst), asLongReg(src)); break; + case LSHL: masm.shlq(asLongReg(dst)); break; + case LSHR: masm.sarq(asLongReg(dst)); break; + case LUSHR:masm.shrq(asLongReg(dst)); break; + + case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break; + case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), asFloatReg(src)); break; + case FDIV: masm.divss(asFloatReg(dst), asFloatReg(src)); break; + case FAND: masm.andps(asFloatReg(dst), asFloatReg(src)); break; + case FOR: masm.orps(asFloatReg(dst), asFloatReg(src)); break; + case FXOR: masm.xorps(asFloatReg(dst), asFloatReg(src)); break; + + case DADD: masm.addsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DAND: masm.andpd(asDoubleReg(dst), asDoubleReg(src)); break; + case DOR: masm.orpd(asDoubleReg(dst), asDoubleReg(src)); break; + case DXOR: masm.xorpd(asDoubleReg(dst), asDoubleReg(src)); break; + + case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break; + case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break; + case D2F: masm.cvtsd2ss(asFloatReg(dst), asDoubleReg(src)); break; + case I2F: masm.cvtsi2ssl(asFloatReg(dst), asIntReg(src)); break; + case I2D: masm.cvtsi2sdl(asDoubleReg(dst), asIntReg(src)); break; + case L2F: masm.cvtsi2ssq(asFloatReg(dst), asLongReg(src)); break; + case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break; + case F2I: + masm.cvttss2sil(asIntReg(dst), asFloatReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case D2I: + masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case F2L: + masm.cvttss2siq(asLongReg(dst), asFloatReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case D2L: + masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break; + case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break; + case MOV_F2I: masm.movdl(asIntReg(dst), asFloatReg(src)); break; + case MOV_D2L: masm.movdq(asLongReg(dst), asDoubleReg(src)); break; + + case IDIV: + case IREM: + masm.cdql(); + exceptionOffset = masm.codeBuffer.position(); + masm.idivl(asRegister(src)); + break; + + case LDIV: + case LREM: + Label continuation = new Label(); + if (opcode == LDIV) { + // check for special case of Long.MIN_VALUE / -1 + Label normalCase = new Label(); + masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE); + masm.cmpq(AMD64.rax, AMD64.rdx); + masm.jcc(ConditionFlag.notEqual, normalCase); + masm.cmpl(asRegister(src), -1); + masm.jcc(ConditionFlag.equal, continuation); + masm.bind(normalCase); + } + + masm.cdqq(); + exceptionOffset = masm.codeBuffer.position(); + masm.idivq(asRegister(src)); + masm.bind(continuation); + break; + + case IUDIV: + case IUREM: + // Must zero the high 64-bit word (in RDX) of the dividend + masm.xorq(AMD64.rdx, AMD64.rdx); + exceptionOffset = masm.codeBuffer.position(); + masm.divl(asRegister(src)); + break; + + case LUDIV: + case LUREM: + // Must zero the high 64-bit word (in RDX) of the dividend + masm.xorq(AMD64.rdx, AMD64.rdx); + exceptionOffset = masm.codeBuffer.position(); + masm.divq(asRegister(src)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(src)) { + switch (opcode) { + case IADD: masm.incrementl(asIntReg(dst), tasm.asIntConst(src)); break; + case ISUB: masm.decrementl(asIntReg(dst), tasm.asIntConst(src)); break; + case IMUL: masm.imull(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break; + case IAND: masm.andl(asIntReg(dst), tasm.asIntConst(src)); break; + case IOR: masm.orl(asIntReg(dst), tasm.asIntConst(src)); break; + case IXOR: masm.xorl(asIntReg(dst), tasm.asIntConst(src)); break; + case ISHL: masm.shll(asIntReg(dst), tasm.asIntConst(src) & 31); break; + case ISHR: masm.sarl(asIntReg(dst), tasm.asIntConst(src) & 31); break; + case IUSHR:masm.shrl(asIntReg(dst), tasm.asIntConst(src) & 31); break; + + case LADD: masm.addq(asLongReg(dst), tasm.asIntConst(src)); break; + case LSUB: masm.subq(asLongReg(dst), tasm.asIntConst(src)); break; + case LMUL: masm.imulq(asLongReg(dst), asLongReg(dst), tasm.asIntConst(src)); break; + case LAND: masm.andq(asLongReg(dst), tasm.asIntConst(src)); break; + case LOR: masm.orq(asLongReg(dst), tasm.asIntConst(src)); break; + case LXOR: masm.xorq(asLongReg(dst), tasm.asIntConst(src)); break; + case LSHL: masm.shlq(asLongReg(dst), tasm.asIntConst(src) & 63); break; + case LSHR: masm.sarq(asLongReg(dst), tasm.asIntConst(src) & 63); break; + case LUSHR:masm.shrq(asLongReg(dst), tasm.asIntConst(src) & 63); break; + + case FADD: masm.addss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + case FAND: masm.andps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; + case FOR: masm.orps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; + case FXOR: masm.xorps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; + case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + + case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DAND: masm.andpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; + case DOR: masm.orpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; + case DXOR: masm.xorpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else { + switch (opcode) { + case IADD: masm.addl(asIntReg(dst), tasm.asIntAddr(src)); break; + case ISUB: masm.subl(asIntReg(dst), tasm.asIntAddr(src)); break; + case IAND: masm.andl(asIntReg(dst), tasm.asIntAddr(src)); break; + case IOR: masm.orl(asIntReg(dst), tasm.asIntAddr(src)); break; + case IXOR: masm.xorl(asIntReg(dst), tasm.asIntAddr(src)); break; + + case LADD: masm.addq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LSUB: masm.subq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LAND: masm.andq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LOR: masm.orq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LXOR: masm.xorq(asLongReg(dst), tasm.asLongAddr(src)); break; + + case FADD: masm.addss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + + case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + if (info != null) { + assert exceptionOffset != -1; + tasm.recordImplicitException(exceptionOffset, info); + } + } + + private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) { + ConvertSlowPath slowPath = new ConvertSlowPath(result, x); + tasm.slowPaths.add(slowPath); + switch (result.kind) { + case Int: masm.cmpl(asIntReg(result), Integer.MIN_VALUE); break; + case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(CiConstant.forLong(java.lang.Long.MIN_VALUE))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + masm.jcc(ConditionFlag.equal, slowPath.start); + masm.bind(slowPath.continuation); + } + + private static class ConvertSlowPath extends AMD64SlowPath { + public final Label start = new Label(); + public final Label continuation = new Label(); + private final CiValue result; + private final CiValue x; + + public ConvertSlowPath(CiValue result, CiValue x) { + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.bind(start); + switch (x.kind) { + case Float: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(CiConstant.FLOAT_0)); break; + case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(CiConstant.DOUBLE_0)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + Label nan = new Label(); + masm.jcc(ConditionFlag.parity, nan); + masm.jcc(ConditionFlag.below, continuation); + + // input is > 0 -> return maxInt + // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff + switch (result.kind) { + case Int: masm.decrementl(asIntReg(result), 1); break; + case Long: masm.decrementq(asLongReg(result), 1); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + masm.jmp(continuation); + + // input is NaN -> return 0 + masm.bind(nan); + masm.xorptr(asRegister(result), asRegister(result)); + masm.jmp(continuation); + } + } + + + private static void verifyKind(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + assert (opcode.name().startsWith("I") && result.kind == CiKind.Int && x.kind.stackKind() == CiKind.Int && y.kind.stackKind() == CiKind.Int) + || (opcode.name().startsWith("L") && result.kind == CiKind.Long && x.kind == CiKind.Long && y.kind == CiKind.Long) + || (opcode.name().startsWith("F") && result.kind == CiKind.Float && x.kind == CiKind.Float && y.kind == CiKind.Float) + || (opcode.name().startsWith("D") && result.kind == CiKind.Double && x.kind == CiKind.Double && y.kind == CiKind.Double); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Call.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiTargetMethod.Mark; +import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; + +public class AMD64Call { + + public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + private final Object targetMethod; + private final Map<XirMark, Mark> marks; + + public DirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, LIRDebugInfo info, Map<XirMark, Mark> marks) { + super("CALL_DIRECT", new CiValue[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.targetMethod = targetMethod; + this.marks = marks; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + callAlignment(tasm, masm); + if (marks != null) { + marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); + } + directCall(tasm, masm, targetMethod, info); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + private final Object targetMethod; + private final Map<XirMark, Mark> marks; + + private static CiValue[] concat(CiValue[] parameters, CiValue targetAddress) { + CiValue[] result = Arrays.copyOf(parameters, parameters.length + 1); + result[result.length - 1] = targetAddress; + return result; + } + + public IndirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, CiValue targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) { + super("CALL_INDIRECT", new CiValue[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.targetMethod = targetMethod; + this.marks = marks; + } + + private CiValue 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<OperandFlag> 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(); + } + } + + + public static void callAlignment(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + // make sure that the displacement word of the call ends up word aligned + int offset = masm.codeBuffer.position(); + offset += tasm.target.arch.machineCodeCallDisplacementOffset; + while (offset++ % tasm.target.wordSize != 0) { + masm.nop(); + } + } + + public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) { + int before = masm.codeBuffer.position(); + if (target instanceof CiRuntimeCall) { + long maxOffset = tasm.runtime.getMaxCallTargetOffset((CiRuntimeCall) target); + if (maxOffset != (int) maxOffset) { + // offset might not fit a 32-bit immediate, generate an + // indirect call with a 64-bit immediate + CiRegister scratch = tasm.frameMap.registerConfig.getScratchRegister(); + // TODO(cwi): we want to get rid of a generally reserved scratch register. + masm.movq(scratch, 0L); + masm.call(scratch); + } else { + masm.call(); + } + } else { + masm.call(); + } + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), info); + tasm.recordExceptionHandlers(after, info); + masm.ensureUniquePC(); + } + + public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) { + int before = masm.codeBuffer.position(); + masm.jmp(0, true); + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), null); + masm.ensureUniquePC(); + } + + public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiRegister dst, Object target, LIRDebugInfo info) { + int before = masm.codeBuffer.position(); + masm.call(dst); + int after = masm.codeBuffer.position(); + tasm.recordIndirectCall(before, after, tasm.runtime.asCallTarget(target), info); + tasm.recordExceptionHandlers(after, info); + masm.ensureUniquePC(); + } + + public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + boolean assertions = false; + assert (assertions = true) == true; + + if (assertions) { + directCall(tasm, masm, CiRuntimeCall.Debug, null); + masm.hlt(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Compare.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; + +public enum AMD64Compare { + ICMP, LCMP, ACMP, FCMP, DCMP; + + public static class CompareOp extends AMD64LIRInstruction { + public CompareOp(AMD64Compare opcode, CiValue x, CiValue y) { + super(opcode, LIRInstruction.NO_OPERANDS, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue x = input(0); + CiValue y = input(1); + emit(tasm, masm, (AMD64Compare) code, x, y); + } + + @Override + public EnumSet<OperandFlag> 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(); + } + + @Override + protected void verify() { + CiValue x = input(0); + CiValue y = input(1); + + super.verify(); + assert (name().startsWith("I") && x.kind == CiKind.Int && y.kind.stackKind() == CiKind.Int) + || (name().startsWith("I") && x.kind == CiKind.Jsr && y.kind == CiKind.Jsr) + || (name().startsWith("L") && x.kind == CiKind.Long && y.kind == CiKind.Long) + || (name().startsWith("A") && x.kind == CiKind.Object && y.kind == CiKind.Object) + || (name().startsWith("F") && x.kind == CiKind.Float && y.kind == CiKind.Float) + || (name().startsWith("D") && x.kind == CiKind.Double && y.kind == CiKind.Double); + } + } + + public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Compare opcode, CiValue x, CiValue y) { + if (isRegister(y)) { + switch (opcode) { + case ICMP: masm.cmpl(asIntReg(x), asIntReg(y)); break; + case LCMP: masm.cmpq(asLongReg(x), asLongReg(y)); break; + case ACMP: masm.cmpptr(asObjectReg(x), asObjectReg(y)); break; + case FCMP: masm.ucomiss(asFloatReg(x), asFloatReg(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), asDoubleReg(y)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(y)) { + switch (opcode) { + case ICMP: masm.cmpl(asIntReg(x), tasm.asIntConst(y)); break; + case LCMP: masm.cmpq(asLongReg(x), tasm.asIntConst(y)); break; + case ACMP: + if (((CiConstant) y).isNull()) { + masm.cmpq(asObjectReg(x), 0); break; + } else { + throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons"); + } + case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(y)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else { + switch (opcode) { + case ICMP: masm.cmpl(asIntReg(x), tasm.asIntAddr(y)); break; + case LCMP: masm.cmpq(asLongReg(x), tasm.asLongAddr(y)); break; + case ACMP: masm.cmpptr(asObjectReg(x), tasm.asObjectAddr(y)); break; + case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatAddr(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleAddr(y)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64CompareToIntOpcode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; + +/** + * Implementation of the Java bytecodes that compare a long, float, or double value and produce the + * integer constants -1, 0, 1 on less, equal, or greater, respectively. For floating point compares, + * unordered can be either greater {@link #CMP2INT_UG} or less {@link #CMP2INT_UL}. + */ +public enum AMD64CompareToIntOpcode { + CMP2INT, CMP2INT_UG, CMP2INT_UL; + + public LIRInstruction create(CiValue result) { + CiValue[] outputs = new CiValue[] {result}; + + return new AMD64LIRInstruction(this, outputs, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + emit(masm, output(0)); + } + + @Override + protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw GraalInternalError.shouldNotReachHere(); + } + }; + } + + private void emit(AMD64MacroAssembler masm, CiValue result) { + CiRegister dest = asIntReg(result); + Label high = new Label(); + Label low = new Label(); + Label done = new Label(); + + // comparison is done by a separate LIR instruction before + switch (this) { + case CMP2INT: + masm.jcc(ConditionFlag.greater, high); + masm.jcc(ConditionFlag.less, low); + break; + case CMP2INT_UG: + masm.jcc(ConditionFlag.parity, high); + masm.jcc(ConditionFlag.above, high); + masm.jcc(ConditionFlag.below, low); + break; + case CMP2INT_UL: + masm.jcc(ConditionFlag.parity, low); + masm.jcc(ConditionFlag.above, high); + masm.jcc(ConditionFlag.below, low); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + // equal -> 0 + masm.xorptr(dest, dest); + masm.jmp(done); + + // greater -> 1 + masm.bind(high); + masm.xorptr(dest, dest); + masm.incrementl(dest, 1); + masm.jmp(done); + + // less -> -1 + masm.bind(low); + masm.xorptr(dest, dest); + masm.decrementl(dest, 1); + + masm.bind(done); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64ControlFlow.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiAddress.Scale; +import com.oracle.max.cri.ci.CiTargetMethod.JumpTable; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; +import com.oracle.max.graal.nodes.calc.*; + +public class AMD64ControlFlow { + + public static class ReturnOp extends AMD64LIRInstruction { + public ReturnOp(CiValue input) { + super("RETURN", LIRInstruction.NO_OPERANDS, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.ret(0); + } + + @Override + protected EnumSet<OperandFlag> 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 Condition condition; + protected LabelRef destination; + + public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) { + super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.condition = condition; + this.destination = destination; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.jcc(intCond(condition), destination.label()); + } + + @Override + public LabelRef destination() { + return destination; + } + + @Override + public void negate(LabelRef newDestination) { + destination = newDestination; + condition = condition.negate(); + } + + @Override + public String operationString() { + return condition.operator + " [" + destination + "]"; + } + + @Override + protected EnumSet<OperandFlag> 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) { + super(condition, destination, info); + this.unorderedIsTrue = unorderedIsTrue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + floatJcc(masm, condition, unorderedIsTrue, destination.label()); + } + + @Override + public void negate(LabelRef newDestination) { + super.negate(newDestination); + unorderedIsTrue = !unorderedIsTrue; + } + + @Override + public String operationString() { + return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse"); + } + } + + + public static class TableSwitchOp extends AMD64LIRInstruction { + private final int lowKey; + private final LabelRef defaultTarget; + private final LabelRef[] targets; + + 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 CiValue[] {index}, new CiValue[] {scratch}); + this.lowKey = lowKey; + this.defaultTarget = defaultTarget; + this.targets = targets; + } + + @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<OperandFlag> 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(); + } + } + + + public static class CondMoveOp extends AMD64LIRInstruction { + private final Condition condition; + + public CondMoveOp(Variable result, Condition condition, Variable trueValue, CiValue falseValue) { + super("CMOVE", new CiValue[] {result}, null, new CiValue[] {falseValue}, new CiValue[] {trueValue}, LIRInstruction.NO_OPERANDS); + this.condition = condition; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0)); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static class FloatCondMoveOp extends AMD64LIRInstruction { + private final Condition condition; + private final boolean unorderedIsTrue; + + public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + super("FLOAT_CMOVE", new CiValue[] {result}, null, LIRInstruction.NO_OPERANDS, new CiValue[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS); + this.condition = condition; + this.unorderedIsTrue = unorderedIsTrue; + } + + @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<OperandFlag> 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(); + } + } + + + private static void tableswitch(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, CiRegister value, CiRegister scratch) { + Buffer buf = masm.codeBuffer; + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + if (lowKey != 0) { + // subtract the low value from the switch value + masm.subl(value, lowKey); + masm.cmpl(value, highKey - lowKey); + } else { + masm.cmpl(value, highKey); + } + + // Jump to default target if index is not within the jump table + masm.jcc(ConditionFlag.above, defaultTarget.label()); + + // Set scratch to address of jump table + int leaPos = buf.position(); + masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), 0)); + int afterLea = buf.position(); + + // Load jump table entry into scratch and jump to it + masm.movslq(value, new CiAddress(CiKind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); + masm.addq(scratch, value); + masm.jmp(scratch); + + // Inserting padding so that jump table address is 4-byte aligned + if ((buf.position() & 0x3) != 0) { + masm.nop(4 - (buf.position() & 0x3)); + } + + // Patch LEA instruction above now that we know the position of the jump table + int jumpTablePos = buf.position(); + buf.setPosition(leaPos); + masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); + buf.setPosition(jumpTablePos); + + // Emit jump table entries + for (LabelRef target : targets) { + Label label = target.label(); + int offsetToJumpTableBase = buf.position() - jumpTablePos; + if (label.isBound()) { + int imm32 = label.position() - jumpTablePos; + buf.emitInt(imm32); + } else { + label.addPatchAt(buf.position()); + + buf.emitByte(0); // psuedo-opcode for jump table entry + buf.emitShort(offsetToJumpTableBase); + buf.emitByte(0); // padding to make jump table entry 4 bytes wide + } + } + + JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); + tasm.targetMethod.addAnnotation(jt); + } + + private static void floatJcc(AMD64MacroAssembler masm, Condition condition, boolean unorderedIsTrue, Label label) { + ConditionFlag cond = floatCond(condition); + Label endLabel = new Label(); + if (unorderedIsTrue && !trueOnUnordered(cond)) { + masm.jcc(ConditionFlag.parity, label); + } else if (!unorderedIsTrue && trueOnUnordered(cond)) { + masm.jcc(ConditionFlag.parity, endLabel); + } + masm.jcc(cond, label); + masm.bind(endLabel); + } + + private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, boolean isFloat, Condition condition, boolean unorderedIsTrue, CiValue trueValue, CiValue falseValue) { + ConditionFlag cond = isFloat ? floatCond(condition) : intCond(condition); + // check that we don't overwrite an input operand before it is used. + assert !result.equals(trueValue); + + AMD64Move.move(tasm, masm, result, falseValue); + cmove(tasm, masm, result, cond, trueValue); + + if (isFloat) { + if (unorderedIsTrue && !trueOnUnordered(cond)) { + cmove(tasm, masm, result, ConditionFlag.parity, trueValue); + } else if (!unorderedIsTrue && trueOnUnordered(cond)) { + cmove(tasm, masm, result, ConditionFlag.parity, falseValue); + } + } + } + + private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, ConditionFlag cond, CiValue other) { + if (isRegister(other)) { + assert asRegister(other) != asRegister(result) : "other already overwritten by previous move"; + switch (other.kind) { + case Int: masm.cmovl(cond, asRegister(result), asRegister(other)); break; + case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else { + switch (other.kind) { + case Int: masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break; + case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + } + + private static ConditionFlag intCond(Condition cond) { + switch (cond) { + case EQ: return ConditionFlag.equal; + case NE: return ConditionFlag.notEqual; + case LT: return ConditionFlag.less; + case LE: return ConditionFlag.lessEqual; + case GE: return ConditionFlag.greaterEqual; + case GT: return ConditionFlag.greater; + case BE: return ConditionFlag.belowEqual; + case AE: return ConditionFlag.aboveEqual; + case AT: return ConditionFlag.above; + case BT: return ConditionFlag.below; + case OF: return ConditionFlag.overflow; + case NOF: return ConditionFlag.noOverflow; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + private static ConditionFlag floatCond(Condition cond) { + switch (cond) { + case EQ: return ConditionFlag.equal; + case NE: return ConditionFlag.notEqual; + case BT: return ConditionFlag.below; + case BE: return ConditionFlag.belowEqual; + case AE: return ConditionFlag.aboveEqual; + case AT: return ConditionFlag.above; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + private static boolean trueOnUnordered(ConditionFlag condition) { + switch(condition) { + case aboveEqual: + case notEqual: + case above: + case less: + case overflow: + return false; + case equal: + case belowEqual: + case below: + case greaterEqual: + case noOverflow: + return true; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64LIRInstruction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.amd64; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; + +/** + * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method. + */ +public abstract class AMD64LIRInstruction extends LIRInstruction { + + public AMD64LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + super(opcode, outputs, info, inputs, alives, temps); + } + + @Override + public final void emitCode(TargetMethodAssembler tasm) { + emitCode(tasm, (AMD64MacroAssembler) tasm.asm); + } + + public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64Move.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +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.max.cri.ci.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.StandardOp.*; +import com.oracle.max.graal.lir.asm.*; + +public class AMD64Move { + + public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp { + public SpillMoveOp(CiValue result, CiValue input) { + super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public CiValue getInput() { + return input(0); + } + @Override + public CiValue getResult() { + return output(0); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp { + public MoveToRegOp(CiValue result, CiValue input) { + super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public CiValue getInput() { + return input(0); + } + @Override + public CiValue getResult() { + return output(0); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp { + public MoveFromRegOp(CiValue result, CiValue input) { + super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public CiValue getInput() { + return input(0); + } + @Override + public CiValue getResult() { + return output(0); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static class LoadOp extends AMD64LIRInstruction { + public LoadOp(CiValue result, CiValue address, LIRDebugInfo info) { + super("LOAD", new CiValue[] {result}, info, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + load(tasm, masm, output(0), (CiAddress) input(0), info); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static class StoreOp extends AMD64LIRInstruction { + public StoreOp(CiValue address, CiValue input, LIRDebugInfo info) { + super("STORE", LIRInstruction.NO_OPERANDS, info, new CiValue[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + store(tasm, masm, (CiAddress) input(0), input(1), info); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static class LeaOp extends AMD64LIRInstruction { + public LeaOp(CiValue result, CiValue address) { + super("LEA", new CiValue[] {result}, null, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0))); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static class MembarOp extends AMD64LIRInstruction { + 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; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.membar(barriers); + } + + @Override + protected EnumSet<OperandFlag> 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 CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + masm.nullCheck(asRegister(input(0))); + } + + @Override + protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw GraalInternalError.shouldNotReachHere(); + } + } + + + public static class CompareAndSwapOp extends AMD64LIRInstruction { + public CompareAndSwapOp(CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { + super("CAS", new CiValue[] {result}, null, new CiValue[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2)); + } + + @Override + protected EnumSet<OperandFlag> 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(); + } + } + + + public static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { + if (isRegister(input)) { + if (isRegister(result)) { + reg2reg(masm, result, input); + } else if (isStackSlot(result)) { + reg2stack(tasm, masm, result, input); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else if (isStackSlot(input)) { + if (isRegister(result)) { + stack2reg(tasm, masm, result, input); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(input)) { + if (isRegister(result)) { + const2reg(tasm, masm, result, (CiConstant) input); + } else if (isStackSlot(result)) { + const2stack(tasm, masm, result, (CiConstant) input); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void reg2reg(AMD64MacroAssembler masm, CiValue result, CiValue input) { + if (input.equals(result)) { + return; + } + switch (result.kind) { + case Jsr: + case Int: masm.movl(asRegister(result), asRegister(input)); break; + case Long: masm.movq(asRegister(result), asRegister(input)); break; + case Float: masm.movflt(asFloatReg(result), asFloatReg(input)); break; + case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break; + case Object: masm.movq(asRegister(result), asRegister(input)); break; + default: throw GraalInternalError.shouldNotReachHere("kind=" + result.kind); + } + } + + private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { + switch (result.kind) { + case Jsr: + case Int: masm.movl(tasm.asAddress(result), asRegister(input)); break; + case Long: masm.movq(tasm.asAddress(result), asRegister(input)); break; + case Float: masm.movflt(tasm.asAddress(result), asFloatReg(input)); break; + case Double: masm.movsd(tasm.asAddress(result), asDoubleReg(input)); break; + case Object: masm.movq(tasm.asAddress(result), asRegister(input)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { + switch (result.kind) { + case Jsr: + case Int: masm.movl(asRegister(result), tasm.asAddress(input)); break; + case Long: masm.movq(asRegister(result), tasm.asAddress(input)); break; + case Float: masm.movflt(asFloatReg(result), tasm.asAddress(input)); break; + case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break; + case Object: masm.movq(asRegister(result), tasm.asAddress(input)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { + switch (result.kind) { + case Jsr: + case Int: + // Do not optimize with an XOR as this instruction may be between + // a CMP and a Jcc in which case the XOR will modify the condition + // flags and interfere with the Jcc. + masm.movl(asRegister(result), tasm.asIntConst(c)); + break; + case Long: + // Do not optimize with an XOR as this instruction may be between + // a CMP and a Jcc in which case the XOR will modify the condition + // flags and interfere with the Jcc. + masm.movq(asRegister(result), c.asLong()); + break; + case Float: + // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f + if (Float.floatToRawIntBits(c.asFloat()) == Float.floatToRawIntBits(0.0f)) { + masm.xorps(asFloatReg(result), asFloatReg(result)); + } else { + masm.movflt(asFloatReg(result), tasm.asFloatConstRef(c)); + } + break; + case Double: + // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d + if (Double.doubleToRawLongBits(c.asDouble()) == Double.doubleToRawLongBits(0.0d)) { + masm.xorpd(asDoubleReg(result), asDoubleReg(result)); + } else { + masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(c)); + } + break; + case Object: + // Do not optimize with an XOR as this instruction may be between + // a CMP and a Jcc in which case the XOR will modify the condition + // flags and interfere with the Jcc. + if (c.isNull()) { + masm.movq(asRegister(result), 0x0L); + } else if (tasm.target.inlineObjects) { + tasm.recordDataReferenceInCode(c, 0); + masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); + } else { + masm.movq(asRegister(result), tasm.recordDataReferenceInCode(c, 0)); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { + switch (result.kind) { + case Jsr: + case Int: masm.movl(tasm.asAddress(result), c.asInt()); break; + case Long: masm.movlong(tasm.asAddress(result), c.asLong()); break; + case Float: masm.movl(tasm.asAddress(result), floatToRawIntBits(c.asFloat())); break; + case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(c.asDouble())); break; + case Object: + if (c.isNull()) { + masm.movlong(tasm.asAddress(result), 0L); + } else { + throw GraalInternalError.shouldNotReachHere("Non-null object constants must be in register"); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + + public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress loadAddr, LIRDebugInfo info) { + if (info != null) { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + } + switch (loadAddr.kind) { + case Boolean: + case Byte: masm.movsxb(asRegister(result), loadAddr); break; + case Char: masm.movzxl(asRegister(result), loadAddr); break; + case Short: masm.movswl(asRegister(result), loadAddr); break; + case Int: masm.movslq(asRegister(result), loadAddr); break; + case Long: masm.movq(asRegister(result), loadAddr); break; + case Float: masm.movflt(asFloatReg(result), loadAddr); break; + case Double: masm.movdbl(asDoubleReg(result), loadAddr); break; + case Object: masm.movq(asRegister(result), loadAddr); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiAddress storeAddr, CiValue input, LIRDebugInfo info) { + if (info != null) { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + } + + if (isRegister(input)) { + switch (storeAddr.kind) { + case Boolean: + case Byte: masm.movb(storeAddr, asRegister(input)); break; + case Char: + case Short: masm.movw(storeAddr, asRegister(input)); break; + case Int: masm.movl(storeAddr, asRegister(input)); break; + case Long: masm.movq(storeAddr, asRegister(input)); break; + case Float: masm.movflt(storeAddr, asFloatReg(input)); break; + case Double: masm.movsd(storeAddr, asDoubleReg(input)); break; + case Object: masm.movq(storeAddr, asRegister(input)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(input)) { + CiConstant c = (CiConstant) input; + switch (storeAddr.kind) { + case Boolean: + case Byte: masm.movb(storeAddr, c.asInt() & 0xFF); break; + case Char: + case Short: masm.movw(storeAddr, c.asInt() & 0xFFFF); break; + case Jsr: + case Int: masm.movl(storeAddr, c.asInt()); break; + case Long: + if (NumUtil.isInt(c.asLong())) { + masm.movslq(storeAddr, (int) c.asLong()); + } else { + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + break; + case Float: masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break; + case Double: throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + case Object: + if (c.isNull()) { + masm.movptr(storeAddr, 0); + } else { + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + + protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { + assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; + + if (tasm.target.isMP) { + masm.lock(); + } + switch (cmpValue.kind) { + case Int: masm.cmpxchgl(asRegister(newValue), address); break; + case Long: + case Object: masm.cmpxchgq(asRegister(newValue), address); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir.amd64/src/com/oracle/max/graal/lir/amd64/AMD64SlowPath.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.lir.amd64; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.asm.*; + +/** + * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method. + */ +public abstract class AMD64SlowPath implements LIR.SlowPath { + @Override + public final void emitCode(TargetMethodAssembler tasm) { + emitCode(tasm, (AMD64MacroAssembler) tasm.asm); + } + + public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/FrameMap.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,344 @@ +/* + * 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.max.graal.lir; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiCallingConvention.Type; +import com.oracle.max.cri.ri.*; + +/** + * This class is used to build the stack frame layout for a compiled method. + * A {@link CiStackSlot} is used to index slots of the frame relative to the stack pointer. + * The frame size is only fixed after register allocation when all spill slots have + * been allocated. Both the outgoing argument area and the spill are can grow until then. + * Therefore, outgoing arguments are indexed from the stack pointer, while spill slots + * are indexed from the beginning of the frame (and the total frame size has to be added + * to get the actual offset from the stack pointer). + * <br> + * This is the format of a stack frame: + * <pre> + * Base Contents + * + * : : ----- + * caller | incoming overflow argument n | ^ + * frame : ... : | positive + * | incoming overflow argument 0 | | offsets + * ---------+--------------------------------+--------------------- + * | return address | | ^ + * current +--------------------------------+ | | ----- + * frame | | | | ^ + * : callee save area : | | | + * | | | | | + * +--------------------------------+ | | | + * | spill slot 0 | | negative | | + * : ... : v offsets | | + * | spill slot n | ----- total frame + * +--------------------------------+ frame size + * | alignment padding | size | + * +--------------------------------+ ----- | | + * | outgoing overflow argument n | ^ | | + * : ... : | positive | | + * | outgoing overflow argument 0 | | offsets v v + * %sp--> +--------------------------------+--------------------------- + * + * </pre> + * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size + * of such a block may be greater than the size of a normal spill slot or the word size. + * <br> + * A runtime has two ways to reserve space in the stack frame for its own use: <ul> + * <li>A memory block somewhere in the frame of size {@link RiRuntime#getCustomStackAreaSize()}. The offset + * to this block is returned in {@link CiTargetMethod#customStackAreaOffset()}. + * <li>At the beginning of the overflow argument area: The calling convention can specify that the first + * overflow stack argument is not at offset 0, but at a specified offset o. Use + * {@link RiRuntime#getMinimumOutgoingSize()} to make sure that call-free methods also have this space + * reserved. Then the VM can use memory the memory at offset 0 relative to the stack pointer. + * </ul> + */ +public final class FrameMap { + public final RiRuntime runtime; + public final CiTarget target; + public final RiRegisterConfig registerConfig; + + /** + * The final frame size, not including the size of the return address. + * The value is only set after register allocation is complete, i.e., after all spill slots have been allocated. + */ + private int frameSize; + + /** + * Size of the area occupied by spill slots and other stack-allocated memory blocks. + */ + private int spillSize; + + /** + * Size of the area occupied by outgoing overflow arguments. + * This value is adjusted as calling conventions for outgoing calls are retrieved. + */ + private int outgoingSize; + + /** + * The list of stack areas allocated in this frame that are present in every reference map. + */ + private final List<CiStackSlot> objectStackBlocks; + + /** + * The stack area reserved for use by the VM, or {@code null} if the VM does not request stack space. + */ + private final CiStackSlot customArea; + + /** + * Creates a new frame map for the specified method. + */ + public FrameMap(RiRuntime runtime, CiTarget target, RiRegisterConfig registerConfig) { + this.runtime = runtime; + this.target = target; + this.registerConfig = registerConfig; + this.frameSize = -1; + this.spillSize = returnAddressSize() + calleeSaveAreaSize(); + this.outgoingSize = runtime.getMinimumOutgoingSize(); + this.objectStackBlocks = new ArrayList<>(); + this.customArea = allocateStackBlock(runtime.getCustomStackAreaSize(), false); + } + + + private int returnAddressSize() { + return target.arch.returnAddressSize; + } + + private int calleeSaveAreaSize() { + CiCalleeSaveLayout csl = registerConfig.getCalleeSaveLayout(); + return csl != null ? csl.size : 0; + } + + /** + * Gets the frame size of the compiled frame, not including the size of the return address. + * @return The size of the frame (in bytes). + */ + public int frameSize() { + assert frameSize != -1 : "frame size not computed yet"; + return frameSize; + } + + /** + * Gets the total frame size of the compiled frame, including the size of the return address. + * @return The total size of the frame (in bytes). + */ + public int totalFrameSize() { + return frameSize() + returnAddressSize(); + } + + /** + * Sets the frame size for this frame. + * @param frameSize The frame size (in bytes). + */ + public void setFrameSize(int frameSize) { + assert this.frameSize == -1 : "must only be set once"; + this.frameSize = frameSize; + } + + /** + * Computes the frame size for this frame. After this method has been called, methods that change the + * frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can be requested. + */ + public void finish() { + setFrameSize(target.alignFrameSize(outgoingSize + spillSize - returnAddressSize())); + } + + /** + * Computes the offset of a stack slot relative to the frame register. + * This is also the bit index of stack slots in the reference map. + * + * @param slot a stack slot + * @return the offset of the stack slot + */ + public int offsetForStackSlot(CiStackSlot slot) { + assert (!slot.rawAddFrameSize() && slot.rawOffset() < outgoingSize) || + (slot.rawAddFrameSize() && slot.rawOffset() < 0 && -slot.rawOffset() <= spillSize) || + (slot.rawAddFrameSize() && slot.rawOffset() >= 0); + return slot.offset(totalFrameSize()); + } + + /** + * Gets the offset to the stack area where callee-saved registers are stored. + * @return The offset to the callee save area (in bytes). + */ + public int offsetToCalleeSaveArea() { + return frameSize() - calleeSaveAreaSize(); + } + + /** + * Gets the offset of the stack area stack block reserved for use by the VM, or -1 if the VM does not request stack space. + * @return The offset to the custom area (in bytes). + */ + public int offsetToCustomArea() { + return customArea == null ? -1 : offsetForStackSlot(customArea); + } + + /** + * Informs the frame map that the compiled code calls a particular method, which + * may need stack space for outgoing arguments. + * @param cc The calling convention for the called method. + * @param type The type of calling convention. + */ + public void callsMethod(CiCallingConvention cc, Type type) { + // TODO look at the actual stack offsets? + assert type.out; + reserveOutgoing(cc.stackSize); + } + + /** + * Reserves space for stack-based outgoing arguments. + * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments. + */ + public void reserveOutgoing(int argsSize) { + assert frameSize == -1 : "frame size must not yet be fixed"; + outgoingSize = Math.max(outgoingSize, argsSize); + } + + private CiStackSlot getSlot(CiKind kind, int additionalOffset) { + return CiStackSlot.get(kind, -spillSize + additionalOffset, true); + } + + /** + * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned on its natural alignment, + * i.e., an 8-byte spill slot is aligned at an 8-byte boundary. + * @param kind The kind of the spill slot to be reserved. + * @return A spill slot denoting the reserved memory area. + */ + public CiStackSlot allocateSpillSlot(CiKind kind) { + assert frameSize == -1 : "frame size must not yet be fixed"; + int size = target.sizeInBytes(kind); + spillSize = NumUtil.roundUp(spillSize + size, size); + return getSlot(kind, 0); + } + + /** + * Reserves a block of memory in the frame of the method being compiled. The returned block is aligned on a word boundary. + * If the requested size is 0, the method returns {@code null}. + * + * @param size The size to reserve (in bytes). + * @param refs Specifies if the block is all references. If true, the block will be in all reference maps for this method. + * The caller is responsible to initialize the memory block before the first instruction that uses a reference map. + * @return A stack slot describing the begin of the memory block. + */ + public CiStackSlot allocateStackBlock(int size, boolean refs) { + assert frameSize == -1 : "frame size must not yet be fixed"; + if (size == 0) { + return null; + } + spillSize = NumUtil.roundUp(spillSize + size, target.wordSize); + + if (refs) { + assert size % target.wordSize == 0; + CiStackSlot result = getSlot(CiKind.Object, 0); + objectStackBlocks.add(result); + for (int i = target.wordSize; i < size; i += target.wordSize) { + objectStackBlocks.add(getSlot(CiKind.Object, i)); + } + return result; + + } else { + return getSlot(target.wordKind, 0); + } + } + + + private int frameRefMapIndex(CiStackSlot slot) { + assert offsetForStackSlot(slot) % target.wordSize == 0; + return offsetForStackSlot(slot) / target.wordSize; + } + + /** + * Initializes a reference map that covers all registers of the target architecture. + */ + public CiBitMap initRegisterRefMap() { + return new CiBitMap(target.arch.registerReferenceMapBitCount); + } + + /** + * Initializes a reference map. Initially, the size is large enough to cover all the + * slots in the frame. If the method has incoming reference arguments on the stack, + * the reference map might grow later when such a reference is set. + */ + public CiBitMap initFrameRefMap() { + CiBitMap frameRefMap = new CiBitMap(frameSize() / target.wordSize); + for (CiStackSlot slot : objectStackBlocks) { + setReference(slot, null, frameRefMap); + } + return frameRefMap; + } + + /** + * Marks the specified location as a reference in the reference map of the debug information. + * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a + * {@link CiConstant} is automatically tracked. + * + * @param location The location to be added to the reference map. + * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}. + * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}. + */ + public void setReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) { + if (location.kind == CiKind.Object) { + if (isRegister(location)) { + assert registerRefMap.size() == target.arch.registerReferenceMapBitCount; + registerRefMap.set(asRegister(location).number); + } else if (isStackSlot(location)) { + int index = frameRefMapIndex(asStackSlot(location)); + frameRefMap.grow(index + 1); + frameRefMap.set(index); + } else { + assert isConstant(location); + } + } + } + + /** + * Clears the specified location as a reference in the reference map of the debug information. + * The tracked location can be a {@link CiRegisterValue} or a {@link CiStackSlot}. Note that a + * {@link CiConstant} is automatically tracked. + * + * @param location The location to be removed from the reference map. + * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}. + * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}. + */ + public void clearReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) { + if (location.kind == CiKind.Object) { + if (location instanceof CiRegisterValue) { + assert registerRefMap.size() == target.arch.registerReferenceMapBitCount; + registerRefMap.clear(asRegister(location).number); + } else if (isStackSlot(location)) { + int index = frameRefMapIndex(asStackSlot(location)); + if (index < frameRefMap.size()) { + frameRefMap.clear(index); + } + } else { + assert isConstant(location); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIR.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,240 @@ +/* + * 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.max.graal.lir; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.asm.*; +import com.oracle.max.graal.lir.cfg.*; + +/** + * This class implements the overall container for the LIR graph + * and directs its construction, optimization, and finalization. + */ +public class LIR { + + public final ControlFlowGraph cfg; + + /** + * The nodes for the blocks. + * TODO: This should go away, we want all nodes connected with a next-pointer. + */ + private final BlockMap<List<Node>> nodesFor; + + /** + * The linear-scan ordered list of blocks. + */ + private final List<Block> linearScanOrder; + + /** + * The order in which the code is emitted. + */ + private final List<Block> codeEmittingOrder; + + + public final List<SlowPath> slowPaths; + + public final List<SlowPath> deoptimizationStubs; + + /** + * The last slow path emitted, which can be used emit marker bytes. + */ + public SlowPath methodEndMarker; + + private int numVariables; + + public SpillMoveFactory spillMoveFactory; + + public interface SpillMoveFactory { + LIRInstruction createMove(CiValue result, CiValue input); + LIRInstruction createExchange(CiValue input1, CiValue input2); + } + + public interface SlowPath { + void emitCode(TargetMethodAssembler tasm); + } + + /** + * Creates a new LIR instance for the specified compilation. + * @param numLoops number of loops + * @param compilation the compilation + */ + public LIR(ControlFlowGraph cfg, BlockMap<List<Node>> nodesFor, List<Block> linearScanOrder, List<Block> codeEmittingOrder) { + this.cfg = cfg; + this.nodesFor = nodesFor; + this.codeEmittingOrder = codeEmittingOrder; + this.linearScanOrder = linearScanOrder; + + slowPaths = new ArrayList<>(); + deoptimizationStubs = new ArrayList<>(); + } + + public List<Node> nodesFor(Block block) { + return nodesFor.get(block); + } + + /** + * Gets the linear scan ordering of blocks as a list. + * @return the blocks in linear scan order + */ + public List<Block> linearScanOrder() { + return linearScanOrder; + } + + public List<Block> codeEmittingOrder() { + return codeEmittingOrder; + } + + public int numVariables() { + return numVariables; + } + + public int nextVariable() { + return numVariables++; + } + + public void emitCode(TargetMethodAssembler tasm) { + for (Block b : codeEmittingOrder()) { + emitBlock(tasm, b); + } + + // generate code for slow cases + for (SlowPath sp : slowPaths) { + emitSlowPath(tasm, sp); + } + // generate deoptimization stubs + for (SlowPath sp : deoptimizationStubs) { + emitSlowPath(tasm, sp); + } + // generate traps at the end of the method + emitSlowPath(tasm, methodEndMarker); + } + + private static void emitBlock(TargetMethodAssembler tasm, Block block) { + if (Debug.isDumpEnabled()) { + tasm.blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); + } + + for (LIRInstruction op : block.lir) { + if (Debug.isDumpEnabled()) { + tasm.blockComment(String.format("%d %s", op.id(), op)); + } + + emitOp(tasm, op); + } + } + + private static void emitOp(TargetMethodAssembler tasm, LIRInstruction op) { + try { + try { + op.emitCode(tasm); + } catch (AssertionError t) { + throw new GraalInternalError(t); + } catch (RuntimeException t) { + throw new GraalInternalError(t); + } + } catch (GraalInternalError e) { + throw e.addContext("lir instruction", op); + } + } + + private static void emitSlowPath(TargetMethodAssembler tasm, SlowPath sp) { + if (Debug.isDumpEnabled()) { + tasm.blockComment(String.format("slow case %s", sp.getClass().getName())); + } + sp.emitCode(tasm); + } + +/* + private int lastDecodeStart; + + private void printAssembly(TargetMethodAssembler tasm) { + byte[] currentBytes = tasm.asm.codeBuffer.copyData(lastDecodeStart, tasm.asm.codeBuffer.position()); + if (currentBytes.length > 0) { + String disasm = tasm.runtime.disassemble(currentBytes, lastDecodeStart); + if (disasm.length() != 0) { + TTY.println(disasm); + } else { + TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length); + Util.printBytes(lastDecodeStart, currentBytes, GraalOptions.PrintAssemblyBytesPerLine); + } + } + lastDecodeStart = tasm.asm.codeBuffer.position(); + } + + + public static void printBlock(Block x) { + // print block id + TTY.print("B%d ", x.getId()); + + // print flags + if (x.isLoopHeader()) { + TTY.print("lh "); + } + if (x.isLoopEnd()) { + TTY.print("le "); + } + + // print block bci range + TTY.print("[%d, %d] ", -1, -1); + + // print predecessors and successors + if (x.numberOfPreds() > 0) { + TTY.print("preds: "); + for (int i = 0; i < x.numberOfPreds(); i++) { + TTY.print("B%d ", x.predAt(i).getId()); + } + } + + if (x.numberOfSux() > 0) { + TTY.print("sux: "); + for (int i = 0; i < x.numberOfSux(); i++) { + TTY.print("B%d ", x.suxAt(i).getId()); + } + } + + TTY.println(); + } + + public static void printLIR(List<Block> blocks) { + if (TTY.isSuppressed()) { + return; + } + TTY.println("LIR:"); + int i; + for (i = 0; i < blocks.size(); i++) { + Block bb = blocks.get(i); + printBlock(bb); + TTY.println("__id_Instruction___________________________________________"); + for (LIRInstruction op : bb.lir) { + TTY.println(op.toStringWithIdPrefix()); + TTY.println(); + } + TTY.println(); + } + } +*/ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRDebugInfo.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,128 @@ +/* + * 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.max.graal.lir; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.max.graal.lir.LIRInstruction.OperandMode; +import com.oracle.max.graal.lir.LIRInstruction.ValueProcedure; + +/** + * This class represents garbage collection and deoptimization information attached to a LIR instruction. + */ +public class LIRDebugInfo { + public final CiFrame topFrame; + private final CiVirtualObject[] virtualObjects; + private final List<CiStackSlot> pointerSlots; + public final LabelRef exceptionEdge; + private CiDebugInfo debugInfo; + + public LIRDebugInfo(CiFrame topFrame, CiVirtualObject[] virtualObjects, List<CiStackSlot> pointerSlots, LabelRef exceptionEdge) { + this.topFrame = topFrame; + this.virtualObjects = virtualObjects; + this.pointerSlots = pointerSlots; + this.exceptionEdge = exceptionEdge; + } + + public boolean hasDebugInfo() { + return debugInfo != null; + } + + public CiDebugInfo 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 (CiFrame cur = topFrame; cur != null; cur = cur.caller()) { + processValues(cur.values, proc); + } + if (virtualObjects != null) { + for (CiVirtualObject 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<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + + private void processValues(CiValue[] values, ValueProcedure proc) { + for (int i = 0; i < values.length; i++) { + CiValue value = values[i]; + if (value instanceof CiMonitorValue) { + CiMonitorValue monitor = (CiMonitorValue) value; + if (processed(monitor.owner)) { + monitor.owner = proc.doValue(monitor.owner, OperandMode.Alive, STATE_FLAGS); + } + + } else if (processed(value)) { + values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS); + } + } + } + + private boolean processed(CiValue 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(CiBitMap registerRefMap, CiBitMap frameRefMap, FrameMap frameMap) { + debugInfo = new CiDebugInfo(topFrame, registerRefMap, frameRefMap); + + // Add additional stack slots for outgoing method parameters. + if (pointerSlots != null) { + for (CiStackSlot v : pointerSlots) { + frameMap.setReference(v, registerRefMap, frameRefMap); + } + } + } + + + @Override + public String toString() { + return debugInfo != null ? debugInfo.toString() : topFrame.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRInsertionBuffer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2009, 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.max.graal.lir; + +import java.util.*; + +/** + * A buffer to enqueue updates to a list. This avoids frequent re-sizing of the list and copying of list elements + * when insertions are done at multiple positions of the list. Additionally, it ensures that the list is not modified + * while it is, e.g., iterated, and instead only modified once after the iteration is done. + * <br> + * The buffer uses internal data structures to store the enqueued updates. To avoid allocations, a buffer can be re-used. + * Call the methods in the following order: + * {@link #init()}, {@link #append()}, {@link #append()}, ..., {@link #finish()}, {@link #init()}, ... + * <br> + * Note: This class does not depend on LIRInstruction, so we could make it a generic utility class. + */ +public final class LIRInsertionBuffer { + + /** + * The lir list where ops of this buffer should be inserted later (null when uninitialized). + */ + private List<LIRInstruction> lir; + + /** + * List of insertion points. index and count are stored alternately: + * indexAndCount[i * 2]: the index into lir list where "count" ops should be inserted + * indexAndCount[i * 2 + 1]: the number of ops to be inserted at index + */ + private final List<Integer> indexAndCount; + + /** + * The LIROps to be inserted. + */ + private final List<LIRInstruction> ops; + + + public LIRInsertionBuffer() { + indexAndCount = new ArrayList<>(8); + ops = new ArrayList<>(8); + } + + /** + * Initialize this buffer. This method must be called before using {@link #append()}. + */ + public void init(List<LIRInstruction> newLir) { + assert !initialized() : "already initialized"; + assert indexAndCount.size() == 0 && ops.size() == 0; + this.lir = newLir; + } + + public boolean initialized() { + return lir != null; + } + + public List<LIRInstruction> lirList() { + return lir; + } + + /** + * Enqueue a new instruction that will be appended to the instruction list when {@link #finish()} is called. + * The new instruction is added <b>before</b> the existing instruction with the given index. This method can only be called + * with increasing values of index, e.g., once an instruction was appended with index 4, subsequent instructions can + * only be appended with index 4 or higher. + */ + public void append(int index, LIRInstruction op) { + int i = numberOfInsertionPoints() - 1; + if (i < 0 || indexAt(i) < index) { + appendNew(index, 1); + } else { + assert indexAt(i) == index : "can append LIROps in ascending order only"; + assert countAt(i) > 0 : "check"; + setCountAt(i, countAt(i) + 1); + } + ops.add(op); + + assert verify(); + } + + /** + * Append all enqueued instructions to the instruction list. After that, {@link init()} can be called again to re-use this buffer. + */ + public void finish() { + if (ops.size() > 0) { + int n = lir.size(); + // increase size of instructions list + for (int i = 0; i < ops.size(); i++) { + lir.add(null); + } + // insert ops from buffer into instructions list + int opIndex = ops.size() - 1; + int ipIndex = numberOfInsertionPoints() - 1; + int fromIndex = n - 1; + int toIndex = lir.size() - 1; + while (ipIndex >= 0) { + int index = indexAt(ipIndex); + // make room after insertion point + while (fromIndex >= index) { + lir.set(toIndex--, lir.get(fromIndex--)); + } + // insert ops from buffer + for (int i = countAt(ipIndex); i > 0; i--) { + lir.set(toIndex--, ops.get(opIndex--)); + } + ipIndex--; + } + indexAndCount.clear(); + ops.clear(); + } + lir = null; + } + + private void appendNew(int index, int count) { + indexAndCount.add(index); + indexAndCount.add(count); + } + + private void setCountAt(int i, int value) { + indexAndCount.set((i << 1) + 1, value); + } + + private int numberOfInsertionPoints() { + assert indexAndCount.size() % 2 == 0 : "must have a count for each index"; + return indexAndCount.size() >> 1; + } + + private int indexAt(int i) { + return indexAndCount.get((i << 1)); + } + + private int countAt(int i) { + return indexAndCount.get((i << 1) + 1); + } + + private boolean verify() { + int sum = 0; + int prevIdx = -1; + + for (int i = 0; i < numberOfInsertionPoints(); i++) { + assert prevIdx < indexAt(i) : "index must be ordered ascending"; + sum += countAt(i); + } + assert sum == ops.size() : "wrong total sum"; + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRInstruction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,447 @@ +/* + * 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.max.graal.lir; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.asm.*; + +/** + * The {@code LIRInstruction} class definition. + */ +public abstract class LIRInstruction { + + public static final CiValue[] NO_OPERANDS = {}; + + /** + * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue methods. + * Clients of the class must only call the doValue method that takes additional parameters. + */ + public abstract static class ValueProcedure { + /** + * Iterator method to be overwritten. This version of the iterator does not take additional parameters + * to keep the signature short. + * + * @param value The value that is iterated. + * @return The new value to replace the value that was passed in. + */ + protected CiValue doValue(CiValue value) { + throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten"); + } + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters about the + * processed value. + * + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + * @return The new value to replace the value that was passed in. + */ + public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + return doValue(value); + } + } + + + /** + * Constants denoting how a LIR instruction uses an operand. + */ + public enum OperandMode { + /** + * The value must have been defined before. It is alive before the instruction until the beginning of the + * instruction, but not necessarily throughout the instruction. A register assigned to it can also be assigend + * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not + * modify the register. + */ + Input, + + /** + * 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, + + /** + * 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, + + /** + * 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, + } + + /** + * Flags for an operand. + */ + public enum OperandFlag { + /** + * The value can be a {@link CiRegisterValue}. + */ + Register, + + /** + * The value can be a {@link CiStackSlot}. + */ + Stack, + + /** + * The value can be a {@link CiAddress}. + */ + Address, + + /** + * The value can be a {@link CiConstant}. + */ + Constant, + + /** + * The value can be {@link CiValue#IllegalValue}. + */ + 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, + + /** + * 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, + } + + /** + * For validity checking of the operand flags defined by instruction subclasses. + */ + private static final EnumMap<OperandMode, EnumSet<OperandFlag>> 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)); + } + + /** + * The opcode of this instruction. + */ + protected final Object code; + + /** + * The output operands for this instruction (modified by the register allocator). + */ + protected CiValue[] outputs; + + /** + * The input operands for this instruction (modified by the register allocator). + */ + protected CiValue[] inputs; + + /** + * The alive operands for this instruction (modified by the register allocator). + */ + protected CiValue[] alives; + + /** + * The temp operands for this instruction (modified by the register allocator). + */ + protected CiValue[] temps; + + /** + * Used to emit debug information. + */ + public final LIRDebugInfo info; + + /** + * Instruction id for register allocation. + */ + 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. + */ + public LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + this.code = opcode; + this.outputs = outputs; + this.inputs = inputs; + this.alives = alives; + this.temps = temps; + this.info = info; + this.id = -1; + } + + public abstract void emitCode(TargetMethodAssembler tasm); + + + public final int id() { + return id; + } + + public final void setId(int id) { + this.id = id; + } + + /** + * Gets an input operand of this instruction. + * + * @param index the index of the operand requested. + * @return the {@code index}'th input operand. + */ + protected final CiValue 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 CiValue 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 CiValue temp(int index) { + return temps[index]; + } + + /** + * Gets the result operand for this instruction. + * + * @return return the result operand + */ + protected final CiValue output(int index) { + return outputs[index]; + } + + /** + * Gets the instruction name. + */ + public String name() { + return code.toString(); + } + + public boolean hasOperands() { + return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall(); + } + + private static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + + private void forEach(CiValue[] values, OperandMode mode, ValueProcedure proc) { + for (int i = 0; i < values.length; i++) { + assert ALLOWED_FLAGS.get(mode).containsAll(flagsFor(mode, i)); + + CiValue value = values[i]; + if (isAddress(value)) { + assert flagsFor(mode, i).contains(OperandFlag.Address); + CiAddress address = asAddress(value); + address.base = proc.doValue(address.base, mode, ADDRESS_FLAGS); + address.index = proc.doValue(address.index, mode, ADDRESS_FLAGS); + } else { + values[i] = proc.doValue(values[i], mode, flagsFor(mode, i)); + } + } + } + + 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); + } + } + } + } + + /** + * Returns true when this instruction is a call instruction that destroys all caller-saved registers. + */ + public final boolean hasCall() { + return this instanceof StandardOp.CallOp; + } + + /** + * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be + * assigned to the value. + * <br> + * Subclasses can override this method. The default implementation processes all Input operands as the hints for + * an Output operand, and all Output operands as the hints for an Input operand. + * + * @param value The value the hints are needed for. + * @param mode The operand mode of the value. + * @param proc The procedure invoked for all the hints. If the procedure returns a non-null value, the iteration is stopped + * and the value is returned by this method, i.e., clients can stop the iteration once a suitable hint has been found. + * @return The non-null value returned by the procedure, or null. + */ + public CiValue forEachRegisterHint(CiValue value, OperandMode mode, ValueProcedure proc) { + CiValue[] 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++) { + CiValue result = proc.doValue(hints[i], null, null); + if (result != null) { + return result; + } + } + return null; + } + + /** + * 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 this method will go away when we have named operands, the flags will be specified as annotations instead. + protected abstract EnumSet<OperandFlag> flagsFor(OperandMode mode, int index); + + protected void verify() { + } + + + public final String toStringWithIdPrefix() { + if (id != -1) { + return String.format("%4d %s", id, toString()); + } + 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 (CiValue 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 (CiValue input : inputs) { + buf.append(sep).append(input); + sep = ", "; + } + for (CiValue 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 (CiValue 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 (CiFrame cur = info.topFrame; cur != null; cur = cur.caller()) { + buf.append(sep).append(cur.bci); + sep = ","; + } + buf.append("]"); + } + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString()); + appendDebugInfo(buf); + return buf.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRVerifier.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,241 @@ +/* + * 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.max.graal.lir; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.lir.ValueUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.criutils.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.LIRInstruction.*; +import com.oracle.max.graal.lir.cfg.*; + +public final class LIRVerifier { + private final LIR lir; + private final FrameMap frameMap; + + private final boolean beforeRegisterAllocation; + + private final BitSet[] blockLiveOut; + private final Object[] variableDefinitions; + + private BitSet liveOutFor(Block block) { + return blockLiveOut[block.getId()]; + } + private void setLiveOutFor(Block block, BitSet liveOut) { + blockLiveOut[block.getId()] = liveOut; + } + + private int maxRegisterNum() { + return frameMap.target.arch.registers.length; + } + + private boolean isAllocatableRegister(CiValue value) { + return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; + } + + public static boolean verify(final LIRInstruction op) { + ValueProcedure allowedProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return allowed(op, value, mode, flags); } }; + + op.forEachInput(allowedProc); + op.forEachAlive(allowedProc); + op.forEachState(allowedProc); + op.forEachTemp(allowedProc); + op.forEachOutput(allowedProc); + + op.verify(); + return true; + } + + public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { + LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap); + verifier.verify(); + return true; + } + + + private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { + this.beforeRegisterAllocation = beforeRegisterAllocation; + this.lir = lir; + this.frameMap = frameMap; + this.blockLiveOut = new BitSet[lir.linearScanOrder().size()]; + this.variableDefinitions = new Object[lir.numVariables()]; + } + + private BitSet curVariablesLive; + private CiValue[] curRegistersLive; + + private Block curBlock; + private Object curInstruction; + private BitSet curRegistersDefined; + + private void verify() { + ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } }; + ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } }; + + curRegistersDefined = new BitSet(); + for (Block block : lir.linearScanOrder()) { + curBlock = block; + curVariablesLive = new BitSet(); + curRegistersLive = new CiValue[maxRegisterNum()]; + + if (block.getDominator() != null) { + curVariablesLive.or(liveOutFor(block.getDominator())); + } + + assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label"; + if (block.numberOfPreds() > 1) { + assert block.lir.get(0) instanceof StandardOp.PhiLabelOp : "phi mapping required for multiple predecessors"; + CiValue[] phiDefinitions = ((StandardOp.PhiLabelOp) block.lir.get(0)).getPhiDefinitions(); + if (!beforeRegisterAllocation) { + assert phiDefinitions.length == 0; + } + for (Block pred : block.getPredecessors()) { + assert pred.numberOfSux() == 1; + LIRInstruction last = pred.lir.get(pred.lir.size() - 1); + assert last instanceof StandardOp.PhiJumpOp : "phi mapping required for multiple successors"; + CiValue[] phiUses = ((StandardOp.PhiJumpOp) last).getPhiInputs(); + if (!beforeRegisterAllocation) { + assert phiUses.length == 0; + } + } + } + + if (block.numberOfSux() > 0) { + LIRInstruction last = block.lir.get(block.lir.size() - 1); + assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump"; + } + + for (LIRInstruction op : block.lir) { + curInstruction = op; + + op.forEachInput(useProc); + if (op.hasCall()) { + for (CiRegister register : frameMap.registerConfig.getCallerSaveRegisters()) { + curRegistersLive[register.number] = null; + } + } + curRegistersDefined.clear(); + op.forEachAlive(useProc); + op.forEachState(useProc); + op.forEachTemp(defProc); + op.forEachOutput(defProc); + + curInstruction = null; + } + + setLiveOutFor(block, curVariablesLive); + } + } + + private CiValue use(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + allowed(curInstruction, value, mode, flags); + + if (isVariable(value)) { + assert beforeRegisterAllocation; + + int variableIdx = asVariable(value).index; + if (!curVariablesLive.get(variableIdx)) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("live variables: %s", curVariablesLive); + if (variableDefinitions[variableIdx] != null) { + TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); + } + TTY.println("ERROR: Use of variable %s that is not defined in dominator", value); + throw GraalInternalError.shouldNotReachHere(); + } + + } else if (isAllocatableRegister(value)) { + int regNum = asRegister(value).number; + if (mode == OperandMode.Alive) { + curRegistersDefined.set(regNum); + } + + if (beforeRegisterAllocation && curRegistersLive[regNum] != value) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("live registers: %s", Arrays.toString(curRegistersLive)); + TTY.println("ERROR: Use of fixed register %s that is not defined in this block", value); + throw GraalInternalError.shouldNotReachHere(); + } + } + return value; + } + + private CiValue def(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + allowed(curInstruction, value, mode, flags); + + if (isVariable(value)) { + assert beforeRegisterAllocation; + + int variableIdx = asVariable(value).index; + if (variableDefinitions[variableIdx] != null) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("live variables: %s", curVariablesLive); + TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); + TTY.println("ERROR: Variable %s defined multiple times", value); + throw GraalInternalError.shouldNotReachHere(); + } + assert curInstruction != null; + variableDefinitions[variableIdx] = curInstruction; + assert !curVariablesLive.get(variableIdx); + if (mode == OperandMode.Output) { + curVariablesLive.set(variableIdx); + } + + } else if (isAllocatableRegister(value)) { + int regNum = asRegister(value).number; + if (curRegistersDefined.get(regNum)) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("ERROR: Same register defined twice in the same instruction: %s", value); + throw GraalInternalError.shouldNotReachHere(); + } + curRegistersDefined.set(regNum); + + if (beforeRegisterAllocation) { + if (mode == OperandMode.Output) { + curRegistersLive[regNum] = value; + } else { + curRegistersLive[regNum] = null; + } + } + } + return value; + } + + private static CiValue allowed(Object op, CiValue value, OperandMode mode, EnumSet<OperandFlag> 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))) { + return value; + } + TTY.println("instruction %s", op); + TTY.println("mode: %s flags: %s", mode, flags); + TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); + throw GraalInternalError.shouldNotReachHere(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LIRXirInstruction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,96 @@ +/* + * 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.max.graal.lir; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.xir.*; +import com.oracle.max.graal.graph.*; + +public abstract class LIRXirInstruction extends LIRInstruction { + + public final CiValue[] 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, + CiValue[] originalOperands, + CiValue outputOperand, + CiValue[] inputs, CiValue[] temps, + int[] inputOperandIndices, int[] tempOperandIndices, + int outputOperandIndex, + LIRDebugInfo info, + LIRDebugInfo infoAfter, + 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 CiValue[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps); + this.infoAfter = infoAfter; + this.snippet = snippet; + this.inputOperandIndices = inputOperandIndices; + this.tempOperandIndices = tempOperandIndices; + this.outputOperandIndex = outputOperandIndex; + this.originalOperands = originalOperands; + this.falseSuccessor = falseSuccessor; + this.trueSuccessor = trueSuccessor; + assert isLegal(outputOperand) || outputOperandIndex == -1; + } + + @Override + protected EnumSet<OperandFlag> 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 CiValue[] getOperands() { + for (int i = 0; i < inputOperandIndices.length; i++) { + originalOperands[inputOperandIndices[i]] = alive(i); + } + for (int i = 0; i < tempOperandIndices.length; i++) { + originalOperands[tempOperandIndices[i]] = temp(i); + } + if (outputOperandIndex != -1) { + originalOperands[outputOperandIndex] = output(0); + } + return originalOperands; + } + + @Override + public String name() { + return "XIR: " + snippet.template; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/LabelRef.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir; + +import com.oracle.max.asm.*; +import com.oracle.max.graal.lir.cfg.*; + +/** + * LIR instructions such as JUMP and BRANCH need to reference their target {@link Block}. However, + * direct references are not possible since the control flow graph (and therefore successors lists) can + * be changed by optimizations - and fixing the instructions is error prone. + * Therefore, we only reference of block B from block A only via the tuple (A, successor-index-of-B), i.e., + * indirectly by storing the index into the successor list of A. + * Note that therefore it is not allowed to reorder the successor list! + * + * Labels of out-of-line stubs can be referenced directly, therefore it is also possible to construct a + * LabelRef for a Label directly via {@link #forLabel}. + */ +public abstract class LabelRef { + + public abstract Label label(); + + /** + * Returns a new reference to a statically defined label. + * @param label The label that is always returned. + * @return The newly created label reference. + */ + public static LabelRef forLabel(final Label label) { + return new LabelRef() { + @Override + public Label label() { + return label; + } + + @Override + public String toString() { + return label.toString(); + } + }; + } + + /** + * Returns a new reference to a successor of the given block. + * This allows to reference the given successor even when the successor list + * is modified between the creation of the reference and the call to {@link #getLabel}. + * @param block The base block that contains the successor list. + * @param suxIndex The index of the successor. + * @return The newly created label reference. + */ + public static LabelRef forSuccessor(final Block block, final int suxIndex) { + return new LabelRef() { + @Override + public Label label() { + return ((StandardOp.LabelOp) block.suxAt(suxIndex).lir.get(0)).getLabel(); + } + + @Override + public String toString() { + return suxIndex < block.numberOfSux() ? block.suxAt(suxIndex).toString() : "?" + block + ":" + suxIndex + "?"; + } + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/StandardOp.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.asm.*; + +/** + * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR + * operations. + */ +public class StandardOp { + + private static CiValue[] EMPTY = new CiValue[0]; + + /** + * LIR operation that defines the position of a label. + * The first operation of every block must implement this interface. + */ + public static class LabelOp extends LIRInstruction { + private final Label label; + private final boolean align; + + protected LabelOp(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps, Label label, boolean align) { + super(opcode, outputs, info, inputs, alives, temps); + 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) { + tasm.asm.align(tasm.target.wordSize); + } + tasm.asm.bind(label); + } + + @Override + public String operationString() { + return label.toString() + " " + super.operationString(); + } + + @Override + protected EnumSet<OperandFlag> 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, CiValue[] phiDefinitions) { + super("PHI_LABEL", phiDefinitions, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align); + } + + @Override + protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Output) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw GraalInternalError.shouldNotReachHere(); + } + + public void markResolved() { + outputs = EMPTY; + } + + public CiValue[] getPhiDefinitions() { + return outputs; + } + } + + /** + * LIR operation that is an unconditional jump to {@link #destination()}. + * When the LIR is constructed, the last operation of every block must implement this interface. After + * register allocation, unnecessary jumps can be deleted. + * + * TODO Currently, a block can also end with an XIR operation. + */ + public static class JumpOp extends LIRInstruction { + private final LabelRef destination; + + protected JumpOp(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps, LabelRef destination) { + super(opcode, outputs, info, inputs, alives, temps); + 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); + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + tasm.asm.jmp(destination.label()); + } + + @Override + public String operationString() { + return destination + " " + super.operationString(); + } + + @Override + protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { + throw GraalInternalError.shouldNotReachHere(); + } + + public LabelRef destination() { + return destination; + } + } + + public static class PhiJumpOp extends JumpOp { + public PhiJumpOp(LabelRef destination, CiValue[] phiInputs) { + super("PHI_JUMP", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, phiInputs, LIRInstruction.NO_OPERANDS, destination); + } + + @Override + protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Alive) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } + throw GraalInternalError.shouldNotReachHere(); + } + + public void markResolved() { + alives = EMPTY; + } + + public CiValue[] getPhiInputs() { + return alives; + } + } + + /** + * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}. + * Conditional jumps may be negated or optimized away after register allocation. + */ + public interface BranchOp { + LabelRef destination(); + void negate(LabelRef newDestination); + } + + /** + * Marker interface for a LIR operation that moves a value from {@link #getInput()} to {@link #getResult()}. + */ + public interface MoveOp { + CiValue getInput(); + CiValue getResult(); + } + + /** + * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved registers. + */ + public interface CallOp { + } + + + /** + * Meta-operation that defines the incoming method parameters. In the LIR, every register and variable must be + * defined before it is used. This operation is the definition point of method parameters, but is otherwise a no-op. + * In particular, it is not the actual method prologue. + */ + public static final class ParametersOp extends LIRInstruction { + public ParametersOp(CiValue[] params) { + super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + // No code to emit. + } + + @Override + protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Output) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw GraalInternalError.shouldNotReachHere(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/ValueUtil.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir; + +import com.oracle.max.cri.ci.*; + +public class ValueUtil extends CiValueUtil { + + public static boolean isVariable(CiValue value) { + assert value != null; + return value instanceof Variable; + } + + public static Variable asVariable(CiValue value) { + assert value != null; + return (Variable) value; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/Variable.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010, 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.max.graal.lir; + +import com.oracle.max.cri.ci.*; + +/** + * Represents a value that is yet to be bound to a machine location (such as + * a {@link CiRegisterValue} or {@link CiStackSlot}) by a register allocator. + */ +public final class Variable extends CiValue { + private static final long serialVersionUID = 4507578431686109809L; + + /** + * The identifier of the variable. This is a non-zero index in a contiguous 0-based name space. + */ + public final int index; + + /** + * The type of register that this variable needs to get assigned. + */ + public final CiRegister.RegisterFlag flag; + + /** + * Creates a new variable. + * @param kind + * @param index + */ + public Variable(CiKind kind, int index, CiRegister.RegisterFlag flag) { + super(kind); + assert kind == kind.stackKind() : "Variables can be only created for stack kinds"; + assert index >= 0; + this.index = index; + this.flag = flag; + } + + @Override + public int hashCode() { + return (index << 4) | kind.ordinal(); + } + + @Override + public String toString() { + return "v" + index + kindSuffix(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/asm/TargetMethodAssembler.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.asm; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.LIR.*; + +public class TargetMethodAssembler { + + private static class ExceptionInfo { + public final int codeOffset; + public final LabelRef exceptionEdge; + + public ExceptionInfo(int pcOffset, LabelRef exceptionEdge) { + this.codeOffset = pcOffset; + this.exceptionEdge = exceptionEdge; + } + } + + public final AbstractAssembler asm; + public final CiTargetMethod targetMethod; + public final CiTarget target; + public final RiRuntime runtime; + public final FrameMap frameMap; + public final List<SlowPath> slowPaths; + + private List<ExceptionInfo> exceptionInfoList; + private int lastSafepointPos; + + public TargetMethodAssembler(CiTarget target, RiRuntime runtime, FrameMap frameMap, List<SlowPath> slowPaths, AbstractAssembler asm) { + this.target = target; + this.runtime = runtime; + this.frameMap = frameMap; + this.slowPaths = slowPaths; + this.asm = asm; + this.targetMethod = new CiTargetMethod(); + // 0 is a valid pc for safepoints in template methods + this.lastSafepointPos = -1; + } + + public void setFrameSize(int frameSize) { + targetMethod.setFrameSize(frameSize); + } + + public CiTargetMethod.Mark recordMark(Object id, CiTargetMethod.Mark[] references) { + return targetMethod.recordMark(asm.codeBuffer.position(), id, references); + } + + public void blockComment(String s) { + targetMethod.addAnnotation(new CiTargetMethod.CodeComment(asm.codeBuffer.position(), s)); + } + + public CiTargetMethod finishTargetMethod(Object name, boolean isStub) { + // Install code, data and frame size + targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position()); + + // Record exception handlers if they exist + if (exceptionInfoList != null) { + for (ExceptionInfo ei : exceptionInfoList) { + int codeOffset = ei.codeOffset; + targetMethod.recordExceptionHandler(codeOffset, -1, 0, ei.exceptionEdge.label().position(), -1, null); + } + } + + Debug.metric("TargetMethods").increment(); + Debug.metric("CodeBytesEmitted").add(targetMethod.targetCodeSize()); + Debug.metric("SafepointsEmitted").add(targetMethod.safepoints.size()); + Debug.metric("DataPatches").add(targetMethod.dataReferences.size()); + Debug.metric("ExceptionHandlersEmitted").add(targetMethod.exceptionHandlers.size()); + + Debug.log("Finished target method %s, isStub %d", name, isStub); +/* + if (GraalOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) { + Util.printSection("Target Method", Util.SECTION_CHARACTER); + TTY.println("Name: " + name); + TTY.println("Frame size: " + targetMethod.frameSize()); + TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount); + + if (GraalOptions.PrintCodeBytes) { + Util.printSection("Code", Util.SUB_SECTION_CHARACTER); + TTY.println("Code: %d bytes", targetMethod.targetCodeSize()); + Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), GraalOptions.PrintAssemblyBytesPerLine); + } + + Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER); + String disassembly = runtime.disassemble(targetMethod); + TTY.println(disassembly); + boolean noDis = disassembly == null || disassembly.length() == 0; + + Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.Safepoint x : targetMethod.safepoints) { + TTY.println(x.toString()); + if (noDis && x.debugInfo != null) { + TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); + } + } + + Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) { + TTY.println(x.toString()); + } + + Util.printSection("Marks", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.Mark x : targetMethod.marks) { + TTY.println(x.toString()); + } + + Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER); + for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) { + TTY.println(x.toString()); + } + } +*/ + + return targetMethod; + } + + public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) { + if (info != null) { + if (info.exceptionEdge != null) { + if (exceptionInfoList == null) { + exceptionInfoList = new ArrayList<>(4); + } + exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge)); + } + } + } + + public void recordImplicitException(int pcOffset, LIRDebugInfo info) { + // record an implicit exception point + if (info != null) { + assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset; + lastSafepointPos = pcOffset; + targetMethod.recordSafepoint(pcOffset, info.debugInfo()); + assert info.exceptionEdge == null; + } + } + + public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) { + CiDebugInfo 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) { + CiDebugInfo 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) { + // safepoints always need debug info + CiDebugInfo debugInfo = info.debugInfo(); + assert lastSafepointPos < pos; + lastSafepointPos = pos; + targetMethod.recordSafepoint(pos, debugInfo); + } + + public CiAddress recordDataReferenceInCode(CiConstant data, int alignment) { + assert data != null; + int pos = asm.codeBuffer.position(); + Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString()); + targetMethod.recordDataReference(pos, data, alignment); + return CiAddress.Placeholder; + } + + public int lastSafepointPos() { + return lastSafepointPos; + } + + + /** + * Returns the integer value of any constants that can be represented by a 32-bit integer value, + * including long constants that fit into the 32-bit range. + */ + public int asIntConst(CiValue value) { + assert (value.kind.stackKind() == CiKind.Int || value.kind == CiKind.Jsr || value.kind == CiKind.Long) && isConstant(value); + long c = ((CiConstant) value).asLong(); + if (!(NumUtil.isInt(c))) { + throw GraalInternalError.shouldNotReachHere(); + } + return (int) c; + } + + /** + * Returns the address of a float constant that is embedded as a data references into the code. + */ + public CiAddress asFloatConstRef(CiValue value) { + return asFloatConstRef(value, 4); + } + + public CiAddress asFloatConstRef(CiValue value, int alignment) { + assert value.kind == CiKind.Float && isConstant(value); + return recordDataReferenceInCode((CiConstant) value, alignment); + } + + /** + * Returns the address of a double constant that is embedded as a data references into the code. + */ + public CiAddress asDoubleConstRef(CiValue value) { + return asDoubleConstRef(value, 8); + } + + public CiAddress asDoubleConstRef(CiValue value, int alignment) { + assert value.kind == CiKind.Double && isConstant(value); + return recordDataReferenceInCode((CiConstant) value, alignment); + } + + /** + * Returns the address of a long constant that is embedded as a data references into the code. + */ + public CiAddress asLongConstRef(CiValue value) { + assert value.kind == CiKind.Long && isConstant(value); + return recordDataReferenceInCode((CiConstant) value, 8); + } + + public CiAddress asIntAddr(CiValue value) { + assert value.kind == CiKind.Int; + return asAddress(value); + } + + public CiAddress asLongAddr(CiValue value) { + assert value.kind == CiKind.Long; + return asAddress(value); + } + + public CiAddress asObjectAddr(CiValue value) { + assert value.kind == CiKind.Object; + return asAddress(value); + } + + public CiAddress asFloatAddr(CiValue value) { + assert value.kind == CiKind.Float; + return asAddress(value); + } + + public CiAddress asDoubleAddr(CiValue value) { + assert value.kind == CiKind.Double; + return asAddress(value); + } + + public CiAddress asAddress(CiValue value) { + if (isStackSlot(value)) { + CiStackSlot slot = (CiStackSlot) value; + return new CiAddress(slot.kind, frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot)); + } + return (CiAddress) value; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/Block.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,186 @@ +/* + * 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.max.graal.lir.cfg; + +import java.util.*; + +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.java.*; + +public class Block { + protected int id; + + protected BeginNode beginNode; + protected Node endNode; + protected Loop loop; + protected double probability; + + protected List<Block> predecessors; + protected List<Block> successors; + + protected Block dominator; + protected List<Block> dominated; + protected Block postdominator; + + // Fields that still need to be worked on, try to remove them later. + public List<LIRInstruction> lir; + public boolean align; + public int linearScanNumber; + + public Block() { + id = ControlFlowGraph.BLOCK_ID_INITIAL; + } + + public int getId() { + assert id >= 0; + return id; + } + + public BeginNode getBeginNode() { + return beginNode; + } + + public Node getEndNode() { + return endNode; + } + + public Loop getLoop() { + return loop; + } + + public int getLoopDepth() { + return loop == null ? 0 : loop.depth; + } + + public boolean isLoopHeader() { + return getBeginNode() instanceof LoopBeginNode; + } + + public boolean isLoopEnd() { + return getEndNode() instanceof LoopEndNode; + } + + public boolean isExceptionEntry() { + return getBeginNode().next() instanceof ExceptionObjectNode; + } + + public List<Block> getPredecessors() { + return predecessors; + } + + public List<Block> getSuccessors() { + return successors; + } + + public Block getDominator() { + return dominator; + } + + public List<Block> getDominated() { + if (dominated == null) { + return Collections.emptyList(); + } + return dominated; + } + + public Block getPostdominator() { + return postdominator; + } + + private class NodeIterator implements Iterator<Node> { + private Node cur; + + public NodeIterator() { + cur = getBeginNode(); + } + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public Node next() { + Node result = cur; + if (cur == getEndNode()) { + cur = null; + } else { + cur = ((FixedWithNextNode) cur).next(); + } + assert !(cur instanceof BeginNode); + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + public Iterable<Node> getNodes() { + return new Iterable<Node>() { + @Override + public Iterator<Node> iterator() { + return new NodeIterator(); + } + }; + } + + public int getFirstLirInstructionId() { + int result = lir.get(0).id(); + assert result >= 0; + return result; + } + + public int getLastLirInstructionId() { + int result = lir.get(lir.size() - 1).id(); + assert result >= 0; + return result; + } + + @Override + public String toString() { + return "B" + id; + } + + +// to be inlined later on + public int numberOfPreds() { + return getPredecessors().size(); + } + + public int numberOfSux() { + return getSuccessors().size(); + } + + public Block predAt(int i) { + return getPredecessors().get(i); + } + + public Block suxAt(int i) { + return getSuccessors().get(i); + } +// end to be inlined later on +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/BlockMap.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.lir.cfg; + +public class BlockMap<T> { + private final T[] data; + + @SuppressWarnings("unchecked") + public BlockMap(ControlFlowGraph cfg) { + data = (T[]) new Object[cfg.getBlocks().length]; + } + + public T get(Block block) { + return data[block.getId()]; + } + + public void put(Block block, T value) { + data[block.getId()] = value; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/CFGVerifier.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.lir.cfg; + +public class CFGVerifier { + public static boolean verify(ControlFlowGraph cfg) { + for (Block block : cfg.getBlocks()) { + assert cfg.getBlocks()[block.getId()] == block; + + for (Block pred : block.getPredecessors()) { + assert pred.getSuccessors().contains(block); + assert pred.getId() < block.getId() || pred.isLoopEnd(); + } + + for (Block sux : block.getSuccessors()) { + assert sux.getPredecessors().contains(block); + assert sux.getId() > block.getId() || sux.isLoopHeader(); + } + + if (block.getDominator() != null) { + assert block.getDominator().getId() < block.getId(); + assert block.getDominator().getDominated().contains(block); + } + for (Block dominated : block.getDominated()) { + assert dominated.getId() > block.getId(); + assert dominated.getDominator() == block; + } + + assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block; + } + + if (cfg.getLoops() != null) { + for (Loop loop : cfg.getLoops()) { + assert loop.header.isLoopHeader(); + + for (Block block : loop.blocks) { + assert block.getId() >= loop.header.getId(); + + Loop blockLoop = block.getLoop(); + while (blockLoop != loop) { + blockLoop = blockLoop.parent; + assert blockLoop != null; + } + } + + for (Block block : loop.exits) { + assert block.getId() >= loop.header.getId(); + + Loop blockLoop = block.getLoop(); + while (blockLoop != null) { + blockLoop = blockLoop.parent; + assert blockLoop != loop; + } + } + } + } + + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/ControlFlowGraph.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2011, 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.max.graal.lir.cfg; + +import java.util.*; + +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.nodes.*; + +public class ControlFlowGraph { + + public final StructuredGraph graph; + + private final NodeMap<Block> nodeToBlock; + private Block[] reversePostOrder; + private Loop[] loops; + + public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { + ControlFlowGraph cfg = new ControlFlowGraph(graph); + cfg.identifyBlocks(); + if (connectBlocks || computeLoops || computeDominators || computePostdominators) { + cfg.connectBlocks(); + } + if (computeLoops) { + cfg.computeLoopInformation(); + } + if (computeDominators) { + cfg.computeDominators(); + } + if (computePostdominators) { + cfg.computePostdominators(); + } + assert CFGVerifier.verify(cfg); + return cfg; + } + + protected ControlFlowGraph(StructuredGraph graph) { + this.graph = graph; + this.nodeToBlock = graph.createNodeMap(); + } + + public Block[] getBlocks() { + return reversePostOrder; + } + + public Block getStartBlock() { + return reversePostOrder[0]; + } + + public NodeMap<Block> getNodeToBlock() { + return nodeToBlock; + } + + public Block blockFor(Node node) { + return nodeToBlock.get(node); + } + + public Loop[] getLoops() { + return loops; + } + + protected static final int BLOCK_ID_INITIAL = -1; + protected static final int BLOCK_ID_VISITED = -2; + + private void identifyBlocks() { + // Find all block headers + int numBlocks = 0; + for (Node node : graph.getNodes()) { + if (node instanceof BeginNode) { + Block block = new Block(); + numBlocks++; + + block.beginNode = (BeginNode) node; + Node cur = node; + do { + assert !cur.isDeleted(); + block.endNode = cur; + + assert nodeToBlock.get(cur) == null; + nodeToBlock.set(cur, block); + if (cur instanceof MergeNode) { + for (PhiNode phi : ((MergeNode) cur).phis()) { + nodeToBlock.set(phi, block); + } + } + + if (cur instanceof FixedNode) { + double probability = ((FixedNode) cur).probability(); + if (probability > block.probability) { + block.probability = probability; + } + } + + Node next = null; + for (Node sux : cur.successors()) { + if (sux != null && !(sux instanceof BeginNode)) { + assert next == null; + next = sux; + } + } + cur = next; + } while (cur != null); + } + } + + // Compute reverse postorder. + reversePostOrder = new Block[numBlocks]; + int reversePostOrderId = numBlocks - 1; + + ArrayList<Block> stack = new ArrayList<>(); + stack.add(blockFor(graph.start())); + + do { + Block block = stack.get(stack.size() - 1); + if (block.id == BLOCK_ID_INITIAL) { + // First time we see this block: push all successors. + for (Node suxNode : block.getEndNode().cfgSuccessors()) { + Block suxBlock = blockFor(suxNode); + assert suxBlock.id != BLOCK_ID_VISITED; + if (suxBlock.id == BLOCK_ID_INITIAL) { + stack.add(suxBlock); + } + } + block.id = BLOCK_ID_VISITED; + } else if (block.id == BLOCK_ID_VISITED) { + // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list. + stack.remove(stack.size() - 1); + reversePostOrder[reversePostOrderId] = block; + block.id = reversePostOrderId; + reversePostOrderId--; + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } while (!stack.isEmpty()); + assert reversePostOrderId == -1; + } + + // Connect blocks (including loop backward edges). + private void connectBlocks() { + for (Block block : reversePostOrder) { + List<Block> predecessors = new ArrayList<>(); + for (Node predNode : block.getBeginNode().cfgPredecessors()) { + predecessors.add(nodeToBlock.get(predNode)); + } + if (block.getBeginNode() instanceof LoopBeginNode) { + predecessors.add(nodeToBlock.get(((LoopBeginNode) block.getBeginNode()).loopEnd())); + } + block.predecessors = predecessors; + + List<Block> successors = new ArrayList<>(); + for (Node suxNode : block.getEndNode().cfgSuccessors()) { + successors.add(nodeToBlock.get(suxNode)); + } + if (block.getEndNode() instanceof LoopEndNode) { + successors.add(nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin())); + } + block.successors = successors; + } + } + + private void computeLoopInformation() { + List<Loop> loopsList = new ArrayList<>(); + for (Block block : reversePostOrder) { + Node beginNode = block.getBeginNode(); + if (beginNode instanceof LoopBeginNode) { + Loop loop = new Loop(block.getLoop(), loopsList.size(), block); + loopsList.add(loop); + + LoopEndNode end = ((LoopBeginNode) beginNode).loopEnd(); + Block endBlock = nodeToBlock.get(end); + computeLoopBlocks(endBlock, loop); + } + } + loops = loopsList.toArray(new Loop[loopsList.size()]); + + for (Loop loop : loops) { + for (Block block : loop.blocks) { + for (Block sux : block.getSuccessors()) { + if (sux.getLoopDepth() < loop.depth) { + loop.exits.add(sux); + } + } + } + } + } + + private void computeLoopBlocks(Block block, Loop loop) { + if (block.getLoop() == loop) { + return; + } + assert block.loop == loop.parent; + block.loop = loop; + + assert !loop.blocks.contains(block); + loop.blocks.add(block); + + if (block != loop.header) { + for (Block pred : block.getPredecessors()) { + computeLoopBlocks(pred, loop); + } + } + } + + private void computeDominators() { + assert reversePostOrder[0].getPredecessors().size() == 0 : "start block has no predecessor and therefore no dominator"; + for (int i = 1; i < reversePostOrder.length; i++) { + Block block = reversePostOrder[i]; + List<Block> predecessors = block.getPredecessors(); + assert predecessors.size() > 0; + + if (block.isLoopHeader()) { + // Loop headers have exactly one non-loop predecessor, and that is the dominator. + setDominator(block, predecessors.get(0)); + continue; + } + + Block dominator = predecessors.get(0); + for (int j = 1; j < predecessors.size(); j++) { + Block pred = predecessors.get(j); + dominator = commonDominator(dominator, pred); + } + setDominator(block, dominator); + } + } + + private static void setDominator(Block block, Block dominator) { + block.dominator = dominator; + if (dominator.dominated == null) { + dominator.dominated = new ArrayList<>(); + } + dominator.dominated.add(block); + } + + public static Block commonDominator(Block a, Block b) { + Block iterA = a; + Block iterB = b; + while (iterA != iterB) { + if (iterA.getId() > iterB.getId()) { + iterA = iterA.getDominator(); + } else { + assert iterB.getId() > iterA.getId(); + iterB = iterB.getDominator(); + } + } + return iterA; + } + + private void computePostdominators() { + for (Block block : reversePostOrder) { + if (block.isLoopEnd()) { + // We do not want the loop header registered as the postdominator of the loop end. + continue; + } + Block postdominator = null; + for (Block sux : block.getSuccessors()) { + if (sux.isExceptionEntry()) { + // We ignore exception handlers. + } else if (postdominator == null) { + postdominator = sux; + } else { + postdominator = commonPostdominator(postdominator, sux); + } + } + block.postdominator = postdominator; + } + } + + private static Block commonPostdominator(Block a, Block b) { + Block iterA = a; + Block iterB = b; + while (iterA != iterB) { + if (iterA.getId() < iterB.getId()) { + iterA = iterA.getPostdominator(); + if (iterA == null) { + return null; + } + } else { + assert iterB.getId() < iterA.getId(); + iterB = iterB.getPostdominator(); + if (iterB == null) { + return null; + } + } + } + return iterA; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.lir/src/com/oracle/max/graal/lir/cfg/Loop.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.lir.cfg; + +import java.util.*; + +public class Loop { + public final Loop parent; + public final List<Loop> children; + + public final int depth; + public final int index; + public final Block header; + public final List<Block> blocks; + public final List<Block> exits; + + protected Loop(Loop parent, int index, Block header) { + this.parent = parent; + if (parent != null) { + this.depth = parent.depth + 1; + parent.children.add(this); + } else { + this.depth = 1; + } + this.index = index; + this.header = header; + this.blocks = new ArrayList<>(); + this.children = new ArrayList<>(); + this.exits = new ArrayList<>(); + } + + @Override + public String toString() { + return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : ""); + } +}
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/type/StampFactory.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/type/StampFactory.java Wed Feb 08 21:15:00 2012 -0800 @@ -173,7 +173,7 @@ RiResolvedType exactType = first.exactType(); while (iterator.hasNext()) { Stamp current = iterator.next().stamp(); - assert current.kind() == first.kind() : values + " first=" + first + " current=" + current; + assert current.kind() == first.kind() : values + " first=" + first + " current=" + current + " first kind=" + first.kind() + " current kind=" + current.kind(); nonNull &= current.nonNull(); declaredType = orTypes(declaredType, current.declaredType()); exactType = orTypes(exactType, current.exactType());
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java Wed Feb 08 21:15:00 2012 -0800 @@ -33,15 +33,15 @@ import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.alloc.*; import com.oracle.max.graal.compiler.alloc.Interval.UsePosList; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.graph.Node.Verbosity; import com.oracle.max.graal.graph.NodeClass.NodeClassIterator; import com.oracle.max.graal.graph.NodeClass.Position; import com.oracle.max.graal.java.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.calc.*; @@ -50,7 +50,6 @@ */ class CFGPrinter extends CompilationPrinter { - public final ByteArrayOutputStream buffer; public final CiTarget target; public final RiRuntime runtime; public LIR lir; @@ -61,9 +60,8 @@ * * @param buffer where the output generated via this printer shown be written */ - public CFGPrinter(ByteArrayOutputStream buffer, CiTarget target, RiRuntime runtime) { - super(buffer); - this.buffer = buffer; + public CFGPrinter(OutputStream out, CiTarget target, RiRuntime runtime) { + super(out); this.target = target; this.runtime = runtime; } @@ -347,22 +345,6 @@ begin("IR"); out.println("LIR"); - if (block.phis != null) { - CiValue[] results = block.phis.results(); - for (int i = 0; i < results.length; i++) { - if (i == 0) { - out.printf("nr %4d ", block.getFirstLirInstructionId()).print(COLUMN_END); - } - out.print("instruction PHI ").print(results[i].toString()).print(" = ("); - String sep = ""; - for (Block pred : block.getPredecessors()) { - out.print(sep).print(block.phis.inputs(pred)[i].toString()); - sep = ", "; - } - out.print(")").print(COLUMN_END).println(COLUMN_END); - } - } - for (int i = 0; i < lirInstructions.size(); i++) { LIRInstruction inst = lirInstructions.get(i); out.printf("nr %4d ", inst.id()).print(COLUMN_END);
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java Wed Feb 08 21:15:00 2012 -0800 @@ -27,118 +27,98 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -import com.oracle.max.criutils.*; import com.oracle.max.graal.alloc.util.*; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.alloc.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.schedule.*; -import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.debug.*; import com.oracle.max.graal.java.*; +import com.oracle.max.graal.lir.*; import com.oracle.max.graal.nodes.*; /** * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the <a * href="http://java.net/projects/c1visualizer/">C1 Visualizer</a>. */ -public class CFGPrinterObserver implements CompilationObserver { +public class CFGPrinterObserver implements DebugDumpHandler { + + private CFGPrinter cfgPrinter; - /** - * A thread local stack of {@link CFGPrinter}s to support thread-safety and re-entrant compilation. - */ - private ThreadLocal<LinkedList<CFGPrinter>> observations = new ThreadLocal<LinkedList<CFGPrinter>>() { - @Override - protected java.util.LinkedList<CFGPrinter> initialValue() { - return new LinkedList<>(); - } - }; + private GraalCompiler compiler; + private RiResolvedMethod method; + private SchedulePhase schedule; @Override - public void compilationStarted(CompilationEvent event) { - if (TTY.isSuppressed()) { + public void dump(final Object object, final String message) { + Debug.sandbox("CFGPrinter", new Runnable() { + @Override + public void run() { + dumpSandboxed(object, message); + } + }); + } + + private void dumpSandboxed(final Object object, final String message) { + if (object instanceof GraalCompiler) { + compiler = (GraalCompiler) object; + return; + } else if (object instanceof SchedulePhase) { + schedule = (SchedulePhase) object; + return; + } else if (object instanceof LIRGenerator) { + cfgPrinter.lirGenerator = (LIRGenerator) object; return; } - RiRuntime runtime = event.debugObject(RiRuntime.class); - CiTarget target = event.debugObject(CiTarget.class); - CFGPrinter cfgPrinter = new CFGPrinter(new ByteArrayOutputStream(), target, runtime); - cfgPrinter.printCompilation(event.debugObject(RiResolvedMethod.class)); - observations.get().push(cfgPrinter); - } - - @Override - public void compilationEvent(CompilationEvent event) { - if (TTY.isSuppressed()) { - return; - } - CFGPrinter cfgPrinter = observations.get().peek(); if (cfgPrinter == null) { - return; + File file = new File("compilations-" + System.currentTimeMillis() + ".cfg"); + try { + OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + cfgPrinter = new CFGPrinter(out, compiler.target, compiler.runtime); + } catch (FileNotFoundException e) { + throw new InternalError("Could not open " + file.getAbsolutePath()); + } } RiRuntime runtime = cfgPrinter.runtime; - if (event.debugObject(LIR.class) != null) { - cfgPrinter.lir = event.debugObject(LIR.class); - } - if (event.debugObject(LIRGenerator.class) != null) { - cfgPrinter.lirGenerator = event.debugObject(LIRGenerator.class); + if (object instanceof RiResolvedMethod) { + method = (RiResolvedMethod) object; + cfgPrinter.printCompilation(method); + + cfgPrinter.lir = null; + cfgPrinter.lirGenerator = null; + schedule = null; + + } else if (object instanceof BciBlockMapping) { + BciBlockMapping blockMap = (BciBlockMapping) object; + cfgPrinter.printCFG(message, blockMap); + cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method)); + + } else if (object instanceof LIR) { + cfgPrinter.lir = (LIR) object; + cfgPrinter.printCFG(message, ((LIR) object).codeEmittingOrder(), schedule); + + } else if (object instanceof StructuredGraph) { + SchedulePhase curSchedule = schedule; + if (curSchedule == null) { + try { + curSchedule = new SchedulePhase(); + curSchedule.apply((StructuredGraph) object); + } catch (Throwable ex) { + // ignore + } + } + cfgPrinter.printCFG(message, Arrays.asList(curSchedule.getCFG().getBlocks()), curSchedule); + + } else if (object instanceof CiTargetMethod) { + cfgPrinter.printMachineCode(runtime.disassemble((CiTargetMethod) object), null); + } else if (object instanceof Interval[]) { + cfgPrinter.printIntervals(message, (Interval[]) object); + } else if (object instanceof IntervalPrinter.Interval[]) { + cfgPrinter.printIntervals(message, (IntervalPrinter.Interval[]) object); } - BciBlockMapping blockMap = event.debugObject(BciBlockMapping.class); - Graph graph = event.debugObject(Graph.class); - SchedulePhase schedule = event.debugObject(SchedulePhase.class); - LinearScan allocator = event.debugObject(LinearScan.class); - Interval[] intervals = event.debugObject(Interval[].class); - IntervalPrinter.Interval[] printIntervals = event.debugObject(IntervalPrinter.Interval[].class); - CiTargetMethod targetMethod = event.debugObject(CiTargetMethod.class); - - if (blockMap != null) { - cfgPrinter.printCFG(event.label, blockMap); - cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method)); - } - if (cfgPrinter.lir != null) { - cfgPrinter.printCFG(event.label, cfgPrinter.lir.codeEmittingOrder(), schedule); - if (targetMethod != null) { - cfgPrinter.printMachineCode(runtime.disassemble(targetMethod), null); - } - } else if (graph != null) { - if (schedule == null) { - try { - schedule = new SchedulePhase(); - schedule.apply((StructuredGraph) graph); - } catch (Throwable t) { - // nothing to do here... - } - } - cfgPrinter.printCFG(event.label, Arrays.asList(schedule.getCFG().getBlocks()), schedule); - } - if (allocator != null && intervals != null) { - cfgPrinter.printIntervals(event.label, intervals); - } - if (printIntervals != null) { - cfgPrinter.printIntervals(event.label, printIntervals); - } - } - - @Override - public void compilationFinished(CompilationEvent event) { - if (TTY.isSuppressed()) { - return; - } - CFGPrinter cfgPrinter = observations.get().pop(); cfgPrinter.flush(); - - OutputStream stream = CompilationPrinter.globalOut(); - if (stream != null) { - synchronized (stream) { - try { - stream.write(cfgPrinter.buffer.toByteArray()); - stream.flush(); - } catch (IOException e) { - TTY.println("WARNING: Error writing CFGPrinter output: %s", e); - } - } - } } }
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java Wed Feb 08 21:15:00 2012 -0800 @@ -27,13 +27,13 @@ import java.util.Map.Entry; import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.graph.Node.Verbosity; import com.oracle.max.graal.graph.NodeClass.NodeClassIterator; import com.oracle.max.graal.graph.NodeClass.Position; import com.oracle.max.graal.java.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; /**
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinterDumpHandler.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinterDumpHandler.java Wed Feb 08 21:15:00 2012 -0800 @@ -25,6 +25,7 @@ import java.io.*; import java.net.*; import java.util.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.criutils.*; @@ -40,7 +41,7 @@ private static final String DEFAULT_FILE_NAME = "output.igv.xml"; private IdealGraphPrinter printer; - private List<RiResolvedMethod> previousInlineContext = new ArrayList<>(); + private List<String> previousInlineContext = new ArrayList<>(); private String fileName; private String host; private int port; @@ -61,8 +62,6 @@ this.port = port; } - - private void ensureInitialized() { if (!initialized) { initialized = true; @@ -85,7 +84,7 @@ } private void initializeNetworkPrinter() { - try { + try { Socket socket = new Socket(host, port); BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000); printer = new IdealGraphPrinter(stream); @@ -103,26 +102,29 @@ if (printer.isValid()) { // Get all current RiResolvedMethod instances in the context. - List<RiResolvedMethod> inlineContext = Debug.contextSnapshot(RiResolvedMethod.class); + List<String> inlineContext = getInlineContext(); + Debug.contextSnapshot(RiResolvedMethod.class); // Reverse list such that inner method comes after outer method. Collections.reverse(inlineContext); // Check for method scopes that must be closed since the previous dump. for (int i = 0; i < previousInlineContext.size(); ++i) { - if (i >= inlineContext.size() || inlineContext.get(i) != previousInlineContext.get(i)) { + if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) { for (int j = previousInlineContext.size() - 1; j >= i; --j) { - closeMethodScope(); + closeScope(); } + break; } } // Check for method scopes that must be opened since the previous dump. for (int i = 0; i < inlineContext.size(); ++i) { - if (i >= previousInlineContext.size() || inlineContext.get(i) != previousInlineContext.get(i)) { + if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) { for (int j = i; j < inlineContext.size(); ++j) { - openMethodScope(inlineContext.get(j)); + openScope(inlineContext.get(j)); } + break; } } @@ -145,13 +147,25 @@ } } - private void openMethodScope(RiResolvedMethod method) { - printer.beginGroup(CiUtil.format("%H::%n", method), CiUtil.format("%h::%n", method), method, -1); - + private static List<String> getInlineContext() { + List<String> result = new ArrayList<>(); + for (Object o : Debug.context()) { + if (o instanceof RiResolvedMethod) { + RiResolvedMethod method = (RiResolvedMethod) o; + result.add(CiUtil.format("%H::%n", method)); + } else if (o instanceof DebugDumpScope) { + DebugDumpScope debugDumpScope = (DebugDumpScope) o; + result.add(debugDumpScope.getName()); + } + } + return result; } - private void closeMethodScope() { + private void openScope(String name) { + printer.beginGroup(name, name, Debug.contextLookup(RiResolvedMethod.class), -1); + } + + private void closeScope() { printer.endGroup(); - } }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -22,13 +22,13 @@ */ package com.oracle.max.graal.snippets.nodes; -import static com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.*; +import static com.oracle.max.graal.lir.amd64.AMD64Arithmetic.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2Reg; import com.oracle.max.graal.compiler.target.amd64.*; -import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.amd64.AMD64Arithmetic.Op2Reg; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.calc.*; import com.oracle.max.graal.nodes.spi.*; @@ -71,7 +71,7 @@ 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; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } gen.setResult(this, result); }
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java Wed Feb 08 21:15:00 2012 -0800 @@ -28,10 +28,10 @@ import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.target.amd64.*; -import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.*; +import com.oracle.max.graal.lir.amd64.*; +import com.oracle.max.graal.lir.asm.*; public class AMD64MathIntrinsicOp extends AMD64LIRInstruction { public enum Opcode { @@ -57,7 +57,7 @@ case SIN: masm.fsin(asDoubleReg(result), asDoubleReg(input)); break; case COS: masm.fcos(asDoubleReg(result), asDoubleReg(input)); break; case TAN: masm.ftan(asDoubleReg(result), asDoubleReg(input)); break; - default: throw Util.shouldNotReachHere(); + default: throw GraalInternalError.shouldNotReachHere(); } } @@ -68,6 +68,6 @@ } else if (mode == OperandMode.Output && index == 0) { return EnumSet.of(OperandFlag.Register); } - throw Util.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } }
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -52,9 +52,6 @@ } private static class UnresolvedException extends RuntimeException { - /** - * - */ private static final long serialVersionUID = 5215434338750728440L; static {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -26,9 +26,9 @@ import org.junit.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; public class GraphScheduleTest extends GraphTest {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java Wed Feb 08 21:13:35 2012 -0800 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -24,9 +24,9 @@ import org.junit.*; -import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.lir.cfg.*; import com.oracle.max.graal.nodes.*; public class NestedLoopTest extends GraphTest {
--- a/mx/commands.py Wed Feb 08 21:13:35 2012 -0800 +++ b/mx/commands.py Wed Feb 08 21:15:00 2012 -0800 @@ -218,6 +218,57 @@ if len(failed) != 0: mx.abort('DaCapo failures: ' + str(failed)) + + +def scaladacapo(args): + """run one or all Scala DaCapo benchmarks + + Scala DaCapo options are distinguished from VM options by a '@' prefix. + For example, '@--iterations @5' will pass '--iterations 5' to the + DaCapo harness.""" + + numTests = {} + + if len(args) > 0: + level = getattr(sanitycheck.SanityCheckLevel, args[0], None) + if level is not None: + del args[0] + for (bench, ns) in sanitycheck.dacapoScalaSanityWarmup.items(): + if ns[level] > 0: + numTests[bench] = ns[level] + else: + while len(args) != 0 and args[0][0] not in ['-', '@']: + n = 1 + if args[0].isdigit(): + n = int(args[0]) + assert len(args) > 1 and args[1][0] not in ['-', '@'] and not args[1].isdigit() + bm = args[1] + del args[0] + else: + bm = args[0] + + del args[0] + if bm not in sanitycheck.dacapoScalaSanityWarmup.keys(): + mx.abort('unknown benchmark: ' + bm + '\nselect one of: ' + str(sanitycheck.dacapoScalaSanityWarmup.keys())) + numTests[bm] = n + + if len(numTests) is 0: + for bench in sanitycheck.dacapoScalaSanityWarmup.keys(): + numTests[bench] = 1 + + # Extract DaCapo options + dacapoArgs = [(arg[1:]) for arg in args if arg.startswith('@')] + + # The remainder are VM options + vmOpts = [arg for arg in args if not arg.startswith('@')] + + failed = [] + for (test, n) in numTests.items(): + if not sanitycheck.getScalaDacapo(test, n, dacapoArgs).test('graal', opts=vmOpts): + failed.append(test) + + if len(failed) != 0: + mx.abort('Scala DaCapo failures: ' + str(failed)) def _jdk(build='product', create=False): """ @@ -498,7 +549,7 @@ build(['--no-native']) tasks.append(t.stop()) - for vmbuild in ['product', 'fastdebug']: + for vmbuild in ['fastdebug', 'product']: global _vmbuild _vmbuild = vmbuild @@ -571,6 +622,15 @@ if dacapo not in sanitycheck.dacapoSanityWarmup.keys(): mx.abort('Unknown dacapo : ' + dacapo) benchmarks += [sanitycheck.getDacapo(dacapo, sanitycheck.dacapoSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark])] + + if ('scaladacapo' in args or 'all' in args): + benchmarks += sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Benchmark) + else: + dacapos = [a[7:] for a in args if a.startswith('scaladacapo:')] + for dacapo in dacapos: + if dacapo not in sanitycheck.dacapoScalaSanityWarmup.keys(): + mx.abort('Unknown dacapo : ' + dacapo) + benchmarks += [sanitycheck.getScalaDacapo(dacapo, sanitycheck.dacapoScalaSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark])] #Bootstrap if ('bootstrap' in args or 'all' in args): @@ -597,14 +657,29 @@ vmArgs = [a for a in args if a[0] != '@'] sanitycheck.getSPECjvm2008(benchArgs).bench('graal', opts=vmArgs) +def hsdis(args): + """Installs the hsdis library + + This is needed to support HotSpot's assembly dumping features. + By default it installs the Intel syntax version, use the 'att' argument to install AT&T syntax.""" + flavor = 'intel' + if 'att' in args: + flavor = 'att' + build = _vmbuild if _vmSourcesAvailable else 'product' + lib = mx.lib_suffix('hsdis-amd64') + path = join(_jdk(build), 'jre', 'lib', 'amd64', lib) + mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib]) + def mx_init(): _vmbuild = 'product' commands = { 'build': [build, '[-options]'], 'clean': [clean, ''], 'copyrightcheck': [copyrightcheck, ''], + 'hsdis': [hsdis, '[att]'], 'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'], - 'specjvm2008': [specjvm2008, ''], + 'scaladacapo': [scaladacapo, '[[n] benchmark] [VM options|@Scala DaCapo options]'], + 'specjvm2008': [specjvm2008, '[VM options|@specjvm2008 options]'], 'example': [example, '[-v] example names...'], 'gate' : [gate, ''], 'bench' : [bench, '[-vm vm] [-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
--- a/mx/projects Wed Feb 08 21:13:35 2012 -0800 +++ b/mx/projects Wed Feb 08 21:15:00 2012 -0800 @@ -41,6 +41,9 @@ library@DACAPO@path=lib/dacapo-9.12-bach.jar library@DACAPO@urls=http://dfn.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar +library@DACAPO_SCALA@path=lib/dacapo-scala-0.1.0.jar +library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20110908.085753-2.jar + # graal.hotspot project@com.oracle.max.graal.hotspot@subDir=graal project@com.oracle.max.graal.hotspot@sourceDirs=src @@ -57,6 +60,24 @@ project@com.oracle.max.graal.debug@sourceDirs=src project@com.oracle.max.graal.debug@checkstyle=com.oracle.max.graal.graph +# graal.lir +project@com.oracle.max.graal.lir@subDir=graal +project@com.oracle.max.graal.lir@sourceDirs=src +project@com.oracle.max.graal.lir@dependencies=com.oracle.max.asm,com.oracle.max.graal.nodes +project@com.oracle.max.graal.lir@checkstyle=com.oracle.max.graal.graph + +# graal.lir.amd64 +project@com.oracle.max.graal.lir.amd64@subDir=graal +project@com.oracle.max.graal.lir.amd64@sourceDirs=src +project@com.oracle.max.graal.lir.amd64@dependencies=com.oracle.max.graal.lir +project@com.oracle.max.graal.lir.amd64@checkstyle=com.oracle.max.graal.graph + +# graal.alloc +project@com.oracle.max.graal.alloc@subDir=graal +project@com.oracle.max.graal.alloc@sourceDirs=src +project@com.oracle.max.graal.alloc@dependencies=com.oracle.max.graal.lir +project@com.oracle.max.graal.alloc@checkstyle=com.oracle.max.graal.graph + # graal.snippets project@com.oracle.max.graal.snippets@subDir=graal project@com.oracle.max.graal.snippets@sourceDirs=src,test @@ -72,7 +93,7 @@ # graal.compiler project@com.oracle.max.graal.compiler@subDir=graal project@com.oracle.max.graal.compiler@sourceDirs=src -project@com.oracle.max.graal.compiler@dependencies=com.oracle.max.asm,com.oracle.max.graal.nodes +project@com.oracle.max.graal.compiler@dependencies=com.oracle.max.graal.lir.amd64,com.oracle.max.graal.alloc project@com.oracle.max.graal.compiler@checkstyle=com.oracle.max.graal.graph # graal.java
--- a/mx/sanitycheck.py Wed Feb 08 21:13:35 2012 -0800 +++ b/mx/sanitycheck.py Wed Feb 08 21:15:00 2012 -0800 @@ -39,13 +39,28 @@ 'luindex': [0, 0, 5, 10, 10], 'lusearch': [0, 4, 5, 5, 8], 'pmd': [0, 0, 5, 10, 13], - 'sunflow': [0, 0, 5, 10, 15], + 'sunflow': [0, 2, 5, 10, 15], 'tomcat': [0, 0, 5, 10, 15], 'tradebeans': [0, 0, 5, 10, 13], 'tradesoap': [2, 4, 5, 10, 15], 'xalan': [0, 0, 5, 10, 18], } +dacapoScalaSanityWarmup = { + 'actors': [0, 0, 2, 8, 10], + 'apparat': [0, 0, 1, 2, 3], + 'factorie': [0, 0, 2, 5, 5], + 'kiama': [0, 0, 3, 13, 15], + 'scalac': [0, 0, 5, 15, 20], + 'scaladoc': [0, 0, 5, 15, 15], + 'scalap': [0, 0, 5, 15, 20], + 'scalariform':[0, 0, 6, 15, 20], + 'scalatest': [0, 0, 2, 10, 12], + 'scalaxb': [0, 0, 5, 15, 25], + 'specs': [0, 0, 3, 13, 18], + 'tmt': [0, 0, 3, 10, 12] +} + dacapoGateBuildLevels = { 'avrora': ['product', 'fastdebug', 'debug'], 'batik': ['product', 'fastdebug', 'debug'], @@ -63,6 +78,21 @@ 'xalan': ['product', 'fastdebug', 'debug'], } +dacapoScalaGateBuildLevels = { + 'actors': ['product', 'fastdebug', 'debug'], + 'apparat': ['product', 'fastdebug', 'debug'], + 'factorie': ['product', 'fastdebug', 'debug'], + 'kiama': ['product', 'fastdebug', 'debug'], + 'scalac': ['product', 'fastdebug', 'debug'], + 'scaladoc': ['product', 'fastdebug', 'debug'], + 'scalap': ['product', 'fastdebug', 'debug'], + 'scalariform':['product', 'fastdebug', 'debug'], + 'scalatest': ['product', 'fastdebug', 'debug'], + 'scalaxb': ['product', 'fastdebug', 'debug'], + 'specs': ['product', 'fastdebug', 'debug'], + 'tmt': ['product', 'fastdebug', 'debug'], +} + class SanityCheckLevel: Fast, Gate, Normal, Extensive, Benchmark = range(5) @@ -118,6 +148,36 @@ return Test("DaCapo-" + name, "DaCapo", ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:MaxPermSize=256m']) +def getScalaDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]): + checks = [] + + for (bench, ns) in dacapoScalaSanityWarmup.items(): + if ns[level] > 0: + if gateBuildLevel is None or gateBuildLevel in dacapoScalaGateBuildLevels[bench]: + checks.append(getScalaDacapo(bench, ns[level], dacapoArgs)) + + return checks + +def getScalaDacapo(name, n, dacapoArgs=[]): + dacapo = mx.get_env('DACAPO_SCALA_CP') + if dacapo is None: + l = mx.library('DACAPO_SCALA', False) + if l is not None: + dacapo = l.get_path(True) + else: + mx.abort('Scala DaCapo 0.1.0 jar file must be specified with DACAPO_SCALA_CP environment variable or as DACAPO_SCALA library') + + if not isfile(dacapo) or not dacapo.endswith('.jar'): + mx.abort('Specified Scala DaCapo jar file does not exist or is not a jar file: ' + dacapo) + + dacapoSuccess = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) PASSED in ([0-9]+) msec =====$") + dacapoFail = re.compile(r"^===== DaCapo 0\.1\.0(-SNAPSHOT)? ([a-zA-Z0-9_]+) FAILED (warmup|) =====$") + dacapoTime = re.compile(r"===== DaCapo 0\.1\.0(-SNAPSHOT)? (?P<benchmark>[a-zA-Z0-9_]+) PASSED in (?P<time>[0-9]+) msec =====") + + dacapoMatcher = Matcher(dacapoTime, {'const:name' : 'benchmark', 'const:score' : 'time'}) + + return Test("Scala-DaCapo-" + name, "Scala-DaCapo", ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:MaxPermSize=256m']) + def getBootstraps(): time = re.compile(r"Bootstrapping Graal\.+ in (?P<time>[0-9]+) ms") scoreMatcher = Matcher(time, {'const:name' : 'const:BootstrapTime', 'const:score' : 'time'})
--- a/mxtool/mx.py Wed Feb 08 21:13:35 2012 -0800 +++ b/mxtool/mx.py Wed Feb 08 21:15:00 2012 -0800 @@ -648,6 +648,17 @@ return name + '.exe' return name +def lib_suffix(name): + """ + Gets the platform specific suffix for a library + """ + os = get_os(); + if os == 'windows': + return name + '.dll' + if os == 'linux': + return name + '.so' + return name + """ A JavaConfig object encapsulates info on how Java commands are run. """
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Wed Feb 08 21:13:35 2012 -0800 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Wed Feb 08 21:15:00 2012 -0800 @@ -128,8 +128,8 @@ @Override protected Group start() throws SAXException { - Group group = new Group(this.getParentObject()); - + final Group group = new Group(this.getParentObject()); + String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY); Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true")))); @@ -138,12 +138,6 @@ monitor.setState(group.getName()); } - return group; - } - - @Override - protected void end(String text) throws SAXException { - final Group group = getObject(); final Folder parent = getParentObject(); if (groupCallback == null || parent instanceof Group) { SwingUtilities.invokeLater(new Runnable(){ @@ -153,6 +147,12 @@ } }); } + + return group; + } + + @Override + protected void end(String text) throws SAXException { } }; // <method> @@ -270,7 +270,7 @@ graph.addBlockEdge(left, right); } blockConnections.clear(); - + SwingUtilities.invokeLater(new Runnable(){ @Override
--- a/src/share/vm/graal/graalCompilerToVM.cpp Wed Feb 08 21:13:35 2012 -0800 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Wed Feb 08 21:15:00 2012 -0800 @@ -247,7 +247,7 @@ } // public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); -JNIEXPORT jobject JNICALL Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { +JNIEXPORT jobject JNICALL Java_com_oracle_max_graal_hotspot_bridge_CompilerToVMImpl_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve) { TRACE_graal_3("CompilerToVM::RiSignature_lookupType"); VM_ENTRY_MARK; ResourceMark rm; @@ -282,7 +282,11 @@ classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader(); protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain(); } - resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); + if (eagerResolve) { + resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); + } else { + resolved_type = SystemDictionary::find(nameSymbol, classloader, protectionDomain, THREAD); + } if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; resolved_type = NULL; @@ -943,7 +947,7 @@ {CC"RiMethod_invocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(RiMethod_1invocationCount)}, {CC"RiMethod_hasCompiledCode", CC"("RESOLVED_METHOD")Z", FN_PTR(RiMethod_1hasCompiledCode)}, {CC"RiMethod_getCompiledCodeSize", CC"("RESOLVED_METHOD")I", FN_PTR(RiMethod_1getCompiledCodeSize)}, - {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(RiSignature_1lookupType)}, + {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE"Z)"TYPE, FN_PTR(RiSignature_1lookupType)}, {CC"RiConstantPool_lookupConstant", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(RiConstantPool_1lookupConstant)}, {CC"RiConstantPool_lookupMethod", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(RiConstantPool_1lookupMethod)}, {CC"RiConstantPool_lookupType", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(RiConstantPool_1lookupType)},
--- a/src/share/vm/graal/graalVmIds.hpp Wed Feb 08 21:13:35 2012 -0800 +++ b/src/share/vm/graal/graalVmIds.hpp Wed Feb 08 21:15:00 2012 -0800 @@ -72,7 +72,7 @@ } inline Symbol* VmIds::toSymbol(jstring string) { - return java_lang_String::as_symbol_or_null(JNIHandles::resolve(string)); + return java_lang_String::as_symbol(JNIHandles::resolve(string), Thread::current()); } inline jlong VmIds::getBoxedLong(oop obj) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.svg" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.svg.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.svg +OpenIDE-Module-Layer: com/sun/hotspot/igv/svg/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/svg/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.svg-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +# 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=ebcf0422 +nbproject/build-impl.xml.script.CRC32=42ef3ff6 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.svg</code-name-base> + <suite-component/> + <module-dependencies/> + <public-packages> + <package>com.sun.hotspot.igv.svg</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.svg; + +import java.awt.Graphics2D; +import java.io.Writer; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import org.w3c.dom.DOMImplementation; + +/** + * Utility class + * @author Thomas Wuerthinger + */ +public class BatikSVG { + + private BatikSVG() { + } + + private static Constructor SVGGraphics2DConstructor; + private static Method streamMethod; + private static Method createDefaultMethod; + private static Method getDOMImplementationMethod; + private static Method setEmbeddedFontsOnMethod; + private static Class<?> classSVGGraphics2D; + + /** + * Creates a graphics object that allows to be exported to SVG data using the {@link #printToStream(Graphics2D, Writer, boolean) printToStream} method. + * @return the newly created Graphics2D object or null if the library does not exist + */ + public static Graphics2D createGraphicsObject() { + try { + if (SVGGraphics2DConstructor == null) { + ClassLoader cl = BatikSVG.class.getClassLoader(); + Class<?> classGenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation"); + Class<?> classSVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext"); + classSVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D"); + getDOMImplementationMethod = classGenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]); + createDefaultMethod = classSVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class}); + setEmbeddedFontsOnMethod = classSVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class}); + streamMethod = classSVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class); + SVGGraphics2DConstructor = classSVGGraphics2D.getConstructor(classSVGGeneratorContext, boolean.class); + } + DOMImplementation dom = (DOMImplementation) getDOMImplementationMethod.invoke(null); + org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null); + Object ctx = createDefaultMethod.invoke(null, document); + setEmbeddedFontsOnMethod.invoke(ctx, true); + Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true); + return svgGenerator; + } catch (ClassNotFoundException e) { + return null; + } catch (NoSuchMethodException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } catch (InvocationTargetException e) { + return null; + } catch (InstantiationException e) { + return null; + } + } + + /** + * Serializes a graphics object to a stream in SVG format. + * @param svgGenerator the graphics object. Only graphics objects created by the {@link #createGraphicsObject() createGraphicsObject} method are valid. + * @param stream the stream to which the data is written + * @param useCSS whether to use CSS styles in the SVG output + */ + public static void printToStream(Graphics2D svgGenerator, Writer stream, boolean useCSS) { + assert classSVGGraphics2D != null; + assert classSVGGraphics2D.isInstance(svgGenerator); + try { + streamMethod.invoke(svgGenerator, stream, useCSS); + } catch (IllegalAccessException e) { + assert false; + } catch (InvocationTargetException e) { + assert false; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=BatikSVGProxy
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/package-info.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008, 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. + * + */ +/** + * This package is used to proxy the SVG export functionality of the BatikSVG library. Reflection is used such that the + * library is optional and need not be present at build time. + */ +package com.sun.hotspot.igv.svg; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.bytecodes" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.bytecodes.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.bytecodes +OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.bytecodes-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=1dee290d +build.xml.script.CRC32=d594034f +build.xml.stylesheet.CRC32=79c3b980 +# 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=1dee290d +nbproject/build-impl.xml.script.CRC32=b4dab126 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.bytecodes</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.graph</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.jdesktop.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.16.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.explorer</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.34.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.nodes</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.14.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.39.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages/> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +CTL_BytecodeViewAction=Bytecode +CTL_BytecodeViewTopComponent=Bytecode +CTL_SelectBytecodesAction=Select nodes +HINT_BytecodeViewTopComponent=Shows the bytecode associated with the displayed graph. +OpenIDE-Module-Name=Bytecodes
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.bytecodes; + +import com.sun.hotspot.igv.data.InputBytecode; +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.data.InputNode; +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher; +import java.awt.Image; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import javax.swing.Action; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; + +/** + * + * @author Thomas Wuerthinger + */ +public class BytecodeNode extends AbstractNode { + + private Set<InputNode> nodes; + + public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) { + + super(Children.LEAF); + this.setDisplayName(bytecode.getBci() + " " + bytecode.getName()); + + bciValue = bytecode.getBci() + " " + bciValue; + bciValue = bciValue.trim(); + + Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(graph.getNodes()); + StringPropertyMatcher matcher = new StringPropertyMatcher("bci", bciValue); + List<InputNode> nodeList = selector.selectMultiple(matcher); + if (nodeList.size() > 0) { + nodes = new LinkedHashSet<>(); + for (InputNode n : nodeList) { + nodes.add(n); + } + this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)"); + } + } + + @Override + public Image getIcon(int i) { + if (nodes != null) { + return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.png"); + } else { + return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.png"); + } + } + + @Override + public Image getOpenedIcon(int i) { + return getIcon(i); + } + + @Override + public Action[] getActions(boolean b) { + return new Action[]{(Action) SelectBytecodesAction.findObject(SelectBytecodesAction.class, true)}; + } + + @Override + public Action getPreferredAction() { + return (Action) SelectBytecodesAction.findObject(SelectBytecodesAction.class, true); + } + + @Override + @SuppressWarnings("unchecked") + public <T extends Node.Cookie> T getCookie(Class<T> aClass) { + if (aClass == SelectBytecodesCookie.class && nodes != null) { + return (T) (new SelectBytecodesCookie(nodes)); + } + return super.getCookie(aClass); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.bytecodes; + +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; + +/** + * @author Thomas Wuerthinger + */ +public class BytecodeViewAction extends AbstractAction { + + public BytecodeViewAction() { + super(NbBundle.getMessage(BytecodeViewAction.class, "CTL_BytecodeViewAction")); + } + + @Override + public void actionPerformed(ActionEvent evt) { + TopComponent win = BytecodeViewTopComponent.findInstance(); + win.open(); + win.requestActive(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="400" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="300" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + </Layout> +</Form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.bytecodes; + +import com.sun.hotspot.igv.data.Group; +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.data.services.InputGraphProvider; +import java.awt.BorderLayout; +import java.io.Serializable; +import javax.swing.SwingUtilities; +import org.openide.ErrorManager; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; +import org.openide.explorer.view.BeanTreeView; +import org.openide.util.*; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; + +/** + * @author Thomas Wuerthinger + */ +final class BytecodeViewTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener { + + private static BytecodeViewTopComponent instance; + private static final String PREFERRED_ID = "BytecodeViewTopComponent"; + private ExplorerManager manager; + private BeanTreeView treeView; + private Lookup.Result result = null; + private MethodNode rootNode; + + private BytecodeViewTopComponent() { + initComponents(); + setName(NbBundle.getMessage(BytecodeViewTopComponent.class, "CTL_BytecodeViewTopComponent")); + setToolTipText(NbBundle.getMessage(BytecodeViewTopComponent.class, "HINT_BytecodeViewTopComponent")); + + manager = new ExplorerManager(); + rootNode = new MethodNode(null, null, ""); + manager.setRootContext(rootNode); + + setLayout(new BorderLayout()); + + treeView = new BeanTreeView(); + treeView.setRootVisible(false); + this.add(BorderLayout.CENTER, treeView); + associateLookup(ExplorerUtils.createLookup(manager, getActionMap())); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents + private void initComponents() { + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(0, 300, Short.MAX_VALUE) + ); + }// </editor-fold>//GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link findInstance}. + */ + public static synchronized BytecodeViewTopComponent getDefault() { + if (instance == null) { + instance = new BytecodeViewTopComponent(); + } + return instance; + } + + /** + * Obtain the BytecodeViewTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized BytecodeViewTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find BytecodeView component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof BytecodeViewTopComponent) { + return (BytecodeViewTopComponent) win; + } + ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + public void componentOpened() { + Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<>(InputGraphProvider.class); + result = Utilities.actionsGlobalContext().lookup(tpl); + result.addLookupListener(this); + } + + @Override + public void componentClosed() { + result.removeLookupListener(this); + result = null; + } + + @Override + public Object writeReplace() { + return new ResolvableHelper(); + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + @Override + public ExplorerManager getExplorerManager() { + return manager; + } + + @Override + public void requestActive() { + super.requestActive(); + this.treeView.requestFocus(); + } + + @Override + public boolean requestFocus(boolean temporary) { + this.treeView.requestFocus(); + return super.requestFocus(temporary); + } + + @Override + protected boolean requestFocusInWindow(boolean temporary) { + this.treeView.requestFocus(); + return super.requestFocusInWindow(temporary); + } + + @Override + public void resultChanged(LookupEvent lookupEvent) { + final InputGraphProvider p = null; // TODO(tw): FIXME //.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class); + if (p != null) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + InputGraph graph = p.getGraph(); + if (graph != null) { + Group g = graph.getGroup(); + rootNode.update(graph, g.getMethod()); + } + } + }); + } + } + + final static class ResolvableHelper implements Serializable { + + private static final long serialVersionUID = 1L; + + public Object readResolve() { + return BytecodeViewTopComponent.getDefault(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd"> +<settings version="1.0"> + <module name="com.sun.hotspot.igv.bytecodes" spec="1.0"/> + <instanceof class="org.openide.windows.TopComponent"/> + <instanceof class="com.sun.hotspot.igv.bytecodes.BytecodeViewTopComponent"/> + <instance class="com.sun.hotspot.igv.bytecodes.BytecodeViewTopComponent" method="getDefault"/> +</settings>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-ref2_0.dtd"> +<tc-ref version="2.0" > + <module name="com.sun.hotspot.igv.bytecodes" spec="1.0"/> + <tc-id id="BytecodeViewTopComponent"/> + <state opened="true"/> +</tc-ref>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.bytecodes; + +import com.sun.hotspot.igv.data.InputBytecode; +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.data.InputMethod; +import java.awt.Image; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; + +/** + * + * @author Thomas Wuerthinger + */ +public class MethodNode extends AbstractNode { + + private static class MethodNodeChildren extends Children.Keys<InputBytecode> { + + private InputMethod method; + private InputGraph graph; + private String bciString; + + public MethodNodeChildren(InputMethod method, InputGraph graph, String bciString) { + this.method = method; + this.bciString = bciString; + this.graph = graph; + } + + @Override + protected Node[] createNodes(InputBytecode bc) { + if (bc.getInlined() == null) { + return new Node[]{new BytecodeNode(bc, graph, bciString)}; + } else { + return new Node[]{new BytecodeNode(bc, graph, bciString), new MethodNode(bc.getInlined(), graph, bc.getBci() + " " + bciString)}; + } + } + + @Override + public void addNotify() { + if (method != null) { + setKeys(method.getBytecodes()); + } + } + + public void setMethod(InputMethod method, InputGraph graph) { + this.method = method; + this.graph = graph; + addNotify(); + } + } + + /** Creates a new instance of MethodNode */ + public MethodNode(InputMethod method, InputGraph graph, String bciString) { + super((method != null && method.getBytecodes().size() == 0) ? Children.LEAF : new MethodNodeChildren(method, graph, bciString)); + if (method != null) { + this.setDisplayName(method.getName()); + } + } + + @Override + public Image getIcon(int i) { + return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.png"); + } + + @Override + public Image getOpenedIcon(int i) { + return getIcon(i); + } + + public void update(InputGraph graph, InputMethod method) { + ((MethodNodeChildren) this.getChildren()).setMethod(method, graph); + if (method != null) { + this.setDisplayName(method.getName()); + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.bytecodes; + +import com.sun.hotspot.igv.data.services.InputGraphProvider; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CookieAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class SelectBytecodesAction extends CookieAction { + + @Override + protected void performAction(Node[] activatedNodes) { + SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class); + InputGraphProvider p = null; // TODO: fixme LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class); + if (p != null) { + p.setSelectedNodes(c.getNodes()); + } + } + + @Override + protected int mode() { + return CookieAction.MODE_EXACTLY_ONE; + } + + @Override + public String getName() { + return NbBundle.getMessage(SelectBytecodesAction.class, "CTL_SelectBytecodesAction"); + } + + @Override + protected Class[] cookieClasses() { + return new Class[]{ + SelectBytecodesCookie.class + }; + } + + @Override + protected void initialize() { + super.initialize(); + putValue("noIconInMenu", Boolean.TRUE); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.bytecodes; + +import com.sun.hotspot.igv.data.InputNode; +import java.util.Collections; +import java.util.Set; +import org.openide.nodes.Node; + +/** + * + * @author Thomas Wuerthinger + */ +public class SelectBytecodesCookie implements Node.Cookie { + + private Set<InputNode> nodes; + + /** Creates a new instance of SelectBytecodesCookie */ + public SelectBytecodesCookie(Set<InputNode> nodes) { + this.nodes = nodes; + } + + public Set<InputNode> getNodes() { + return Collections.unmodifiableSet(nodes); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <folder name="Actions"> + <folder name="Edit"> + <file name="com-sun-hotspot-igv-bytecodes-SelectBytecodesAction.instance"/> + </folder> + <folder name="Window"> + <file name="com-sun-hotspot-igv-bytecodes-BytecodeViewAction.instance"/> + </folder> + </folder> + <folder name="Menu"> + <folder name="Window"> + <file name="BytecodeViewAction.shadow"> + <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-bytecodes-BytecodeViewAction.instance"/> + </file> + </folder> + </folder> + <folder name="Windows2"> + <folder name="Components"> + <file name="BytecodeViewTopComponent.settings" url="BytecodeViewTopComponentSettings.xml"/> + </folder> + <folder name="Modes"> + <folder name="customRightTopMode"> + <file name="BytecodeViewTopComponent.wstcref" url="BytecodeViewTopComponentWstcref.xml"/> + </folder> + </folder> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="at.ssw.visualizer.cfg" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project at.ssw.visualizer.cfg.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: at.ssw.visualizer.cfg +OpenIDE-Module-Layer: at/ssw/visualizer/cfg/layer.xml +OpenIDE-Module-Localizing-Bundle: at/ssw/visualizer/cfg/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="at.ssw.visualizer.cfg-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=d86dea19 +build.xml.script.CRC32=ec651852 +build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 +# 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=d86dea19 +nbproject/build-impl.xml.script.CRC32=d9cb852b +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,204 @@ +cluster.path=\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + com.jcraft.jsch,\ + com.jcraft.jzlib,\ + org.apache.commons.codec,\ + org.apache.commons.httpclient,\ + org.apache.commons.io,\ + org.apache.commons.lang,\ + org.apache.commons.logging,\ + org.apache.ws.commons.util,\ + org.apache.xml.resolver,\ + org.apache.xmlrpc,\ + org.eclipse.core.contenttype,\ + org.eclipse.core.jobs,\ + org.eclipse.core.net,\ + org.eclipse.core.runtime,\ + org.eclipse.core.runtime.compatibility.auth,\ + org.eclipse.equinox.app,\ + org.eclipse.equinox.common,\ + org.eclipse.equinox.preferences,\ + org.eclipse.equinox.registry,\ + org.eclipse.equinox.security,\ + org.eclipse.jgit,\ + org.eclipse.mylyn.bugzilla.core,\ + org.eclipse.mylyn.commons.core,\ + org.eclipse.mylyn.commons.net,\ + org.eclipse.mylyn.commons.xmlrpc,\ + org.eclipse.mylyn.tasks.core,\ + org.mozilla.rhino.patched,\ + org.netbeans.api.debugger,\ + org.netbeans.api.java.classpath,\ + org.netbeans.api.xml,\ + org.netbeans.core.browser,\ + org.netbeans.core.execution,\ + org.netbeans.core.ide,\ + org.netbeans.core.io.ui,\ + org.netbeans.core.multiview,\ + org.netbeans.core.nativeaccess,\ + org.netbeans.core.osgi,\ + org.netbeans.lib.cvsclient,\ + org.netbeans.lib.terminalemulator,\ + org.netbeans.libs.antlr3.runtime,\ + org.netbeans.libs.bytelist,\ + org.netbeans.libs.commons_net,\ + org.netbeans.libs.freemarker,\ + org.netbeans.libs.git,\ + org.netbeans.libs.ini4j,\ + org.netbeans.libs.jaxb,\ + org.netbeans.libs.jsr223,\ + org.netbeans.libs.junit4,\ + org.netbeans.libs.jvyamlb,\ + org.netbeans.libs.lucene,\ + org.netbeans.libs.smack,\ + org.netbeans.libs.svnClientAdapter,\ + org.netbeans.libs.svnClientAdapter.javahl,\ + org.netbeans.libs.svnClientAdapter.svnkit,\ + org.netbeans.libs.swingx,\ + org.netbeans.libs.xerces,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.bugtracking,\ + org.netbeans.modules.bugtracking.bridge,\ + org.netbeans.modules.bugzilla,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.csl.api,\ + org.netbeans.modules.css.editor,\ + org.netbeans.modules.css.lib,\ + org.netbeans.modules.css.visual,\ + org.netbeans.modules.db,\ + org.netbeans.modules.db.core,\ + org.netbeans.modules.db.dataview,\ + org.netbeans.modules.db.drivers,\ + org.netbeans.modules.db.kit,\ + org.netbeans.modules.db.metadata.model,\ + org.netbeans.modules.db.mysql,\ + org.netbeans.modules.db.sql.editor,\ + org.netbeans.modules.db.sql.visualeditor,\ + org.netbeans.modules.dbapi,\ + org.netbeans.modules.defaults,\ + org.netbeans.modules.derby,\ + org.netbeans.modules.dlight.nativeexecution,\ + org.netbeans.modules.dlight.terminal,\ + org.netbeans.modules.editor.bookmarks,\ + org.netbeans.modules.editor.bracesmatching,\ + org.netbeans.modules.editor.codetemplates,\ + org.netbeans.modules.editor.completion,\ + org.netbeans.modules.editor.guards,\ + org.netbeans.modules.editor.indent.project,\ + org.netbeans.modules.editor.kit,\ + org.netbeans.modules.editor.macros,\ + org.netbeans.modules.editor.structure,\ + org.netbeans.modules.extbrowser,\ + org.netbeans.modules.extexecution,\ + org.netbeans.modules.extexecution.destroy,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.git,\ + org.netbeans.modules.glassfish.common,\ + org.netbeans.modules.gototest,\ + org.netbeans.modules.gsf.codecoverage,\ + org.netbeans.modules.gsf.testrunner,\ + org.netbeans.modules.html,\ + org.netbeans.modules.html.editor,\ + org.netbeans.modules.html.editor.lib,\ + org.netbeans.modules.html.lexer,\ + org.netbeans.modules.html.parser,\ + org.netbeans.modules.html.validation,\ + org.netbeans.modules.httpserver,\ + org.netbeans.modules.hudson,\ + org.netbeans.modules.hudson.git,\ + org.netbeans.modules.hudson.mercurial,\ + org.netbeans.modules.hudson.subversion,\ + org.netbeans.modules.hudson.tasklist,\ + org.netbeans.modules.ide.kit,\ + org.netbeans.modules.image,\ + org.netbeans.modules.javascript.editing,\ + org.netbeans.modules.javascript.hints,\ + org.netbeans.modules.javascript.kit,\ + org.netbeans.modules.javascript.refactoring,\ + org.netbeans.modules.jellytools.ide,\ + org.netbeans.modules.jumpto,\ + org.netbeans.modules.keyring.impl,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.languages.diff,\ + org.netbeans.modules.languages.manifest,\ + org.netbeans.modules.languages.yaml,\ + org.netbeans.modules.lexer.nbbridge,\ + org.netbeans.modules.localhistory,\ + org.netbeans.modules.mercurial,\ + org.netbeans.modules.netbinox,\ + org.netbeans.modules.parsing.api,\ + org.netbeans.modules.parsing.lucene,\ + org.netbeans.modules.print.editor,\ + org.netbeans.modules.project.ant,\ + org.netbeans.modules.project.libraries,\ + org.netbeans.modules.projectui,\ + org.netbeans.modules.projectui.buildmenu,\ + org.netbeans.modules.projectuiapi,\ + org.netbeans.modules.properties,\ + org.netbeans.modules.properties.syntax,\ + org.netbeans.modules.refactoring.api,\ + org.netbeans.modules.schema2beans,\ + org.netbeans.modules.server,\ + org.netbeans.modules.servletapi,\ + org.netbeans.modules.spellchecker,\ + org.netbeans.modules.spellchecker.apimodule,\ + org.netbeans.modules.spellchecker.bindings.htmlxml,\ + org.netbeans.modules.spellchecker.bindings.properties,\ + org.netbeans.modules.spellchecker.dictionary_en,\ + org.netbeans.modules.spellchecker.kit,\ + org.netbeans.modules.spi.actions,\ + org.netbeans.modules.subversion,\ + org.netbeans.modules.swing.validation,\ + org.netbeans.modules.target.iterator,\ + org.netbeans.modules.tasklist.kit,\ + org.netbeans.modules.tasklist.projectint,\ + org.netbeans.modules.tasklist.todo,\ + org.netbeans.modules.tasklist.ui,\ + org.netbeans.modules.terminal,\ + org.netbeans.modules.usersguide,\ + org.netbeans.modules.utilities,\ + org.netbeans.modules.utilities.project,\ + org.netbeans.modules.versioning,\ + org.netbeans.modules.versioning.indexingbridge,\ + org.netbeans.modules.versioning.system.cvss.installer,\ + org.netbeans.modules.versioning.util,\ + org.netbeans.modules.web.client.tools.api,\ + org.netbeans.modules.web.common,\ + org.netbeans.modules.web.indent,\ + org.netbeans.modules.xml,\ + org.netbeans.modules.xml.axi,\ + org.netbeans.modules.xml.catalog,\ + org.netbeans.modules.xml.core,\ + org.netbeans.modules.xml.jaxb.api,\ + org.netbeans.modules.xml.lexer,\ + org.netbeans.modules.xml.multiview,\ + org.netbeans.modules.xml.retriever,\ + org.netbeans.modules.xml.schema.completion,\ + org.netbeans.modules.xml.schema.model,\ + org.netbeans.modules.xml.tax,\ + org.netbeans.modules.xml.text,\ + org.netbeans.modules.xml.tools,\ + org.netbeans.modules.xml.wsdl.model,\ + org.netbeans.modules.xml.xam,\ + org.netbeans.modules.xml.xdm,\ + org.netbeans.modules.xsl,\ + org.netbeans.spi.debugger.ui,\ + org.netbeans.spi.editor.hints,\ + org.netbeans.spi.navigator,\ + org.netbeans.spi.palette,\ + org.netbeans.spi.tasklist,\ + org.netbeans.spi.viewmodel,\ + org.netbeans.swing.dirchooser,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.options,\ + org.openide.util.enumerations +## Not disabled because of NetBeans bug 206347: +## Applications not using OSGi don't start on NbP 7.1 +# org.netbeans.core.netigso,\ +# org.netbeans.libs.felix,\ +# org.netbeans.libs.osgi,\ +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>at.ssw.visualizer.cfg</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.oracle.graal.visualizer.editor</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.oracle.graal.visualizer.sharedactions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.eclipse.draw2d</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.jdesktop.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.4.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.api.visual</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>2.9.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.modules.options.api</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.5</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.modules.projectapi</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.40.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.actions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.6.1.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.11.1.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.dialogs</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.5</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.loaders</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.5</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.nodes</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.2.0.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.9.0.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.3.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.16</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>at.ssw.visualizer.cfg</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +at.ssw.visualizer.cfg.CfgCompilationViewerFactory \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=ControlFlowEditor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,235 @@ +/* + * 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 at.ssw.visualizer.cfg; + +import at.ssw.visualizer.cfg.action.*; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.graph.NodeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.preferences.FlagsSetting; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import com.oracle.graal.visualizer.editor.CompilationViewer; +import com.sun.hotspot.igv.data.InputGraph; +import java.awt.Color; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import javax.swing.*; +import javax.swing.border.Border; +import org.netbeans.api.visual.widget.Widget; +import org.openide.awt.Toolbar; +import org.openide.util.Lookup; +import org.openide.util.actions.SystemAction; +import org.openide.util.lookup.Lookups; + +class CfgCompilationViewer implements CompilationViewer { + + private CfgScene scene; + private JScrollPane jScrollPane; + private ControlFlowGraph cfg; + private JComponent myView; + + public CfgCompilationViewer(InputGraph cfg) { + this.cfg = cfg; + + // setIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg.gif")); +// setName(cfg.getParent().getShortName()); +// setToolTipText(cfg.getCompilation().getMethod() + " - " + cfg.getName()); + // TODO(tw): Add title. + + //panel setup + this.jScrollPane = new JScrollPane(); + this.jScrollPane.setOpaque(true); + this.jScrollPane.setBorder(BorderFactory.createEmptyBorder()); + this.jScrollPane.setViewportBorder(BorderFactory.createEmptyBorder()); + this.scene = new CfgScene(jScrollPane, cfg); + this.myView = scene.createView(); + this.jScrollPane.setViewportView(myView); + jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + jScrollPane.getVerticalScrollBar().setEnabled(true); + jScrollPane.getHorizontalScrollBar().setEnabled(true); + + //setup enviroment,register listeners + // TODO(tw): Add to lookup. +// selection = new Selection(); +// selection.put(cfg); +// selection.put(scene); +// selection.addChangeListener(scene); + + scene.validate(); + scene.applyLayout(); + } + + public void propertyChange(PropertyChangeEvent evt) { + if (this.scene != null) { + + String propName = evt.getPropertyName(); + CfgPreferences prefs = CfgPreferences.getInstance(); + switch (propName) { + case CfgPreferences.PROP_BACKGROUND_COLOR: + scene.setBackground(prefs.getBackgroundColor()); + scene.revalidate(); + break; + case CfgPreferences.PROP_NODE_COLOR: + for (NodeWidget nw : scene.getNodeWidgets()) { + //only change the node color if its not a custom color + if (!nw.isNodeColorCustomized()) { + nw.setNodeColor(prefs.getNodeColor(), false); + } + } + break; + case CfgPreferences.PROP_EDGE_COLOR: + for (CfgEdge e : scene.getEdges()) { + if (!e.isBackEdge() && !e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getEdgeColor()); + } + } + break; + case CfgPreferences.PROP_BACK_EDGE_COLOR: + for (CfgEdge e : scene.getEdges()) { + if (e.isBackEdge()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getBackedgeColor()); + } + } + break; + case CfgPreferences.PROP_EXCEPTION_EDGE_COLOR: + for (CfgEdge e : scene.getEdges()) { + if (e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getExceptionEdgeColor()); + } + } + break; + case CfgPreferences.PROP_BORDER_COLOR: + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setBorderColor(prefs.getBorderColor()); + } + break; + case CfgPreferences.PROP_TEXT_FONT: + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.adjustFont(prefs.getTextFont()); + } + break; + case CfgPreferences.PROP_TEXT_COLOR: + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setForeground(prefs.getTextColor()); + } + break; + case CfgPreferences.PROP_FLAGS: + FlagsSetting fs = CfgPreferences.getInstance().getFlagsSetting(); + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + Color nodeColor = fs.getColor(n.getBasicBlock().getFlags()); + if (nodeColor != null) { + nw.setNodeColor(nodeColor, true); + } else { + nw.setNodeColor(CfgPreferences.getInstance().getNodeColor(), false); + } + } + break; + case CfgPreferences.PROP_SELECTION_COLOR_BG: + case CfgPreferences.PROP_SELECTION_COLOR_FG: + for (CfgNode n : scene.getNodes()) { + Widget w = scene.findWidget(n); + w.revalidate(); + } + break; + } + scene.validate(); + } + + } + + /*@Override + public Component getToolBarComponent() { + Toolbar tb = new Toolbar("CfgToolbar"); + + tb.setBorder((Border) UIManager.get("Nb.Editor.Toolbar.border")); + + //zoomin/zoomout buttons + tb.add(SystemAction.get(ZoominAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(ZoomoutAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //router buttons + ButtonGroup routerButtons = new ButtonGroup(); + UseDirectLineRouterAction direct = SystemAction.get(UseDirectLineRouterAction.class); + UseBezierRouterAction bezier = SystemAction.get(UseBezierRouterAction.class); + JToggleButton button = (JToggleButton) direct.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + button.setSelected(true); + tb.add(button); + button = (JToggleButton) bezier.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + tb.add(button); + tb.addSeparator(); + + //layout buttons + tb.add(SystemAction.get(HierarchicalNodeLayoutAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HierarchicalCompoundLayoutAction.class).getToolbarPresenter()); + + tb.addSeparator(); + tb.add(SystemAction.get(ShowAllAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //cluster button + tb.add(SystemAction.get(SwitchLoopClustersAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //show/hide edge button + tb.add(SystemAction.get(ShowEdgesAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HideEdgesAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //color button + JComponent colorButton = SystemAction.get(ColorAction.class).getToolbarPresenter(); + scene.addCfgEventListener((CfgEventListener) colorButton); + tb.add(colorButton); + + //export button + tb.add(SystemAction.get(ExportAction.class).getToolbarPresenter()); + tb.doLayout(); + + return tb; + }*/ + + @Override + public Lookup getLookup() { + return Lookups.fixed(scene); + } + + @Override + public Component getComponent() { + return jScrollPane; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewerFactory.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,26 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.ssw.visualizer.cfg; + +import com.oracle.graal.visualizer.editor.CompilationViewer; +import com.oracle.graal.visualizer.editor.CompilationViewerFactory; +import com.oracle.graal.visualizer.editor.DiagramViewModel; +import com.oracle.graal.visualizer.editor.SplitCompilationViewerFactory; +import com.sun.hotspot.igv.data.InputGraph; + +public class CfgCompilationViewerFactory extends SplitCompilationViewerFactory { + + @Override + public String getName() { + return "CFG"; + } + + @Override + protected CompilationViewer createViewer(InputGraph graph) { + return new CfgCompilationViewer(graph); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgEditorContext.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,10 @@ + +package at.ssw.visualizer.cfg; + +public abstract class CfgEditorContext { + + public static final int LAYOUT_HIERARCHICALNODELAYOUT = 1; + public static final int LAYOUT_HIERARCHICALCOMPOUNDLAYOUT = 2; + + public static final int MAX_AUTOEDGESVISIBLE = 8; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractCfgEditorAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,57 @@ +package at.ssw.visualizer.cfg.action; + + +import at.ssw.visualizer.cfg.graph.CfgScene; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import org.openide.util.Utilities; +import org.openide.util.actions.CallableSystemAction; + +/** + * The common superclass of all concrete actions related to the CFG visualizer. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public abstract class AbstractCfgEditorAction extends CallableSystemAction { + + CfgScene topComponent = null; + + public AbstractCfgEditorAction() { + setEnabled(false); + + } + + protected CfgScene getEditor() { + return Utilities.actionsGlobalContext().lookup(CfgScene.class); + } + + @Override + public JMenuItem getMenuPresenter() { + return new JMenuItem(this); + } + + + @Override + public JComponent getToolbarPresenter() { + JButton b = new JButton(this); + if (getIcon() != null) { + b.setText(null); + b.setToolTipText(getName()); + } + return b; + } + + + @Override + public JMenuItem getPopupPresenter() { + return new JMenuItem(this); + } + + + @Override + protected boolean asynchronous() { + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +CTL_SomeAction=test +CTL_SomeAction2=test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HideEdgesAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,52 @@ +/* + * 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 at.ssw.visualizer.cfg.action; + + +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "at.ssw.visualizer.cfg.action.HideEdges", category = "View") +@ActionRegistration(displayName = "Hide Edges", iconBase="at/ssw/visualizer/cfg/icons/hideedges.gif") +@ActionReference(path = "CompilationViewer/CFG/Actions", position = 180) +public class HideEdgesAction implements ActionListener { + + private List<CfgScene> scenes; + + public HideEdgesAction(List<CfgScene> scenes) { + this.scenes = scenes; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (CfgScene scene : scenes) { + scene.setSelectedEdgesVisibility(false); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalCompoundLayoutAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,52 @@ +/* + * 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 at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + + +@ActionID(id = "at.ssw.visualizer.cfg.action.HierarchicalCompoundLayout", category = "View") +@ActionRegistration(displayName = "Compound Layout", iconBase="at/ssw/visualizer/cfg/icons/arrangeloop.gif") +@ActionReference(path = "CompilationViewer/CFG/Actions", position = 150) +public class HierarchicalCompoundLayoutAction implements ActionListener { + List<CfgScene> scenes; + + public HierarchicalCompoundLayoutAction(List<CfgScene> scenes) { + this.scenes = scenes; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (CfgScene s : scenes) { + s.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalNodeLayoutAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,52 @@ +/* + * 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 at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + + +@ActionID(id = "at.ssw.visualizer.cfg.action.HierarchicalNodeLayout", category = "View") +@ActionRegistration(displayName = "Layout", iconBase="at/ssw/visualizer/cfg/icons/arrangehier.gif") +@ActionReference(path = "CompilationViewer/CFG/Actions", position = 160) +public class HierarchicalNodeLayoutAction implements ActionListener { + List<CfgScene> scenes; + + public HierarchicalNodeLayoutAction(List<CfgScene> scenes) { + this.scenes = scenes; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (CfgScene s : scenes) { + s.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowEdgesAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,52 @@ +/* + * 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 at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + + +@ActionID(id = "ShowEdges", category = "View") +@ActionRegistration(displayName = "Show Edges", iconBase="at/ssw/visualizer/cfg/icons/showedges.gif") +@ActionReference(path = "CompilationViewer/CFG/Actions", position = 170) +public class ShowEdgesAction implements ActionListener { + + private List<CfgScene> scenes; + + public ShowEdgesAction(List<CfgScene> scenes) { + this.scenes = scenes; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (CfgScene scene : scenes) { + scene.setSelectedEdgesVisibility(true); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgScene.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,836 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.action.HideEdgesAction; +import at.ssw.visualizer.cfg.action.ShowEdgesAction; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalCompoundLayout; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalNodeLayout; +import at.ssw.visualizer.cfg.model.CfgEnv; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.visual.PolylineRouter; +import at.ssw.visualizer.cfg.visual.PolylineRouterV2; +import at.ssw.visualizer.cfg.visual.WidgetCollisionCollector; +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import com.oracle.graal.visualizer.sharedactions.ZoomCookie; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; +import java.util.prefs.Preferences; +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.MoveProvider; +import org.netbeans.api.visual.action.PopupMenuProvider; +import org.netbeans.api.visual.action.RectangularSelectDecorator; +import org.netbeans.api.visual.action.RectangularSelectProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.anchor.AnchorFactory; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.layout.LayoutFactory; +import org.netbeans.api.visual.layout.SceneLayout; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.router.Router.*; +import org.netbeans.api.visual.router.RouterFactory; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.LayerWidget; +import org.netbeans.api.visual.widget.Widget; +import org.openide.util.NbPreferences; +import org.openide.util.actions.SystemAction; + +public final class CfgScene extends GraphScene<CfgNode, CfgEdge> implements ChangeListener, ZoomCookie { + + private LayerWidget mainLayer = new LayerWidget(this); + private LayerWidget connectionLayer = new LayerWidget(this); + private LayerWidget interractionLayer = new LayerWidget(this); + private LayerWidget clusterLayer = new LayerWidget(this); + private Set<CfgNode> selectedNodes = Collections.<CfgNode>emptySet(); + private Map<Integer, LoopClusterWidget> loopidx2clusterwidget = new HashMap<>(); + private Map<CfgNode, EdgeSwitchWidget> inputSwitches = new HashMap<>(); + private Map<CfgNode, EdgeSwitchWidget> outputSwitches = new HashMap<>(); + private WidgetAction moveAction = ActionFactory.createMoveAction(ActionFactory.createFreeMoveStrategy(), this.createMoveProvider()); + private SceneLayout sceneLayout; + private CfgEnv env; + private int currentLayout = -1; + private JScrollPane scrollPane; + private WidgetAction contextPopupAction = this.createContextMenuAction(this); + private List<NodeWidget> nodeWidgets = null; + private boolean loopClustersVisible = true; + private static String PREFERENCE_LOOP_CLUSTER = "loopClusters"; + private static String PREFERENCE_ROUTER = "router"; + private static String PREFERENCE_LAYOUT = "layout"; + + public static Preferences getPreferences() { + return NbPreferences.forModule(CfgScene.class); + } + private final PreferenceChangeListener preferenceChangeListener = new PreferenceChangeListener() { + @Override + public void preferenceChange(PreferenceChangeEvent evt) { + if (evt.getKey().equals(PREFERENCE_ROUTER)) { + setUseBezierRouter(Boolean.parseBoolean(evt.getNewValue())); + } else if (evt.getKey().equals(PREFERENCE_LOOP_CLUSTER)) { + setLoopWidgets(Boolean.parseBoolean(evt.getNewValue())); + } + } + }; + + public CfgScene(final JScrollPane scrollPane, final ControlFlowGraph cfg) { + addChild(clusterLayer); + addChild(mainLayer); + addChild(interractionLayer); + addChild(connectionLayer); + this.scrollPane = scrollPane; + this.loadModel(new CfgEnv(cfg)); + this.getInputBindings().setZoomActionModifiers(0); + this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1)); + this.getActions().addAction(ActionFactory.createPanAction()); + this.getActions().addAction(ActionFactory.createRectangularSelectAction( + this.createSelectDecorator(this), + interractionLayer, + this.createRectangularSelectProvider())); + this.getActions().addAction(this.contextPopupAction); + this.addSceneListener(createSceneListener(this)); + this.validate(); + + getPreferences().addPreferenceChangeListener(preferenceChangeListener); + this.loadDefaults(); + } + + private void loadModel(CfgEnv cfgenv) { + this.env = cfgenv; + for (CfgNode n : env.getNodes()) { + addNode(n); + } + for (CfgEdge e : env.getEdges()) { + addEdge(e); + setEdgeSource(e, e.getSourceNode()); + setEdgeTarget(e, e.getTargetNode()); + } + this.stackLoops(cfgenv.getLoopMap()); + this.autoHideEdges(); + } + + public void loadDefaults() { + CfgPreferences prefs = CfgPreferences.getInstance(); + this.setBackground(prefs.getBackgroundColor()); + setUseBezierRouter(getPreferences().getBoolean(PREFERENCE_ROUTER, true)); + setLoopWidgets(getPreferences().getBoolean(PREFERENCE_LOOP_CLUSTER, true)); + setSceneLayout(getPreferences().getInt(PREFERENCE_LAYOUT, CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT)); + } + + //sets the parent Widget of all LoopClusterWidgets + private void stackLoops(Map<CfgNode, LoopInfo> map) { + this.clusterLayer.removeChildren(); + + Set<LoopInfo> cache = new HashSet<>(); + for (LoopInfo info : map.values()) { + if (cache.contains(info)) { + continue; + } + LoopClusterWidget widget = this.loopidx2clusterwidget.get(info.getLoopIndex()); + LoopInfo parent = info.getParent(); + while (parent != null) { + LoopClusterWidget parentWidget = this.loopidx2clusterwidget.get(parent.getLoopIndex()); + assert parentWidget != null; + if (widget.getParentWidget() != null) { + widget.removeFromParent(); + } + parentWidget.addChild(widget); + widget = parentWidget; + parent = parent.getParent(); + } + widget.removeFromParent(); + this.clusterLayer.addChild(widget);//parent == null => parent is clusterlayer + } + } + + //hide in|output edges + private void autoHideEdges() { + for (CfgNode n : this.getNodes()) { + int fanin = n.getInputEdges().length; + int fanout = n.getOutputEdges().length; + if (fanin > CfgEditorContext.MAX_AUTOEDGESVISIBLE) { + assert (inputSwitches.containsKey(n)); + if (this.inputSwitches.containsKey(n)) { + EdgeSwitchWidget esw = this.inputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + if (fanout > CfgEditorContext.MAX_AUTOEDGESVISIBLE) { + if (this.outputSwitches.containsKey(n)) { + EdgeSwitchWidget esw = this.outputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + } + + } + + //apply current cfggraphscene layout + public void applyLayout() { + this.sceneLayout.invokeLayoutImmediately(); + } + + //returns a Set with the currently selected Nodes + public Set<CfgNode> getSelectedNodes() { + return Collections.<CfgNode>unmodifiableSet(selectedNodes); + } + + public Map<Integer, LoopClusterWidget> getLoopidx2clusterwidget() { + return loopidx2clusterwidget; + } + + /** + * Sets the color of the currently selected Nodes If the supplied color is null the default color will be used + */ + public void setSelectedNodesColor(Color color) { + if (color == null) { //set default color + CfgPreferences prefs = CfgPreferences.getInstance(); + boolean customized = false; + for (CfgNode n : this.selectedNodes) { + color = null; + color = prefs.getFlagsSetting().getColor(n.getBasicBlock().getFlags()); + customized = (color != null); + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor((customized) ? color : prefs.getNodeColor(), customized); + } + } else { + for (CfgNode n : this.selectedNodes) { + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor(color, true); + } + } + this.validate(); + } + + public void setSelectedEdgesVisibility(boolean visible) { + for (CfgNode n : this.selectedNodes) { + EdgeSwitchWidget in = this.inputSwitches.get(n); + EdgeSwitchWidget out = this.outputSwitches.get(n); + if (in != null) { + in.changeEdgeVisibility(visible); + } + if (out != null) { + out.changeEdgeVisibility(visible); + } + } + this.validate(); + } + + public EdgeSwitchWidget getInputSwitch(CfgNode n) { + return this.inputSwitches.get(n); + } + + public EdgeSwitchWidget getOutputSwitch(CfgNode n) { + return this.outputSwitches.get(n); + } + + public CfgEnv getCfgEnv() { + return env; + } + + public boolean isLoopClusterVisible() { + return loopClustersVisible; + } + + public void setLoopWidgets(boolean visible) { + for (Widget w : this.loopidx2clusterwidget.values()) { + w.setVisible(visible); + w.revalidate(); + } + this.loopClustersVisible = visible; + this.validate(); + getPreferences().putBoolean(PREFERENCE_LOOP_CLUSTER, visible); + } + + private void setUseBezierRouter(boolean value) { + Router router; + if (value) { + router = new PolylineRouterV2(new WidgetCollisionCollector() { + @Override + public void collectCollisions(List<Widget> collisions) { + collisions.addAll(getNodeWidgets()); + } + }); + } else { + router = RouterFactory.createDirectRouter(); + } + + for (CfgEdge e : this.getEdges()) { + EdgeWidget ew = (EdgeWidget) this.findWidget(e); + ew.setRouter(router); + } + this.validate(); + getPreferences().putBoolean(PREFERENCE_ROUTER, value); + } + + public Collection<NodeWidget> getNodeWidgets() { + if (nodeWidgets != null && nodeWidgets.size() == this.getNodes().size()) { + return nodeWidgets; + } + + List<NodeWidget> widgets = new ArrayList<>(); + for (CfgNode n : this.getNodes()) { + NodeWidget w = (NodeWidget) this.findWidget(n); + widgets.add(w); + } + + nodeWidgets = Collections.unmodifiableList(widgets); + return widgets; + } + + public void setSceneLayout(int newLayout) { + + GraphLayout<CfgNode, CfgEdge> graphLayout = null; + + switch (newLayout) { + case CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT: + graphLayout = new HierarchicalNodeLayout(this); + break; + + case CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT: + graphLayout = new HierarchicalCompoundLayout(this); + break; + } + + this.currentLayout = newLayout; + if (graphLayout != null) { + this.sceneLayout = LayoutFactory.createSceneGraphLayout(this, graphLayout); + } + + getPreferences().putInt(PREFERENCE_LAYOUT, newLayout); + sceneLayout.invokeLayoutImmediately(); + } + + @Override + protected void attachEdgeSourceAnchor(CfgEdge edge, CfgNode oldSourceNode, CfgNode sourceNode) { + Anchor sourceAnchor; + EdgeWidget edgeWidget = (EdgeWidget) findWidget(edge); + Widget sourceWidget = findWidget(sourceNode); + + if (edge.isSymmetric()) { + sourceAnchor = new SymmetricAnchor(sourceWidget, true, true); + } else { + sourceAnchor = AnchorFactory.createRectangularAnchor(sourceWidget); + } + edgeWidget.setSourceAnchor(sourceAnchor); + } + + @Override + protected void attachEdgeTargetAnchor(CfgEdge edge, CfgNode oldtarget, CfgNode targetNode) { + Anchor targetAnchor; + ConnectionWidget edgeWidget = (ConnectionWidget) findWidget(edge); + Widget targetWidget = findWidget(targetNode); + + if (edge.isSymmetric()) { + targetAnchor = new SymmetricAnchor(targetWidget, true, false); + } else { + targetAnchor = AnchorFactory.createRectangularAnchor(targetWidget); + } + edgeWidget.setTargetAnchor(targetAnchor); + } + + @Override + protected Widget attachEdgeWidget(CfgEdge edge) { + EdgeWidget widget = new EdgeWidget(this, edge); + connectionLayer.addChild(widget); + attachSourceSwitchWidget(edge); + attachTargetSwitchWidget(edge); + return widget; + } + + @Override + protected Widget attachNodeWidget(CfgNode node) { + this.nodeWidgets = null; + + NodeWidget nw = new NodeWidget(this, node); + WidgetAction.Chain actions = nw.getActions(); + actions.addAction(this.contextPopupAction); + actions.addAction(this.moveAction); + actions.addAction(this.createObjectHoverAction()); + + if (node.isLoopMember()) { + LoopClusterWidget loopWidget = this.attachLoopMember(node); + loopWidget.addMember(nw); + } + mainLayer.addChild(nw); + return nw; + } + + private LoopClusterWidget attachLoopMember(CfgNode node) { + LoopClusterWidget lw = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if (lw == null) { + lw = new LoopClusterWidget(this, node.getLoopDepth(), node.getLoopIndex()); + this.loopidx2clusterwidget.put(node.getLoopIndex(), lw); + this.clusterLayer.addChild(lw); + } + return lw; + } + + private boolean detachLoopMember(CfgNode node, NodeWidget nodeWidget) { + LoopClusterWidget rm = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if (rm == null) { + return false;//not added + } + if (rm.removeMember(nodeWidget)) { + if (rm.getMembers().isEmpty()) { + this.loopidx2clusterwidget.remove(rm.getLoopIndex()); + List<Widget> childs = new ArrayList<>(rm.getChildren()); + for (Widget w : childs) {//append stacked loopwidgets + w.removeFromParent(); + rm.getParentWidget().addChild(w); + } + rm.removeFromParent(); + } + return true; + } + return false; + } + + //this function is not invoked by any class of the module + //however to ensure that the edge switches are treatet corretly + //when a future version removes nodes it was implemented too. + @Override + protected void detachNodeWidget(CfgNode node, Widget nodeWidget) { + if (node.isLoopMember() && nodeWidget instanceof NodeWidget) { + this.detachLoopMember(node, (NodeWidget) nodeWidget); + } + super.detachNodeWidget(node, nodeWidget); + assert nodeWidget.getParentWidget() == null; + if (this.inputSwitches.containsKey(node)) { + EdgeSwitchWidget esw = this.inputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + if (this.outputSwitches.containsKey(node)) { + EdgeSwitchWidget esw = this.outputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + } + + protected EdgeSwitchWidget attachSourceSwitchWidget(CfgEdge e) { + CfgNode sourceNode = e.getSourceNode(); + NodeWidget sourceWidget = (NodeWidget) this.findWidget(sourceNode); + EdgeSwitchWidget out = outputSwitches.get(sourceNode); + if (out == null) { + out = new EdgeSwitchWidget(this, sourceWidget, true); + this.connectionLayer.addChild(out); + outputSwitches.put(sourceNode, out); + } + return out; + } + + protected EdgeSwitchWidget attachTargetSwitchWidget(CfgEdge e) { + CfgNode targetNode = e.getTargetNode(); + NodeWidget targetWidget = (NodeWidget) this.findWidget(targetNode); + EdgeSwitchWidget in = inputSwitches.get(targetNode); + if (in == null) { + in = new EdgeSwitchWidget(this, targetWidget, false); + this.connectionLayer.addChild(in); + inputSwitches.put(targetNode, in); + } + return in; + } + + //resets the selection state of all NodeWidgets + private void cleanNodeSelection() { + if (!this.selectedNodes.isEmpty()) { + this.userSelectionSuggested(Collections.<CfgNode>emptySet(), false); + this.selectedNodes = Collections.<CfgNode>emptySet(); + this.validate(); + } + } + + //sets the scene & global node selection + public void setNodeSelection(Set<CfgNode> newSelection) { + this.setSceneSelection(newSelection); + this.updateGlobalSelection(); + } + + //sets the scene selection + private void setSceneSelection(Set<CfgNode> newSelection) { + if (newSelection.equals(selectedNodes)) { + return; + } + + this.selectedNodes = newSelection; + + Set<Object> selectedObjects = new HashSet<>(); + + for (CfgNode n : newSelection) { + selectedObjects.addAll(this.findNodeEdges(n, true, true)); + } + selectedObjects.addAll(newSelection); + + //if the selection gets updated from a change in the block view + //the scene will be centered + if (selectionUpdating) { + this.centerSelection(); + } + + this.userSelectionSuggested(selectedObjects, false); + this.validate(); + } + + //updates selection of Block View + public void updateGlobalSelection() { + // TODO(tw): Add selection management. +// Selection selection = SelectionManager.getDefault().getCurSelection(); +// ArrayList<BasicBlock> newBlocks = new ArrayList<BasicBlock>(); +// for (CfgNode n : this.selectedNodes) { +// newBlocks.add(n.getBasicBlock()); +// } +// BasicBlock[] curBlocks = newBlocks.toArray(new BasicBlock[newBlocks.size()]); +// selection.put(curBlocks); + } + private boolean selectionUpdating = false; + + //change of blockview selection + public void stateChanged(ChangeEvent event) { + if (selectionUpdating) { + return; + } + + selectionUpdating = true; + + Object source = event.getSource(); +// if(source instanceof Selection){ +// Selection selection=(Selection) source; +// Set<CfgNode> newSelection = new HashSet<CfgNode>(); +// BasicBlock[] newBlocks = selection.get(BasicBlock[].class); +// if (newBlocks != null) { +// for(BasicBlock b : newBlocks){ +// for(CfgNode n : this.getNodes()){ +// if(n.getBasicBlock() == b) newSelection.add(n); +// } +// } +// this.setSceneSelection(newSelection); +// } +// } + selectionUpdating = false; + // TODO(tw): Add selection management. + } + + //centers the viewport on the currently selected nodewidgets + private void centerSelection() { + Point sceneCenter = null; + Collection<CfgNode> nodes = this.selectedNodes; + if (nodes.size() == 0) { + nodes = this.getNodes(); + } + + for (CfgNode n : nodes) { + if (sceneCenter == null) { + sceneCenter = this.findWidget(n).getLocation(); + continue; + } + Point location = this.findWidget(n).getLocation(); + sceneCenter.x = (location.x + sceneCenter.x) / 2; + sceneCenter.y = (location.y + sceneCenter.y) / 2; + } + + JComponent view = this.getView(); + if (view != null) { + Rectangle viewBounds = view.getVisibleRect(); + + Point viewCenter = this.convertSceneToView(sceneCenter); + + view.scrollRectToVisible(new Rectangle( + viewCenter.x - viewBounds.width / 2, + viewCenter.y - viewBounds.height / 2, + viewBounds.width, + viewBounds.height)); + } + } + + public void zoomScene() { + JScrollPane pane = scrollPane; + Rectangle prefBounds = this.getPreferredBounds(); + Dimension viewDim = pane.getViewportBorderBounds().getSize(); + + double realwidth = (double) prefBounds.width * this.getZoomFactor(); + double realheight = (double) prefBounds.height * this.getZoomFactor(); + + double zoomX = (double) viewDim.width / realwidth; + double zoomY = (double) viewDim.height / realheight; + double zoomFactor = Math.min(zoomX, zoomY); + this.setZoomFactor(zoomFactor * 0.9); + } + + //Enables Antialiasing + @Override + public void paintChildren() { + Object anti = getGraphics().getRenderingHint(RenderingHints.KEY_ANTIALIASING); + Object textAnti = getGraphics().getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); + + getGraphics().setRenderingHint( + RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + getGraphics().setRenderingHint( + RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + super.paintChildren(); + + getGraphics().setRenderingHint(RenderingHints.KEY_ANTIALIASING, anti); + getGraphics().setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, textAnti); + } + + //select provider for node selection + private RectangularSelectProvider createRectangularSelectProvider() { + return new RectangularSelectProvider() { + + public void performSelection(Rectangle rectangle) { + HashSet<CfgNode> set = new HashSet<>(); + + //change to a rectangle with (x,offsetY) at the top left + if (rectangle.width < 0) { + rectangle.x = rectangle.x + rectangle.width; + rectangle.width *= -1; + } + if (rectangle.height < 0) { + rectangle.y = rectangle.y + rectangle.height; + rectangle.height *= -1; + } + + for (NodeWidget n : getNodeWidgets()) { + Point p = n.getLocation(); + if (p != null && rectangle.contains(p)) { + set.add(n.getNodeModel()); + } + } + setNodeSelection(set); + } + }; + } + + //select decorator for node selection + private RectangularSelectDecorator createSelectDecorator(final CfgScene scene) { + return new RectangularSelectDecorator() { + + public Widget createSelectionWidget() { + scene.cleanNodeSelection();//unselected all nodes + scene.revalidate(); + return new SelectionWidget(getScene()); + } + }; + } + + private MoveProvider createMoveProvider() { + return new MoveProvider() { + + private HashMap<Widget, Point> originals = new HashMap<>(); + private Point original = null; + + public void movementStarted(Widget widget) { + originals.clear(); + NodeWidget nw = (NodeWidget) widget; + if (selectedNodes.contains(nw.getNodeModel())) {//move current selection + for (CfgNode n : selectedNodes) { + Widget w = findWidget(n); + originals.put(w, w.getLocation()); + } + } else {//a newly-selected node will be moved + CfgNode n = nw.getNodeModel(); + HashSet<CfgNode> selectedNode = new HashSet<>(1); + selectedNode.add(n); + setNodeSelection(selectedNode); + originals.put(widget, widget.getPreferredLocation()); + widget.revalidate(); + validate(); + + } + } + + public void movementFinished(Widget widget) { + NodeWidget nw = (NodeWidget) widget; + if (selectedNodes.contains(nw.getNodeModel())) { + return;//to be able to move the current selection + } + + HashSet<CfgNode> selectedNode = new HashSet<>(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + originals.clear(); + original = null; + + } + + public Point getOriginalLocation(Widget widget) { + if (original == null) { + original = widget.getLocation(); + } + + return original; + } + //todo : find a cache algorithm which only routes edges + //which are intersected by bounds of the moved rectangle + + public void setNewLocation(Widget widget, Point location) { + Point org = getOriginalLocation(widget); + int dx = location.x - org.x; + int dy = location.y - org.y; + for (Map.Entry<Widget, Point> entry : originals.entrySet()) { + Point point = entry.getValue(); + entry.getKey().setPreferredLocation(new Point(point.x + dx, point.y + dy)); + } + for (CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) findWidget(e); + if (ew.isVisible()) { + ew.reroute(); + } + } + } + }; + } + + private WidgetAction createContextMenuAction(final CfgScene scene) { + return ActionFactory.createPopupMenuAction(new PopupMenuProvider() { + + public JPopupMenu getPopupMenu(Widget widget, Point point) { + JPopupMenu menu = new JPopupMenu(); + NodeWidget nw = null; + if (widget instanceof NodeWidget) { + nw = (NodeWidget) widget; + if (!selectedNodes.contains(nw.getNodeModel())) { + HashSet<CfgNode> selectedNode = new HashSet<>(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + } + } else if (scene.getSelectedNodes().size() == 1) { + nw = (NodeWidget) scene.findWidget(scene.getSelectedNodes().iterator().next()); + } + + if (nw != null) { + CfgNode node = nw.getNodeModel(); + ArrayList<CfgNode> successors = new ArrayList<>(); + ArrayList<CfgNode> predecessors = new ArrayList<>(); + for (CfgEdge e : node.getOutputEdges()) { + successors.add(e.getTargetNode()); + } + for (CfgEdge e : node.getInputEdges()) { + predecessors.add(e.getSourceNode()); + } + + if (predecessors.size() > 0) { + Collections.sort(predecessors, new NodeNameComparator()); + JMenu predmenu = new JMenu("Go to predecessor"); + for (CfgNode n : predecessors) { + GotoNodeAction action = new GotoNodeAction(n); + predmenu.add(action); + } + menu.add(predmenu); + } + if (successors.size() > 0) { + Collections.sort(successors, new NodeNameComparator()); + JMenu succmenu = new JMenu("Go to successor"); + for (CfgNode n : successors) { + GotoNodeAction action = new GotoNodeAction(n); + succmenu.add(action); + } + menu.add(succmenu); + } + if (successors.size() > 0 || predecessors.size() > 0) { + menu.addSeparator(); + } + } + + return menu; + } + }); + } + + @Override + public void zoomIn() { + this.setZoomFactor(this.getZoomFactor() * 1.1); + this.validate(); + } + + @Override + public void zoomOut() { + this.setZoomFactor(this.getZoomFactor() * 0.9); + this.validate(); + } + + @Override + public void showAll() { + this.zoomScene(); + this.validate(); + } + + private class NodeNameComparator implements Comparator<CfgNode> { + + public int compare(CfgNode node1, CfgNode node2) { + String name1 = node1.getBasicBlock().getName().substring(1); + String name2 = node2.getBasicBlock().getName().substring(1); + Integer blocknum1 = Integer.parseInt(name1); + Integer blocknum2 = Integer.parseInt(name2); + return blocknum1.compareTo(blocknum2); + } + } + + private class GotoNodeAction extends AbstractAction { + + CfgNode node; + + GotoNodeAction(CfgNode node) { + super(node.getBasicBlock().getName()); + this.node = node; + } + + public void actionPerformed(ActionEvent e) { + Set<CfgNode> nodes = new HashSet<>(1); + nodes.add(node); + setNodeSelection(nodes); + centerSelection(); + } + } + + private SceneListener createSceneListener(final CfgScene scene) { + return new SceneListener() { + + public void sceneRepaint() { + } + + public void sceneValidating() { + } + + public void sceneValidated() { + if (scene.isLoopClusterVisible()) { //update only if visible + for (LoopClusterWidget cw : getLoopidx2clusterwidget().values()) { + cw.updateClusterBounds(); + } + } + for (EdgeSwitchWidget esw : inputSwitches.values()) { + esw.updatePosition(); + } + + for (EdgeSwitchWidget esw : outputSwitches.values()) { + esw.updatePosition(); + } + } + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeSwitchWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,290 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; +import java.util.Collection; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.SelectProvider; +import org.netbeans.api.visual.action.TwoStateHoverProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + + +public class EdgeSwitchWidget extends Widget { + private final static Color color_enabled = Color.gray; + private final static Color color_hover = Color.lightGray; + private float width=1; + private float height=1; + private CfgScene scene; + private NodeWidget nodeWidget; + private boolean output; + private WidgetAction hoverAction; + private static final String TT_HIDE_EDGES = "Hide Edges"; + private static final String TT_SHOW_EDGES = "Show Edges"; + private static SelectProvider selectProvider = createSelectProvider(); + + + public EdgeSwitchWidget(final CfgScene scene, NodeWidget nodeWidget, boolean output) { + super(scene); + this.scene = scene; + this.output = output; + this.nodeWidget = nodeWidget; + + this.getActions().addAction(ActionFactory.createSelectAction(selectProvider)); + TwoStateHoverProvider ts = new TsHover(this); + WidgetAction wa = ActionFactory.createHoverAction(ts); + this.hoverAction = wa; + this.getActions().addAction(wa); + scene.getActions().addAction(wa); + this.setToolTipText(TT_HIDE_EDGES); + this.setForeground(color_enabled); + this.setState(ObjectState.createNormal()); + } + + + @Override + protected Rectangle calculateClientArea() { + if (this.nodeWidget.getBounds() == null) return new Rectangle(0, 0, 1, 1); + int hw = (int) (this.width / 2); + int hh = (int) (this.height /2); + + return new Rectangle(-hw, -hh, 2*hw, 2*hh); + } + + + public void updatePosition() { + if (this.nodeWidget.getBounds() != null) { + this.width = nodeWidget.getBounds().width*9; + this.width /=10; + this.height = nodeWidget.getBounds().height/4; + int offset=(int)(2 * (height / 3)); + + Rectangle bounds = nodeWidget.getBounds(); + Point location = nodeWidget.getLocation(); + + Point newLoc = new Point(); + newLoc.x = location.x; + + if(output) { + newLoc.y = +location.y + bounds.height/2+offset; + }else { + newLoc.y = location.y - bounds.height/2-offset; + } + this.setPreferredLocation(newLoc); + } + } + + private Collection<CfgEdge> getEdges(){ + Collection<CfgEdge> edges; + CfgNode node = nodeWidget.getNodeModel(); + if (output) { + edges = scene.findNodeEdges(node, true, false); + } else { + edges = scene.findNodeEdges(node, false, true); + } + return edges; + } + + //change visibility for all Edges + public void changeEdgeVisibility(boolean visible){ + Collection<CfgEdge> edges = this.getEdges(); + + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(visible != ew.isEdgeVisible()){ + ew.setEdgeVisible(visible); + if(output){ + scene.getInputSwitch(e.getTargetNode()).updateStatus(); + } else { + scene.getOutputSwitch(e.getSourceNode()).updateStatus(); + } + } + } + if(visible) + this.setToolTipText(TT_HIDE_EDGES); + else + this.setToolTipText(TT_SHOW_EDGES); + + this.setForeground(color_enabled); + this.bringToBack(); + ObjectState os = this.getState(); + this.setState(os.deriveSelected(!visible)); + } + + /** + * Update the status of the switch to the current state of the edges + * usually needed when the opposit switch changes the state + */ + private void updateStatus(){ + Collection<CfgEdge> edges = this.getEdges(); + boolean hiddenFound=false; + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!ew.isVisible()) { + hiddenFound=true; + break; + } + } + ObjectState os = this.getState(); + if(os.isSelected() && !hiddenFound) { + this.setState(os.deriveSelected(false)); + setToolTipText(TT_HIDE_EDGES); + } else if (!os.isSelected() && hiddenFound) { + this.setState(os.deriveSelected(true)); + setToolTipText(TT_SHOW_EDGES); + } + this.revalidate(); + } + + + public void startPreview() { + ObjectState os = this.getState(); + + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!os.isSelected() || !ew.isVisible()){ + ObjectState edgeState = ew.getState(); + ew.setState(edgeState.deriveHighlighted(true)); + } + } + } + + public void endPreview(){ + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + ObjectState os = ew.getState(); + ew.setState(os.deriveHighlighted(false)); + } + } + + /** + * shows or hides the edges of the switch + */ + public void switchEdges() { + endPreview(); + ObjectState os = this.getState(); + Collection<CfgEdge> edges = this.getEdges(); + ArrayList<CfgEdge> updates = new ArrayList<>(); + boolean visible=os.isSelected(); + this.setState(os.deriveSelected(!visible)); + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(ew.isEdgeVisible() != visible){ + updates.add(e); + ew.setEdgeVisible(visible); + if(output){ + scene.getInputSwitch(e.getTargetNode()).updateStatus(); + } else { + scene.getOutputSwitch(e.getSourceNode()).updateStatus(); + } + } + } + if(visible) + this.setToolTipText(TT_HIDE_EDGES); + else + this.setToolTipText(TT_SHOW_EDGES); + + revalidate(); + } + + + + + private class TsHover implements TwoStateHoverProvider { + EdgeSwitchWidget tw; + + TsHover(EdgeSwitchWidget tw) { + this.tw = tw; + } + + public void unsetHovering(Widget w) { + w.setForeground(color_enabled); + ObjectState state = w.getState(); + w.setState(state.deriveWidgetHovered(false)); + w.bringToBack(); + endPreview(); + } + + public void setHovering(Widget w) { + ObjectState state = w.getState(); + w.setState(state.deriveWidgetHovered(true)); + w.setForeground(color_hover); + w.bringToFront(); + nodeWidget.bringToFront(); + startPreview(); + } + } + + @Override + public void paintWidget() { + ObjectState os = this.getState(); + if(!os.isHovered() && !os.isSelected()) return; //all previewEdges visible and not hovering, + //no need to paint the switch + float hw = width/2; + Polygon pol = new Polygon(); + pol.addPoint(0,(int) -height/2); + pol.addPoint((int)hw,(int) height/2); + pol.addPoint((int)-hw,(int) height/2); + Graphics2D gr = getGraphics(); + gr.setColor(this.getForeground()); + BasicStroke bs = new BasicStroke(2.0f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND); + gr.setStroke(bs); + AffineTransform previousTransform; + previousTransform = gr.getTransform (); + if(output) { + if(os.isSelected() ){//hidden + gr.scale(1.0, -1.0); + } + } else { //input switch + if(os.isHovered() && !os.isSelected()){ + gr.scale(1.0, -1.0); + } + } + gr.fillPolygon(pol); + gr.setTransform(previousTransform); + + } + + + + //the constructor adds the hover WidgetAction to the scene + //the action is removed from the scene when the object gets destroyed + @Override + protected void finalize() throws Throwable { + this.getScene().getActions().removeAction(hoverAction); + this.getActions().removeAction(hoverAction); + } + + @Override + public String toString(){ + return "EDGESWITCH("+this.nodeWidget.getNodeModel().toString()+")"; + } + + private static SelectProvider createSelectProvider() { + return new SelectProvider(){ + public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) { + return false; + } + + public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) { + return true; + } + + public void select(Widget w, Point arg1, boolean arg2) { + if(w instanceof EdgeSwitchWidget){ + EdgeSwitchWidget tw = (EdgeSwitchWidget) w; + tw.switchEdges(); + } + } + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,97 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.visual.BezierWidget; +import at.ssw.visualizer.cfg.visual.SplineConnectionWidget; +import org.netbeans.api.visual.anchor.AnchorShapeFactory; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Stroke; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.model.ObjectState; + +//public class EdgeWidget extends BezierWidget { +public class EdgeWidget extends SplineConnectionWidget { + + private boolean visible=true;//to store the visible state when entering the preview + protected static final Stroke selectedStroke = new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + protected static final Stroke defaultStroke = new BasicStroke(1.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + protected static final Stroke previewStroke = new BasicStroke( + 0.5f, // Width + BasicStroke.CAP_SQUARE, // End cap + BasicStroke.JOIN_MITER, // Join style + 10.0f, // Miter limit + new float[] {5.0f, 5.0f}, // Dash pattern + 0.0f); + + + + public EdgeWidget(CfgScene scene, CfgEdge edge) { + super(scene); + Color lineColor; + CfgPreferences prefs = CfgPreferences.getInstance(); + + if(edge.isBackEdge()) + lineColor = prefs.getBackedgeColor(); + else if (edge.isXhandler()) + lineColor = prefs.getExceptionEdgeColor(); + else + lineColor = prefs.getEdgeColor(); + + setLineColor(lineColor); + AnchorShape as; + if(edge.isReflexive())//small Arrow + as = AnchorShapeFactory.createTriangleAnchorShape(6, true, false, 5); + else + as =AnchorShapeFactory.createTriangleAnchorShape(10, true, false, 9); + + setTargetAnchorShape(as); + setToolTipText(edge.toString()); + } + + public CfgEdge getEdgeModel() { + CfgScene scene = (CfgScene) this.getScene(); + return (CfgEdge) scene.findObject(this); + } + + public void setEdgeVisible(boolean visible) { + this.visible=visible; + this.setVisible(visible); + this.reroute(); + this.revalidate(); + } + + + public boolean isEdgeVisible(){ + return visible; + } + + + @Override + public void notifyStateChanged(ObjectState oldState, ObjectState newState) { + setForeground (getLineColor()); + + if(newState.isHighlighted() && !oldState.isHighlighted()){ + this.setStroke(previewStroke); + this.setVisible(true); + } else { + if(newState.isSelected()){ + this.setStroke(selectedStroke); + } else { + this.setStroke(defaultStroke); + } + if(this.isEdgeVisible()){ + this.setVisible(true); + } else { + this.setVisible(false); + } + } + } + + + @Override + public String toString(){ + return "EdgeWidget[" + getEdgeModel().toString() + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/LoopClusterWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,107 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Color; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.EditProvider; +import org.netbeans.api.visual.border.BorderFactory; +import org.netbeans.api.visual.widget.Widget; + +public class LoopClusterWidget extends Widget implements Comparable<LoopClusterWidget> { + private static final int INSET = 10;//min space between node members and cluster border + private static final int DASHSIZE = 10; + private Color color = Color.BLUE; + private int loopIndex; + private int loopDepth; + private CfgScene cfgscene; + private ArrayList<NodeWidget> members = new ArrayList<>(); + + public LoopClusterWidget(CfgScene scene, int loopdepth, final int loopindex) { + super(scene); + this.cfgscene = scene; + this.loopIndex = loopindex; + this.loopDepth = loopdepth; + this.setBorder(BorderFactory.createDashedBorder(color, DASHSIZE, DASHSIZE/2, true)); + this.getActions().addAction(ActionFactory.createEditAction( new EditProvider() { //double click action + public void edit(Widget w) { + if(w instanceof LoopClusterWidget){ + for(LoopInfo info : cfgscene.getCfgEnv().getLoopMap().values()){ + if(info.getLoopIndex() == loopindex){ + cfgscene.setNodeSelection(info.getMembers()); + break; + } + } + } + } + })); + + } + + public List<NodeWidget> getMembers() { + return members; + } + + public int getLoopIndex() { + return loopIndex; + } + + public void addMember(NodeWidget nw) { + assert(!this.members.contains(nw)); + members.add(nw); + } + + public boolean removeMember(NodeWidget nw) { + if(this.members.contains(nw)){ + members.remove(nw); + return true; + } + return false; + } + + public void setrandomColor(){ + if(this.loopDepth == 0 ) return; + Random rand = new Random(); + Color randColor = Color.getHSBColor(rand.nextFloat()%360,0.1f,1.0f); + this.setBackground(randColor); + } + + //updates the bounds of the widget, + //and revalidates the widget if a membernode changed the scene position + public void updateClusterBounds(){ + Rectangle boundRect=null; + + for(NodeWidget nw : this.members){ + if(boundRect==null){ + boundRect = nw.convertLocalToScene(nw.getBounds()); + } else { + boundRect = boundRect.union(nw.convertLocalToScene(nw.getBounds())); + } + } + if(boundRect==null) return; + for(Widget w : this.getChildren()) { + if(w instanceof LoopClusterWidget) { + LoopClusterWidget lc = (LoopClusterWidget)w; + lc.updateClusterBounds(); + boundRect = boundRect.union(w.convertLocalToScene(w.getBounds())); + } + } + + boundRect.grow(INSET, INSET); + this.setPreferredBounds(boundRect); + } + + + public int compareTo(LoopClusterWidget o) { + return new Integer(this.loopDepth).compareTo(o.loopDepth); + } + + + @Override + public String toString(){ + return "LoopCluster: [DEPTH "+this.loopDepth+ "] [INDEX "+this.loopIndex+"]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/NodeWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,153 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import org.netbeans.api.visual.border.BorderFactory; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + + +public class NodeWidget extends Widget { + + + //basic block node dimension + private final int halfheight=12; + private final int halfwidth=17; + + private final int height=halfheight*2+1; + private final int width=halfwidth*2+1; + private final int arcHeight=(halfheight/4)*3; + private final int arcWidth = arcHeight; + private final int FONT_MAXSIZE=18; + + private int borderWidth; + private boolean nodeColorCustomized; + private String text; + private Rectangle2D fontRect; + private Color nodeColor; + + protected static final Color HOVER_BACKGROUND = new Color(0xEEEEEE); + protected static final Color HOVER_FOREGROUND = new Color(0xCDCDCD); + + public NodeWidget(CfgScene scene, CfgNode nodeModel ){ + super(scene); + this.setToolTipText("<html>" + nodeModel.getDescription().replaceAll("\n", "<br>") + "</html>"); + this.text = nodeModel.getBasicBlock().getName(); + this.borderWidth = nodeModel.getLoopDepth()+1; + this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, Color.BLACK, Color.BLACK)); + CfgPreferences prefs = CfgPreferences.getInstance(); + Color color = prefs.getFlagsSetting().getColor(nodeModel.getBasicBlock().getFlags()); + this.nodeColorCustomized = (color!=null); + this.nodeColor = (nodeColorCustomized) ? color : prefs.getNodeColor(); + this.adjustFont(null); + } + + public void setBorderColor(Color color){ + this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, color, color)); + } + + public boolean isNodeColorCustomized() { + return nodeColorCustomized; + } + + //sets a customColor node color + public void setNodeColor(Color color, boolean customColor) { + this.nodeColorCustomized=customColor; + this.nodeColor=color; + this.revalidate(); + } + + public Color getNodeColor() { + return this.nodeColor; + } + + public CfgNode getNodeModel() { + CfgScene scene = (CfgScene) this.getScene(); + return (CfgNode) scene.findObject(this); + } + + + @Override + public void notifyStateChanged(ObjectState oldState, ObjectState newState) { + if(!oldState.equals(newState)) + this.revalidate(); + if(!oldState.isSelected() && newState.isSelected()) + this.bringToFront(); + } + + @Override + protected Rectangle calculateClientArea() { + return new Rectangle(-(halfwidth+1), -(1+halfheight), width+1, height+1);//add border + } + + public void adjustFont(Font font){ + if(font==null) + font = CfgPreferences.getInstance().getTextFont(); + if(font.getSize()>FONT_MAXSIZE){ + font = new Font(font.getFamily(), font.getStyle(), FONT_MAXSIZE); + } + int size=font.getSize(); + int fontStyle = font.getStyle(); + String fontName = font.getFamily(); + FontRenderContext frc = new FontRenderContext(new AffineTransform(), false, false); + Rectangle2D bounds = font.getStringBounds(text, frc); + while(size > 1 && bounds.getWidth() > width) { + font = new Font(fontName, fontStyle, --size); + bounds = font.getStringBounds(text, frc); + } + this.fontRect=bounds; + this.setFont(font); + } + + @Override + protected void paintWidget() { + Graphics2D gr = getGraphics(); + gr.setColor(nodeColor); + Insets borderInsets = this.getBorder().getInsets(); + RoundRectangle2D.Float innerRect = new RoundRectangle2D.Float(-(halfwidth+1), -(halfheight+1), width+1, height+1,arcWidth-1, arcHeight-1); + gr.fill(innerRect); + gr.setColor(getForeground()); + gr.setFont(getFont()); + float textX = (float)( - fontRect.getCenterX()); + float textY = (float)( - fontRect.getCenterY()); + gr.drawString(text, textX, textY); + + RoundRectangle2D.Float outerRect = new RoundRectangle2D.Float(-(halfwidth+borderInsets.left + 1), -(halfheight+borderInsets.top + 1), + width+borderInsets.left + borderInsets.right + 1, height + borderInsets.top + borderInsets.bottom + 1, + arcWidth + borderWidth, arcHeight + borderWidth); + + ObjectState os =this.getState(); + if(os.isSelected()){ + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); + gr.fill(outerRect); + gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); + gr.setComposite(composite); + } + if(os.isHovered()){ + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + gr.setColor(HOVER_FOREGROUND); + gr.fill(outerRect); + gr.setColor(HOVER_BACKGROUND); + gr.setComposite(composite); + } + } + + @Override + public String toString() { + return "NodeWidget[" + getNodeModel().getBasicBlock().getName() + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SelectionWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,39 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +public class SelectionWidget extends Widget { + public SelectionWidget(Scene scene) { + super(scene); + } + + public static void renderSelectedRect(Graphics2D gr, Rectangle rect) { + if (rect == null) { + return; + } + gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); + gr.fillRect(rect.x, rect.y, rect.width, rect.height); + gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); + } + + public void renderSelectionRectangle(Graphics2D gr, Rectangle selectionRectangle) { + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + + renderSelectedRect(gr, selectionRectangle); + gr.setComposite(composite); + } + + @Override + public void paintWidget(){ + this.renderSelectionRectangle(this.getGraphics(), this.getBounds()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SymmetricAnchor.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,157 @@ +package at.ssw.visualizer.cfg.graph; + +import org.netbeans.api.visual.widget.Widget; +import org.netbeans.api.visual.anchor.Anchor; +import java.awt.*; + + +/** + * This Anchor can be used with symmetric edges to create parallel Edges. + * Two Directed Edges are symmetric if they are connecting the same Nodes in different directions. + * e.g. Nodes (1, 2) Edges(a , b) with (1)-a->(2) , (2)-b->(1) + * Start-/End positions are calculated with a fixed offset to prevent edges from overlapping. + * If the edges are drawn as straight lines they will appear as parallel edges. + */ + +public final class SymmetricAnchor extends Anchor { + + private final static int OFFSET = 10; + private boolean includeBorders; + private int offx; + private int offy; + + public SymmetricAnchor (Widget widget, boolean includeBorders, boolean source) { + super (widget); + this.includeBorders = includeBorders; + if (source) { + offx = OFFSET; + offy = OFFSET; + } + else { + offx = -OFFSET; + offy = -OFFSET; + } + } + + public Result compute (Entry entry) { + Point relatedLocation = //center of the widget + getRelatedSceneLocation (); + Point oppositeLocation = //center of the widget + getOppositeSceneLocation (entry); + + Widget widget = getRelatedWidget (); + Rectangle bounds = widget.getBounds (); + if (! includeBorders) { + Insets insets = widget.getBorder ().getInsets (); + bounds.x += insets.left; + bounds.y += insets.top; + bounds.width -= insets.left + insets.right; + bounds.height -= insets.top + insets.bottom; + } + + bounds = widget.convertLocalToScene (bounds); + + if (bounds.isEmpty () || relatedLocation.equals (oppositeLocation)) + return new Anchor.Result (relatedLocation, Anchor.DIRECTION_ANY); + + float dx //distance x-axis + = oppositeLocation.x - relatedLocation.x; + float dy //distance y-axis + = oppositeLocation.y - relatedLocation.y; + + + float ddx + = Math.abs (dx) / (float) bounds.width; + float ddy = + Math.abs (dy) / (float) bounds.height; + + Anchor.Direction direction; + + + if (ddx >= ddy) { + if(dx >= 0.0f){ + direction = Direction.RIGHT; + relatedLocation.y -= offy; + } else { + direction = Direction.LEFT; + relatedLocation.y += offy; + } + } else { + if(dy >= 0.0f){ + direction = Direction.BOTTOM; + relatedLocation.x += offx; + } else { + direction = Direction.TOP; + relatedLocation.x -= offx; + } + } + + + float scale = 0.5f / Math.max (ddx, ddy); + + float ex = scale * dx; + float ey = scale * dy; + + Point point = new Point (Math.round (relatedLocation.x + ex), Math.round (relatedLocation.y + ey)); + + if(direction == Direction.RIGHT) { + int top = bounds.y;//-bounds.height;// left y of the widget + int bottom = bounds.y + bounds.height;// right y of the widget + if(point.y < top) {//above the widget + int cor = top-point.y; + point.x -= cor; + point.y += cor; + } else if ( point.y > bottom) { + int cor = point.y-bottom; + point.x -= cor; + point.y -= cor; + } + + } else if (direction == Direction.LEFT) { + int top = bounds.y;//-bounds.height;// left y of the widget + int bottom = bounds.y + bounds.height;// right y of the widget + + + + if(point.y < top) {//above the widget + int cor = top-point.y; + point.x += cor; + point.y += cor; + } else if ( point.y > bottom) { + int cor = bottom-point.y; + point.x -= cor; + point.y += cor; + } + + + } else if (direction == Direction.BOTTOM) { + int left = bounds.x;//-bounds.height;// left y of the widget + int right = bounds.x + bounds.width;// right y of the widget + if(point.x < left) {//above the widget + int cor = left-point.x; + point.x += cor; + point.y -= cor; + } else if ( point.x > right) { + int cor = point.x- right; + point.x -= cor; + point.y -= cor; + } + + } else if (direction == Direction.TOP) { + int left = bounds.x;//-bounds.height;// left y of the widget + int right = bounds.x + bounds.width;// right y of the widget + if(point.x < left) {//above the widget + int cor = left-point.x; + point.x += cor; + point.y += cor; + } else if ( point.x > right) { + int cor = point.x - right; + point.x -= cor; + point.y += cor; + } + + } + + return new Anchor.Result (point, direction); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalCompoundLayout.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,102 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Point; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.draw2d.geometry.Insets; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.eclipse.draw2d.graph.Subgraph; +import org.netbeans.api.visual.widget.Widget; + +public class HierarchicalCompoundLayout extends GraphLayout<CfgNode, CfgEdge> { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 20; + private int PADDING = 20; + private static final int INSET = 20; + private CfgScene scene; + + public HierarchicalCompoundLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph<CfgNode, CfgEdge> ug) { + CompoundDirectedGraph dg = new CompoundDirectedGraph(); + CompoundDirectedGraphLayout layout = new CompoundDirectedGraphLayout(); + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + Map<Integer, Subgraph> idx2graph = new HashMap<>(); + Subgraph base = new Subgraph(0); + idx2graph.put(0, base); + base.insets=getInsets(); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = new Subgraph(info.getLoopIndex()); + subg.insets=getInsets(); + idx2graph.put(info.getLoopIndex(), subg); + } + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + node.setPadding(new Insets(PADDING, PADDING, PADDING, PADDING)); + Subgraph subg = idx2graph.get(n.getLoopIndex()); + assert(subg != null); + node.setParent(subg); + subg.addMember(node); + nodeList.add(node); + + } + nodeList.addAll(idx2graph.values()); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = idx2graph.get(info.getLoopIndex()); + if(info.getParent() != null){ + Subgraph parentsubg = idx2graph.get(info.getParent().getLoopIndex()); + Edge edge = new Edge(parentsubg, subg); + parentsubg.addMember(subg); + subg.setParent(parentsubg); + edgeList.add(edge); + } + } + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + if(n.data instanceof CfgNode){ + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER, n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + this.setResolvedNodeLocation(ug, cfgNode, scenepos); + } + } + } + + @Override + protected void performNodesLayout(UniversalGraph<CfgNode, CfgEdge> ug, Collection<CfgNode> collection) { + } + + private Insets getInsets(){ + return new Insets(INSET, INSET, INSET, INSET); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalNodeLayout.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,69 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.Point; +import java.util.Collection; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.DirectedGraph; +import org.eclipse.draw2d.graph.DirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.netbeans.api.visual.widget.Widget; + + +public class HierarchicalNodeLayout extends GraphLayout<CfgNode, CfgEdge> { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 40; + + private CfgScene scene; + + public HierarchicalNodeLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph<CfgNode, CfgEdge> ug) { + DirectedGraph dg = new DirectedGraph(); + DirectedGraphLayout layout = new DirectedGraphLayout(); + + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + nodeList.add(node); + } + + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), + nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER , n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + setResolvedNodeLocation(ug, cfgNode, scenepos); + } + + } + + @Override + protected void performNodesLayout(UniversalGraph<CfgNode, CfgEdge> ug, Collection<CfgNode> collection) { + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/Icons.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,18 @@ +package at.ssw.visualizer.cfg.icons; + +/** + * + * @author Christian Wimmer + */ +public class Icons { + private static final String PATH = "at/ssw/visualizer/cfg/icons/"; + + public static final String CFG = PATH + "cfg.gif"; + + public static final String ICON_ZOOMIN = PATH + "zoomin.gif"; + public static final String ICON_ZOOMOUT = PATH + "zoomout.gif"; + public static final String ICON_DEFAULT = PATH + "arrangebfs.gif"; + + private Icons() { + } +}
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangehier.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangeloop.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize_selection.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/bezierrouter.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine_disabled.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges_disabled.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/manhattanrouter.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges_disabled.gif has changed
Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split_disabled.gif has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <folder name="OptionsDialog"> + <file name="CFGOptions.instance"> + <attr name="instanceClass" stringvalue="at.ssw.visualizer.cfg.preferences.CFGOptionsCategory"/> + <attr name="position" intvalue="1"/> + </file> + </folder> + <folder name="CompilationViewer"> + <folder name="CFG"> + <folder name="Actions"> + <file name="com-oracle-graal-visualizer-cfg-RouterAction.instance"> + <attr name="displayName" stringvalue="Use bezier routing"/> + <attr methodvalue="org.openide.awt.Actions.checkbox" name="instanceCreate"/> + <attr name="iconBase" stringvalue="at/ssw/visualizer/cfg/icons/bezierrouter.gif"/> + <attr name="preferencesNode" methodvalue="at.ssw.visualizer.cfg.graph.CfgScene.getPreferences"/> + <attr name="preferencesKey" stringvalue="router"/> + </file> + <file name="com-oracle-graal-visualizer-cfg-LoopClusterAction.instance"> + <attr name="displayName" stringvalue="Show loop clusters"/> + <attr methodvalue="org.openide.awt.Actions.checkbox" name="instanceCreate"/> + <attr name="iconBase" stringvalue="at/ssw/visualizer/cfg/icons/cluster.gif"/> + <attr name="preferencesNode" methodvalue="at.ssw.visualizer.cfg.graph.CfgScene.getPreferences"/> + <attr name="preferencesKey" stringvalue="loopClusters"/> + </file> + <file name="com-oracle-graal-visualizer-sharedactions-ShowAllAction.shadow"> + <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ShowAllAction.instance"/> + </file> + <file name="com-oracle-graal-visualizer-sharedactions-ZoomInAction.shadow"> + <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomInAction.instance"/> + </file> + <file name="com-oracle-graal-visualizer-sharedactions-ZoomOutAction.shadow"> + <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomOutAction.instance"/> + </file> + <file name="com-oracle-graal-visualizer-sharedactions-ExportSVGAction.shadow"> + <attr name="originalFile" stringvalue="Actions/File/com-oracle-graal-visualizer-sharedactions-ExportSVGAction.instance"/> + </file> + </folder> + </folder> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdge.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,10 @@ +package at.ssw.visualizer.cfg.model; + +public interface CfgEdge { + public CfgNode getSourceNode(); + public CfgNode getTargetNode(); + public boolean isXhandler(); + public boolean isBackEdge(); + public boolean isSymmetric(); + public boolean isReflexive(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdgeImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,50 @@ +package at.ssw.visualizer.cfg.model; + +public class CfgEdgeImpl implements CfgEdge { + private CfgNodeImpl sourceNode; + private CfgNodeImpl targetNode; + private boolean symmetric; + private boolean backedge; + + public CfgEdgeImpl(CfgNodeImpl sourceNode, CfgNodeImpl targetNode) { + this.sourceNode = sourceNode; + this.targetNode = targetNode; + } + + public void setSymmetric(boolean symmetric){ + this.symmetric = symmetric; + } + + public void setBackEdge(boolean isBackedge){ + this.backedge = isBackedge; + } + + public CfgNode getSourceNode() { + return sourceNode; + } + + public CfgNode getTargetNode() { + return targetNode; + } + + public boolean isBackEdge() { + return this.backedge; + } + + public boolean isSymmetric() { + return symmetric; + } + + public boolean isReflexive() { + return sourceNode==targetNode; + } + + public boolean isXhandler() { + return sourceNode.getBasicBlock().getXhandlers().contains(targetNode.getBasicBlock()); + } + + @Override + public String toString(){ + return this.sourceNode.getBasicBlock().getName() + "->" + targetNode.getBasicBlock().getName(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEnv.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,297 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + + +/** + * This is the container class for the data model, + * it prepares creates nodes and edges for the CfgScene + * from a ControlFlowGraph of the Compilation Model + */ +public class CfgEnv { + private ControlFlowGraph cfg; + private Map<CfgNode, LoopInfo> loopMap;//maps: LoopHeader --> LoopInfo + private CfgNodeImpl[] nodeArr; + private CfgEdgeImpl[] edgeArr; + + public CfgEnv(ControlFlowGraph cfg) { + this.cfg = cfg; + int blockCount = cfg.getBasicBlocks().size(); + CfgNodeImpl[] nodes = new CfgNodeImpl[blockCount]; + Map<BasicBlock, CfgNodeImpl> block2nodeMap = new HashMap<>(); + Map<CfgNodeImpl, Set<CfgEdgeImpl>> inputMap = new HashMap<>(); + ArrayList<CfgEdgeImpl> allEdges = new ArrayList<>(); + List<BasicBlock> blocks = cfg.getBasicBlocks(); + //create nodes + for(int idx=0 ; idx < blockCount ; idx++) { + BasicBlock b = blocks.get(idx); + + String description = "Name: " + b.getName() + "\n"; + description += "BCI: [" + b.getFromBci() + "," + b.getToBci() + "]\n"; + if (b.getLoopDepth() > 0) { + description += "Loop " + b.getLoopIndex() + " Depth " + b.getLoopDepth() + "\n"; + } + description += "Predecessors: " + getBlockList(b.getPredecessors()) + "\n"; + description += "Successors: " + getBlockList(b.getSuccessors()) + "\n"; + description += "XHandlers: " + getBlockList(b.getXhandlers()); + if (b.getDominator() != null) { + description += "\nDominator: " + b.getDominator().getName(); + } + nodes[idx] = new CfgNodeImpl(b, idx, description); + block2nodeMap.put(b, nodes[idx]); + } + + + //create edges + Set<String> cache = new HashSet<>();//avoids identical edges with same source and same target + for(int i = 0 ; i < blockCount ; i++) { + BasicBlock b = blocks.get(i); + List<CfgEdgeImpl> outputEdges = new ArrayList<>(); + + Set<BasicBlock> successors = new HashSet<>(); + successors.addAll(b.getSuccessors()); + successors.addAll(b.getXhandlers()); + for(BasicBlock sb : successors) { + CfgNodeImpl succNode = block2nodeMap.get(sb); + CfgEdgeImpl edge = new CfgEdgeImpl(nodes[i], succNode); + if(cache.contains(edge.toString())) + continue; + cache.add(edge.toString()); + //check for symtric edges + if(sb.getXhandlers().contains(b) || sb.getSuccessors().contains(b)) + edge.setSymmetric(true); + outputEdges.add(edge); + } + allEdges.addAll(outputEdges); + nodes[i].setOutputEdges(outputEdges.toArray(new CfgEdgeImpl[outputEdges.size()])); + } + + for(CfgEdgeImpl e: allEdges) { + //CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + CfgNodeImpl tar = (CfgNodeImpl) e.getTargetNode(); + Set<CfgEdgeImpl> set = inputMap.get(tar); + if( set == null) { + set = new HashSet<>(); + set.add(e); + inputMap.put(tar, set); + } + set.add(e); + } + for(CfgNodeImpl n : nodes){ + Set<CfgEdgeImpl> inputEdges = inputMap.get(n); + if(inputEdges == null) continue; + n.setInputEdges(inputEdges.toArray(new CfgEdgeImpl[inputEdges.size()])); + } + CfgEdgeImpl[] edges = allEdges.toArray(new CfgEdgeImpl[allEdges.size()]); + this.edgeArr=edges; + this.nodeArr=nodes; + CfgNodeImpl rootNode = nodeArr[0]; + setNodeLevels(rootNode); + indexLoops(rootNode); + + } + + + private String getBlockList(List<? extends BasicBlock> blocks) { + if (blocks.size() == 0) { + return "None"; + } + StringBuilder sb = new StringBuilder(); + String prefix = ""; + for (BasicBlock b : blocks) { + sb.append(prefix).append(b.getName()); + prefix = ", "; + } + return sb.toString(); + } + + + public CfgNode[] getNodes(){ + return this.nodeArr; + } + + public CfgEdge[] getEdges(){ + return this.edgeArr; + } + + public Map<CfgNode, LoopInfo> getLoopMap() { + return loopMap; + } + + public void setLoopMap(Map<CfgNode, LoopInfo> loopMap) { + this.loopMap = loopMap; + } + + private void indexLoops(CfgNodeImpl rootNode){ + LoopEnv env = new LoopEnv(Arrays.asList(nodeArr)); + loopDetection(env, rootNode); + calcLoopDepth(env); + + int loopIndex=1; + + for(LoopInfo info : env.loopMap.values()) { + info.setLoopIndex(loopIndex++); + info.setLoopDepth(info.getHeader().getLoopDepth()); + for(CfgNode n : info.getMembers()){ + if(n.getLoopDepth()>info.getLoopDepth()) continue; + CfgNodeImpl ni = (CfgNodeImpl) n; + ni.setLoopDepth(info.getLoopDepth()); + ni.setLoopIndex(info.getLoopIndex()); + } + } + + for(LoopInfo info : env.loopMap.values()) { + HashSet<CfgNode> members = new HashSet<>(info.getMembers()); + members.remove(info.getHeader());//remove own header + for(CfgNode n: members){ + if(n.isLoopHeader()) { + LoopInfo memberInfo = env.loopMap.get(n); + if (info.getLoopDepth() == memberInfo.getLoopDepth()-1) + memberInfo.setParent(info); + } + } + } + this.loopMap = env.loopMap; + } + + + private class LoopEnv { + Set<CfgNodeImpl> allNodes; + Set<CfgNodeImpl> activeNodes; + Set<CfgNodeImpl> visitedNodes; + Map<CfgNode, LoopInfo> loopMap; + private int loopIndex=0; + + public LoopEnv(Collection<CfgNodeImpl> nodes){ + allNodes = new HashSet<>(nodes); + activeNodes = new HashSet<>(2 * allNodes.size()); + visitedNodes = new HashSet<>(2 * allNodes.size()); + loopMap = new HashMap<>(); + } + + public int getLoopIndex(){ + return ++loopIndex; + } + } + + + private void loopDetection(LoopEnv env, CfgNodeImpl root) { + for (CfgNodeImpl n : env.allNodes) { + n.setLoopHeader(false); + for (CfgEdge e : n.getInputEdges()) { + CfgEdgeImpl ei = (CfgEdgeImpl) e; + ei.setBackEdge(false); + } + } + visit(env, root, null); + } + + + + private void visit(LoopEnv env, CfgNodeImpl n, CfgEdgeImpl e) { + if (env.activeNodes.contains(n)) { + // This node is b loop header! + n.setLoopHeader(true); + e.setBackEdge(true); + } else if (!env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + env.activeNodes.add(n); + + for (CfgEdge edge : n.getOutputEdges()) { + if(!edge.getTargetNode().isOSR()) { + CfgEdgeImpl ei = (CfgEdgeImpl) edge; + CfgNodeImpl ni = (CfgNodeImpl) edge.getTargetNode(); + visit(env, ni, ei); + } + } + env.activeNodes.remove(n); + } + } + + + + private void calcLoopDepth(LoopEnv env) { + for (CfgNodeImpl n : env.allNodes) { + env.visitedNodes.clear(); + + if (n.isLoopHeader()) { + LoopInfo loop = new LoopInfo(); + loop.setHeader(n); + n.setLoopIndex(env.getLoopIndex()); + HashSet<CfgNode> members = new HashSet<>(); + loop.setMembers(members); + members.add(n); + env.loopMap.put(loop.getHeader(), loop); + int loopDepth = n.getLoopDepth() + 1; + loop.setLoopDepth(loopDepth); + n.setLoopDepth(loopDepth); + for (CfgEdge e : n.getInputEdges()) { + if (e.isBackEdge() && !e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, n, src, loop); + loop.getBackEdges().add(e); + } + } + } + } + } + + + private void backwardIteration(LoopEnv env, CfgNodeImpl endNode, CfgNodeImpl n, LoopInfo loop) { + if (endNode != n && !env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + + for (CfgEdge e : n.getInputEdges()) { + if (!e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, endNode, src, loop); + } + } + loop.getMembers().add(n); + n.setLoopDepth(n.getLoopDepth() + 1); + } + } + + private void setNodeLevels(CfgNode rootNode){ + Set<CfgNode> cache = new HashSet<>(); + Queue<CfgNode> queue = new LinkedList<>(); + queue.add(rootNode); + cache.add(rootNode); + int level=0; + int[] nodeCount = new int[2]; + nodeCount[0]=1; + while(!queue.isEmpty()){ + CfgNodeImpl curNode = (CfgNodeImpl) queue.poll(); + curNode.setLevel(level); + nodeCount[0]--; + for(CfgEdge outEdge : curNode.getOutputEdges()) { + CfgNode succNode = outEdge.getTargetNode(); + if(cache.contains(succNode)) continue; + cache.add(succNode); + queue.add(succNode); + nodeCount[1]++; + } + if(nodeCount[0]==0){ + nodeCount[0]=nodeCount[1]; + nodeCount[1]=0; + level++; + } + } + } + + public ControlFlowGraph getCfg() { + return cfg; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,23 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; + + +public interface CfgNode { + //testers + public boolean isOSR(); + public boolean isRoot(); + public boolean isLoopHeader(); + public boolean isLoopMember(); + + //getters + public int getLevel(); + public int getLoopDepth(); + public int getLoopIndex(); + public int getNodeIndex(); + public CfgEdge[] getInputEdges(); + public CfgEdge[] getOutputEdges(); + public BasicBlock getBasicBlock(); + public String getDescription(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNodeImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,133 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import java.awt.Color; + + + +public class CfgNodeImpl implements CfgNode { + private int nodeIndex; + private BasicBlock basicBlock; + private int level; + private int loopDepth=0; + private int loopIndex=0; + private boolean osr=false; + private CfgNodeImpl dominator=null; + private CfgEdgeImpl[] inputEdges = new CfgEdgeImpl[0]; + private CfgEdgeImpl[] outputEdges = new CfgEdgeImpl[0]; + private String description; + private Color customColor=null; + private boolean loopHeader; + + public CfgNodeImpl(BasicBlock bb, int nodeIndex, String description) { + this.basicBlock = bb; + this.nodeIndex = nodeIndex; + this.description = description; + + if (bb.getPredecessors().size() == 1) { + BasicBlock pred = bb.getPredecessors().get(0); + boolean isStd = pred.getPredecessors().size() == 0; + if (isStd) { + for (String s : bb.getFlags()) { + if (s.equals("osr")) { + osr = true; + break; + } + } + } + } + } + + public int getNodeIndex() { + return nodeIndex; + } + + + public void setDominator(CfgNodeImpl dominator) { + this.dominator = dominator; + } + + public void setLevel(int level) { + this.level = level; + } + + public void setLoopDepth(int loopDepth) { + this.loopDepth = loopDepth; + } + + public void setLoopHeader(boolean loopHeader) { + this.loopHeader = loopHeader; + } + + public void setLoopIndex(int loopIndex) { + this.loopIndex = loopIndex; + } + + public void setNodeIndex(int nodeIndex) { + this.nodeIndex = nodeIndex; + } + + public boolean isRoot() { + return nodeIndex==0; + } + + public boolean isLoopHeader() { + return loopHeader; + } + + public boolean isLoopMember() { + return loopIndex > 0; + } + + public int getLevel() { + return level; + } + + public BasicBlock getBasicBlock() { + return basicBlock; + } + + public int getLoopDepth() { + return loopDepth; + } + + public int getLoopIndex() { + return loopIndex; + } + + public boolean isOSR() { + return osr; + } + + @Override + public String toString(){ + return basicBlock.getName(); + } + + public void setInputEdges(CfgEdgeImpl[] inputEdges){ + this.inputEdges = inputEdges; + } + + + public void setOutputEdges(CfgEdgeImpl[] outputEdges){ + this.outputEdges = outputEdges; + } + + public CfgEdge[] getInputEdges() { + return this.inputEdges; + } + + public CfgEdge[] getOutputEdges() { + return outputEdges; + } + + public String getDescription() { + return description; + } + + public void setColor(Color color) { + this.customColor=color; + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/LoopInfo.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,67 @@ +package at.ssw.visualizer.cfg.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + + +public class LoopInfo { + private CfgNode header;//the target node of the backedge + private int loopIndex; //index of the min cycleSet + private int loopDepth; //nested depth >=1 + private LoopInfo parent=null; + private Set<CfgNode> members; + private List<CfgEdge> backEdges = new ArrayList<>();//dfs backEdge + + protected void setLoopDepth(int depth) { + this.loopDepth=depth; + } + + protected void setLoopIndex(int loopIndex) { + this.loopIndex = loopIndex; + } + + public int getLoopDepth() { + return loopDepth; + } + + public Set<CfgNode> getMembers() { + return members; + } + + protected void setMembers(Set<CfgNode> members) { + this.members = members; + } + + public int getLoopIndex() { + return loopIndex; + } + + protected void setParent(LoopInfo parent) { + this.parent = parent; + } + + public LoopInfo getParent(){ + return parent; + } + + public List<CfgEdge> getBackEdges() { + return backEdges; + } + + public CfgNode getHeader() { + return header; + } + + protected void setHeader(CfgNode header) { + this.header = header; + } + + @Override + public String toString(){ + return "Loop(" + header.toString()+ ")-->" + members.toString(); + } + + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsCategory.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,32 @@ +package at.ssw.visualizer.cfg.preferences; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import org.netbeans.spi.options.OptionsCategory; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.ImageUtilities; + +/** + * Descriptor for the settings page displayed in the options dialog. + * + * @author Bernhard Stiftner + */ +public class CFGOptionsCategory extends OptionsCategory { + + public OptionsPanelController create() { + return new CFGOptionsPanelController(); + } + + public String getCategoryName() { + return "Control Flow Graph"; + } + + @Override + public Icon getIcon() { + return new ImageIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg32.gif")); + } + + public String getTitle() { + return "CFG Visualizer"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,482 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + +/** + * The actual component for changing the CFG visualizer settings. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class CFGOptionsPanel extends JPanel { + + List<ConfigurationElement> elements = new ArrayList<>(); + + /** Creates a new instance of CFGOptionsPanel */ + public CFGOptionsPanel() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + JPanel cfgPanel = new JPanel(new GridBagLayout()); + + // color/font settings + addColorChooser(cfgPanel, "Background color: ", new ColorChooser(CfgPreferences.PROP_BACKGROUND_COLOR){ + @Override + public void apply() { + CfgPreferences.getInstance().setBackgroundColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBackgroundColor(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); + } + + + + }); + addColorChooser(cfgPanel, "Back edge color: ", new ColorChooser(CfgPreferences.PROP_BACK_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setBackedgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBackedgeColor(); + this.setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); + } + }); + addColorChooser(cfgPanel, "Edge color: ", new ColorChooser(CfgPreferences.PROP_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setEdgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getEdgeColor(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); + } + + }); + addColorChooser(cfgPanel, "Exception edge color: ", new ColorChooser(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setExceptionEdgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getExceptionEdgeColor(); + setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); + } + }); + addColorChooser(cfgPanel, "Node color: ", new ColorChooser(CfgPreferences.PROP_NODE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setNodeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getNodeColor(); + setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAUT_NODE_COLOR); + } + }); + addColorChooser(cfgPanel, "Text color: ", new ColorChooser(CfgPreferences.PROP_TEXT_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setTextColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getTextColor(); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); + } + }); + addColorChooser(cfgPanel, "Border color: ", new ColorChooser(CfgPreferences.PROP_BORDER_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setBorderColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBorderColor(); + setColor(this.originalColor); + + } + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); + } + }); + addColorChooser(cfgPanel, "Selected Nodes color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_FG){ + + @Override + public void apply() { + CfgPreferences.getInstance().setSelectionColorForeground(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getSelectionColorForeground(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + } + }); + addColorChooser(cfgPanel, "Selection Rect color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_BG){ + + @Override + public void apply() { + CfgPreferences.getInstance().setSelectionColorBackground(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getSelectionColorBackground(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); + } + }); + addFontChooser(cfgPanel, "Text font: ", new FontChooser(CfgPreferences.PROP_TEXT_FONT){ + + @Override + public void apply() { + CfgPreferences.getInstance().setTextFont(getSelectedFont()); + } + + @Override + public void update() { + this.originalFont = CfgPreferences.getInstance().getTextFont(); + this.setSelectedFont(originalFont); + + } + + public void reset() { + this.setSelectedFont(CfgPreferencesDefaults.DEFAULT_TEXT_FONT); + } + }); + + // flags editor + addFlagsEditor(cfgPanel, "Flags: "); + add(cfgPanel); + + // add update button + Box hBox = new Box(BoxLayout.X_AXIS); + hBox.add(new JButton(new ResetAction())); + hBox.add(Box.createHorizontalGlue()); + add(hBox); + + add(Box.createVerticalGlue()); + } + + public void update() { + for (ConfigurationElement e : elements) { + e.update(); + } + } + + public void cancel() { + for (ConfigurationElement e : elements) { + e.update(); + } + } + + public void applyChanges() { + for (ConfigurationElement e : elements) { + if(e.isChanged()) + e.apply(); + } + } + + public boolean isDataValid() { + return true; + } + + public boolean isChanged() { + for (ConfigurationElement e : elements) { + if (e.isChanged()) { + return true; + } + } + return false; + } + + public void loadDefault() { + for (ConfigurationElement e : elements) { + e.reset(); + } + } + + private void addColorChooser(JComponent c, String displayName, ColorChooser chooser) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + JLabel label = new JLabel(displayName, JLabel.TRAILING); + layout.setConstraints(label, constraints); + c.add(label); + constraints.anchor = GridBagConstraints.WEST; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(chooser, constraints); + c.add(chooser); + elements.add(chooser); + label.setLabelFor(chooser); + } + + + + private void addFontChooser(JComponent c, String displayName, FontChooser chooser) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + JLabel label = new JLabel(displayName, JLabel.TRAILING); + layout.setConstraints(label, constraints); + c.add(label); + constraints.insets = new Insets(3, 3, 3, 1); + constraints.weightx = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.anchor = GridBagConstraints.CENTER; + layout.setConstraints(chooser.getPreview(), constraints); + c.add(chooser.getPreview()); + constraints.insets = new Insets(3, 1, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(chooser.getButton(), constraints); + c.add(chooser.getButton()); + elements.add(chooser); + label.setLabelFor(chooser.getButton()); + } + + private void addFlagsEditor(JComponent c, String displayName) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.NORTHEAST; + FlagsEditor flagsEditor = new FlagsEditor(); + JLabel flagsLabel = new JLabel(displayName, JLabel.TRAILING); + flagsLabel.setVerticalAlignment(SwingConstants.TOP); + layout.setConstraints(flagsLabel, constraints); + c.add(flagsLabel); + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.BOTH; + constraints.anchor = GridBagConstraints.CENTER; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(flagsEditor, constraints); + c.add(flagsEditor); + elements.add(flagsEditor); + flagsLabel.setLabelFor(flagsEditor); + } + + + + + interface ConfigurationElement { + + public boolean isChanged(); + + //apply changes to preferences + public void apply(); + + //optain current value from preferences + public void update(); + + //reset to default value + public void reset(); + + } + + abstract class ColorChooser extends ColorChooserButton implements ConfigurationElement { + + Color originalColor;//the color before any change + String propertyName; + + public ColorChooser(String propertyName) { + this.propertyName = propertyName; + } + + public boolean isChanged() { + return !originalColor.equals(getColor()); + } + + + public abstract void apply(); + public abstract void update(); + + } + + + abstract class FontChooser implements ConfigurationElement, ActionListener { + + Font originalFont; + Font selectedFont; + String propertyName; + JTextField preview; + JButton button; + + public FontChooser(String propertyName) { + this.propertyName = propertyName; + preview = new JTextField(""); + preview.setEditable(false); + button = new JButton("..."); + button.setMargin(new Insets(0, 0, 0, 0)); + button.addActionListener(this); + } + + public boolean isChanged() { + return !originalFont.equals(selectedFont); + } + + public abstract void apply(); + + public abstract void update(); + + public abstract void reset(); + + public JTextField getPreview() { + return preview; + } + + public JButton getButton() { + return button; + }; + + public Font getSelectedFont() { + return selectedFont; + } + + public void setSelectedFont(Font f) { + selectedFont = f; + preview.setText(fontToString(f)); + preview.revalidate(); + } + + public void actionPerformed(ActionEvent e) { + setSelectedFont(FontChooserDialog.show(selectedFont)); + } + + public String fontToString(Font font) { + StringBuffer sb = new StringBuffer(); + sb.append(font.getName()); + sb.append(" "); + sb.append(font.getSize()); + if (font.isBold()) { + sb.append(" bold"); + } + if (font.isItalic()) { + sb.append(" italic"); + } + return sb.toString(); + } + + } + + class FlagsEditor extends FlagsEditorPanel implements ConfigurationElement { + + FlagsSetting originalFlags; + + public FlagsEditor() { + super(null); + } + + public boolean isChanged() { + return !originalFlags.getFlagString().equals(getFlagString()); + } + + public void apply() { + CfgPreferences.getInstance().setFlagsSetting(new FlagsSetting(getFlagString())); + update(); + } + + public void update() { + originalFlags = CfgPreferences.getInstance().getFlagsSetting(); + setFlagString(originalFlags.getFlagString()); + } + + public void reset() { + FlagsSetting defaultFlags = new FlagsSetting(CfgPreferencesDefaults.DEFAULT_FLAGSTRING); + setFlagString(defaultFlags.getFlagString()); + colorButton.setColor(getParent().getBackground()); + } + + } + + class ResetAction extends AbstractAction { + + public ResetAction() { + super("Reset"); + } + + public void actionPerformed(ActionEvent e) { + CFGOptionsPanel.this.loadDefault(); + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanelController.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,63 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.beans.PropertyChangeListener; +import javax.swing.JComponent; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; + +/** + * Controller for the settings page displayed in the options dialog. + * + * @author Bernhard Stiftner + */ +public class CFGOptionsPanelController extends OptionsPanelController { + + CFGOptionsPanel optionsPanel; + + + public void update() { + getOptionsPanel().update(); + } + + public void applyChanges() { + getOptionsPanel().applyChanges(); + } + + public void cancel() { + getOptionsPanel().cancel(); + } + + public boolean isValid() { + return getOptionsPanel().isDataValid(); + } + + public boolean isChanged() { + return getOptionsPanel().isChanged(); + } + + public JComponent getComponent(Lookup masterLookup) { + return getOptionsPanel(); + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + getOptionsPanel().addPropertyChangeListener(l); + } + + //todo: investigate - who removes the changelistener ? + public void removePropertyChangeListener(PropertyChangeListener l) { + getOptionsPanel().removePropertyChangeListener(l); + } + + private CFGOptionsPanel getOptionsPanel() { + if (optionsPanel == null) { + optionsPanel = new CFGOptionsPanel(); + } + return optionsPanel; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferences.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,239 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Font; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.prefs.Preferences; +import javax.swing.event.EventListenerList; +import org.openide.util.NbPreferences; + +/** + * Replacement for old CFGSettings to remove dependency on deprecated SystemOption package + * + * @author Rumpfhuber Stefan + */ +public class CfgPreferences { + public static final String PROP_FLAGS = "flagsPreference"; + public static final String PROP_TEXT_FONT = "textFontPreference"; + public static final String PROP_TEXT_COLOR = "textColorPreference"; + public static final String PROP_NODE_COLOR = "nodeColorPreference"; + public static final String PROP_EDGE_COLOR = "edgeColorPreference"; + public static final String PROP_BORDER_COLOR = "borderColorPreference"; + public static final String PROP_BACK_EDGE_COLOR = "backEdgeColorPreference"; + public static final String PROP_BACKGROUND_COLOR = "backgroundColorPreference"; + public static final String PROP_SELECTION_COLOR_FG = "selectionColorFgPreference"; + public static final String PROP_SELECTION_COLOR_BG = "selectionColorBgPreference"; + public static final String PROP_EXCEPTION_EDGE_COLOR = "exceptionEdgeColorPreference"; + + private static final String PROP_FONTNAME = "_FontFamily"; + private static final String PROP_FONTSIZE = "_FontSize"; + private static final String PROP_FONTSTYLE = "_FontStyle"; + + protected static final String nodeName = "CfgPreferences"; + + private static CfgPreferences instance = new CfgPreferences(); + private EventListenerList listenerList; + + private FlagsSetting flagsSetting; + private Color node_color; + private Color background_color; + private Color backedge_color; + private Color edge_color; + private Color border_color; + private Color exceptionEdgeColor; + private Color text_color; + private Font text_font; + private Color selection_color_fg; + private Color selection_color_bg; + + + private CfgPreferences(){ + listenerList = new EventListenerList(); + init(); + } + + public static CfgPreferences getInstance(){ + return instance; + } + + protected final Preferences getPreferences() { + return NbPreferences.forModule(this.getClass()).node("options").node(nodeName); + } + + + protected void init(){ + Preferences prefs = this.getPreferences(); + String flagString = prefs.get(PROP_FLAGS, CfgPreferencesDefaults.DEFAULT_FLAGSTRING); + flagsSetting = new FlagsSetting(flagString); + node_color = this.getColorProperty(PROP_NODE_COLOR, CfgPreferencesDefaults.DEFAUT_NODE_COLOR); + background_color = this.getColorProperty(PROP_BACKGROUND_COLOR, CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); + backedge_color = this.getColorProperty(PROP_BACK_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); + edge_color = this.getColorProperty(PROP_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); + selection_color_fg= this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + border_color = this.getColorProperty(PROP_BORDER_COLOR, CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); + exceptionEdgeColor = this.getColorProperty(PROP_EXCEPTION_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); + text_color= this.getColorProperty(PROP_TEXT_COLOR, CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); + selection_color_bg = this.getColorProperty(PROP_SELECTION_COLOR_BG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); + selection_color_fg = this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + text_font = this.getFontProperty(PROP_TEXT_FONT, CfgPreferencesDefaults.DEFAULT_TEXT_FONT); + } + + private void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + Object[] listeners = listenerList.getListenerList(); + + PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == PropertyChangeListener.class) { + ((PropertyChangeListener) listeners[i+1]).propertyChange(event); + } + } + } + + private Font getFontProperty(String propName, Font defaultFont){ + Preferences prefs = this.getPreferences(); + String fontName = prefs.get(propName+PROP_FONTNAME, defaultFont.getFamily()); + int fontSize = prefs.getInt(propName+PROP_FONTSIZE, defaultFont.getSize()); + int fontStyle = prefs.getInt(propName+PROP_FONTSTYLE, defaultFont.getStyle()); + return new Font(fontName, fontStyle, fontSize); + } + + private Color getColorProperty(String propName, Color defaultColor){ + Preferences prefs = this.getPreferences(); + int srgb = prefs.getInt(propName, defaultColor.getRGB()); + if(srgb == defaultColor.getRGB()) + return defaultColor; + return new Color(srgb); + } + + public Color getBackedgeColor() { + return backedge_color; + } + + public Color getBackgroundColor() { + return background_color; + } + + public Color getBorderColor() { + return border_color; + } + + public Color getEdgeColor() { + return edge_color; + } + + public Color getExceptionEdgeColor() { + return exceptionEdgeColor; + } + + public Color getNodeColor() { + return node_color; + } + + public Color getSelectionColorForeground() { + return selection_color_fg; + } + + public Color getSelectionColorBackground() { + return selection_color_bg; + } + + public Color getTextColor() { + return text_color; + } + + public Font getTextFont() { + return text_font; + } + + public FlagsSetting getFlagsSetting() { + return flagsSetting; + } + + + public void setFlagsSetting(FlagsSetting flagsSetting) { + FlagsSetting old = this.getFlagsSetting(); + this.flagsSetting = flagsSetting; + Preferences prefs = getPreferences(); + firePropertyChange(PROP_FLAGS, old, flagsSetting); + prefs.put(PROP_FLAGS, flagsSetting.getFlagString()); + } + + + public void setTextFont(Font text_font) { + Font old = this.getTextFont(); + Preferences prefs = getPreferences(); + this.text_font = text_font; + firePropertyChange(PROP_TEXT_FONT, old, text_font); + prefs.put(PROP_TEXT_FONT + PROP_FONTNAME , text_font.getFamily()); + prefs.putInt(PROP_TEXT_FONT + PROP_FONTSIZE, text_font.getSize()); + prefs.putInt(PROP_TEXT_FONT + PROP_FONTSTYLE, text_font.getStyle()); + } + + public void setBackedgeColor(Color backedge_color) { + Color old = this.getBackedgeColor(); + this.backedge_color = backedge_color; + firePropertyChange(PROP_BACK_EDGE_COLOR, old, backedge_color); + getPreferences().putInt(PROP_BACK_EDGE_COLOR, backedge_color.getRGB()); + } + + public void setBackgroundColor(Color bg_color) { + Color old = this.getBackgroundColor(); + background_color = bg_color; + firePropertyChange(PROP_BACKGROUND_COLOR, old, bg_color ); + getPreferences().putInt(PROP_BACKGROUND_COLOR, bg_color.getRGB()); + } + + public void setBorderColor(Color border_color) { + Color old = getBorderColor(); + this.border_color = border_color; + firePropertyChange(PROP_BORDER_COLOR, old, border_color ); + getPreferences().putInt(PROP_BORDER_COLOR, border_color.getRGB()); + } + + public void setEdgeColor(Color edge_color) { + Color old = getEdgeColor(); + this.edge_color = edge_color; + firePropertyChange(PROP_EDGE_COLOR, old, edge_color); + getPreferences().putInt(PROP_EDGE_COLOR, edge_color.getRGB()); + } + + public void setNodeColor(Color node_color) { + Color old = getNodeColor(); + this.node_color = node_color; + firePropertyChange(PROP_NODE_COLOR, old, node_color); + getPreferences().putInt(PROP_NODE_COLOR, node_color.getRGB()); + + } + + public void setSelectionColorForeground(Color selection_color) { + Color old = this.getSelectionColorForeground(); + this.selection_color_fg = selection_color; + firePropertyChange(PROP_SELECTION_COLOR_FG, old, selection_color); + getPreferences().putInt(PROP_SELECTION_COLOR_FG, selection_color.getRGB()); + } + + public void setSelectionColorBackground(Color selection_color) { + Color old = this.getSelectionColorBackground(); + this.selection_color_bg = selection_color; + firePropertyChange(PROP_SELECTION_COLOR_BG, old, selection_color); + getPreferences().putInt(PROP_SELECTION_COLOR_BG, selection_color.getRGB()); + } + + public void setTextColor(Color text_color) { + Color old = this.getTextColor(); + this.text_color = text_color; + firePropertyChange(PROP_TEXT_COLOR, old, text_color); + getPreferences().putInt(PROP_TEXT_COLOR, text_color.getRGB()); + } + + public void setExceptionEdgeColor(Color exceptionEdgeColor) { + Color old = this.getExceptionEdgeColor(); + this.exceptionEdgeColor = exceptionEdgeColor; + firePropertyChange(PROP_EXCEPTION_EDGE_COLOR, old, exceptionEdgeColor); + getPreferences().putInt(PROP_EXCEPTION_EDGE_COLOR, exceptionEdgeColor.getRGB()); + } + + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferencesDefaults.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,23 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Font; + +/** + * Default Configuration for options panel + * + * @author Rumpfhuber Stefan + */ +public final class CfgPreferencesDefaults { + public static final String DEFAULT_FLAGSTRING = "std(224,224,128);osr(224,224,0);ex(128,128,224);sr(128,224,128);llh(224,128,128);lle(224,192,192);plh(128,224,128);bb(160,0,0);ces(192,192,192)"; + public static final Color DEFAUT_NODE_COLOR = new Color(208, 208, 208); + public static final Color DEFAULT_BACKGROUND_COLOR = new Color(255, 255, 255); + public static final Color DEFAULT_BACKEDGE_COLOR = new Color(160, 0, 0); + public static final Color DEFAULT_EDGE_COLOR = new Color(0, 0, 0); + public static final Color DEFAULT_SELECTION_COLOR_FOREGROUND = Color.BLUE; + public static final Color DEFAULT_SELECTION_COLOR_BACKGROUND = Color.BLUE; + public static final Color DEFAULT_BORDER_COLOR = new Color(0, 0, 0); + public static final Color DEFAULT_EXCEPTIONEDGE_COLOR = new Color(0, 0, 160); + public static final Color DEFAULT_TEXT_COLOR = new Color(0, 0, 0); + public static final Font DEFAULT_TEXT_FONT = new Font("Dialog", Font.PLAIN, 18); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/ColorChooserButton.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,94 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JColorChooser; + +/** + * A color selection button. It will preview the currently selected color as + * an icon. Clicking the button will bring up the JColorChooser dialog. + * + * @author Bernhard Stiftner + */ +public class ColorChooserButton extends JButton implements ActionListener { + + public static final Dimension ICON_SIZE = new Dimension(24, 8); + + Color color; + boolean colorChooserEnabled = true; // bring up dialog when clicked? + + + public ColorChooserButton() { + this(Color.black); + } + + public ColorChooserButton(Color defaultColor) { + setIcon(new ColorBoxIcon()); + addActionListener(this); + color = defaultColor; + Dimension size = new Dimension(ICON_SIZE); + size.width += getInsets().left + getInsets().right; + size.height += getInsets().top + getInsets().bottom; + setPreferredSize(size); + } + + public void setColor(Color newColor) { + color = newColor; + repaint(); + } + + public Color getColor() { + return color; + } + + public boolean isColorChooserEnabled() { + return colorChooserEnabled; + } + + public void setColorChooserEnabled(boolean enabled) { + this.colorChooserEnabled = enabled; + } + + public void actionPerformed(ActionEvent e) { + if (!colorChooserEnabled) { + return; + } + + Color c = JColorChooser.showDialog(this, "Choose color", color); + if (c != null) { + setColor(c); + } + } + + class ColorBoxIcon implements Icon { + + public int getIconWidth() { + return ICON_SIZE.width; + } + + public int getIconHeight() { + return ICON_SIZE.height; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Color oldColor = g.getColor(); + g.translate(x, y); + + g.setColor(color); + g.fillRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); + + g.setColor(Color.black); + g.drawRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); + + g.translate(-x, -y); + g.setColor(oldColor); + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsEditorPanel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,247 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Enumeration; +import java.util.StringTokenizer; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +/** + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class FlagsEditorPanel extends JPanel implements ActionListener, + ListSelectionListener { + + FlagListModel listModel; + JList list; + ColorChooserButton colorButton; + JButton newButton; + JButton removeButton; + JButton upButton; + JButton downButton; + + + /** Creates a new instance of FlagsEditorPanel */ + public FlagsEditorPanel(String flagString) { + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + listModel = new FlagListModel(flagString); + list = new JList(listModel); + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.addListSelectionListener(this); + add(new JScrollPane(list)); + + add(Box.createHorizontalStrut(3)); + + Box buttonBox = new Box(BoxLayout.Y_AXIS); + buttonBox.add(colorButton = new ColorChooserButton()); + buttonBox.add(newButton = new JButton("New...")); + buttonBox.add(removeButton = new JButton("Remove")); + buttonBox.add(upButton = new JButton("Up")); + buttonBox.add(downButton = new JButton("Down")); + buttonBox.add(Box.createVerticalGlue()); + add(buttonBox); + layoutButtonContainer(buttonBox); + + colorButton.setColorChooserEnabled(false); + colorButton.addActionListener(this); + newButton.addActionListener(this); + removeButton.addActionListener(this); + upButton.addActionListener(this); + downButton.addActionListener(this); + + selectionChanged(-1); // no selection + } + + /** + * Ugly helper to make a nice layout for vertically aligned buttons. + */ + private static void layoutButtonContainer(JComponent buttonContainer) { + int width = 0; + int height = 0; + + for (int i=0; i<buttonContainer.getComponentCount(); i++) { + Component c = buttonContainer.getComponent(i); + if (c instanceof JButton) { + JButton b = (JButton)c; + if (width < b.getPreferredSize().width) { + width = b.getPreferredSize().width; + } + if (height < b.getPreferredSize().height) { + height = b.getPreferredSize().height; + } + } + } + + Dimension commonButtonSize = new Dimension(width, height); + + for (int i=0; i<buttonContainer.getComponentCount(); i++) { + Component c = buttonContainer.getComponent(i); + if (c instanceof JButton) { + JButton b = (JButton)c; + b.setMinimumSize(commonButtonSize); + b.setPreferredSize(commonButtonSize); + b.setMaximumSize(commonButtonSize); + } + } + + } + + public String getFlagString() { + return listModel.getFlagString(); + } + + public void setFlagString(String flagString) { + listModel.setFlagString(flagString); + } + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + if (source == colorButton) { + changeColor(); + } else if (source == newButton) { + String s = JOptionPane.showInputDialog(this, + "Type in the flag which should fill the block with a specific color"); + if (s == null) { + return; + } + s = s.replace('(', ' '); + s = s.replace(';', ' '); + int index = list.getSelectedIndex()+1; + listModel.insertElementAt(new FlagListItem(s, Color.WHITE), index); + } else if (source == removeButton) { + listModel.removeElementAt(list.getSelectedIndex()); + } else if (source == upButton) { + int index = list.getSelectedIndex(); + if (index == 0) { + return; + } + Object o = listModel.getElementAt(index); + listModel.removeElementAt(index); + listModel.insertElementAt(o, index-1); + } else if (source == downButton) { + int index = list.getSelectedIndex(); + if (index >= listModel.size()-1) { + return; + } + Object o = listModel.getElementAt(index); + listModel.removeElementAt(index); + listModel.insertElementAt(o, index+1); + } + } + + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) { + return; // another event will be fired soon + } + selectionChanged(list.getSelectedIndex()); + } + + protected void selectionChanged(int index) { //index is -1 if there is no selection + colorButton.setEnabled(index >= 0); + removeButton.setEnabled(index >= 0); + upButton.setEnabled(index > 0); + downButton.setEnabled(index >= 0 && index < listModel.getSize()-1); + + if (index >= 0) { + FlagListItem item = (FlagListItem)listModel.elementAt(index); + colorButton.setColor(item.getColor()); + list.setSelectedIndex(index); + } else { + colorButton.setColor(getBackground()); + } + } + + protected void changeColor() { + int selectedIndex = list.getSelectedIndex(); + FlagListItem item = (FlagListItem)listModel.elementAt(selectedIndex); + Color c = JColorChooser.showDialog(this, "Choose color", item.getColor()); + + if (c != null) { + item.setColor(c); + colorButton.setColor(c); + } + } + + class FlagListModel extends DefaultListModel { + + public FlagListModel(String flagString) { + if (flagString != null) { + setFlagString(flagString); + } + } + + public String getFlagString() { + StringBuffer sb = new StringBuffer(); + Enumeration e = elements(); + while (e.hasMoreElements()) { + FlagListItem item = (FlagListItem)e.nextElement(); + sb.append(item.getFlagString()); + Color c = item.getColor(); + sb.append("(").append(c.getRed()).append(",").append(c.getGreen()).append(",").append(c.getBlue()).append(")"); + if (e.hasMoreElements()) { + sb.append(";"); + } + } + return sb.toString(); + } + + public void setFlagString(String flagString) { + clear(); + StringTokenizer st = new StringTokenizer(flagString, ";"); + while (st.hasMoreTokens()) { + String s = st.nextToken(); + String flag = s.split("\\(")[0]; + Color color = FlagsSetting.toColor(s); + addElement(new FlagListItem(flag, color)); + } + } + + } + + class FlagListItem { + + Color color; + String flagString; + + public FlagListItem(String flagString, Color color) { + this.flagString = flagString; + this.color = color; + } + + public Color getColor() { + return color; + } + + public String getFlagString() { + return flagString; + } + + public void setColor(Color c) { + color = c; + } + + @Override + public String toString() { + return flagString; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsSetting.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,85 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.io.Serializable; +import java.util.Hashtable; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class FlagsSetting implements Serializable { + + private Hashtable<String, Color> flag2color; + private Hashtable<String, Integer> priority; + private String flagString; + + + public FlagsSetting(String flagString) { + this.flagString = flagString; + flag2color = new Hashtable<>(); + priority = new Hashtable<>(); + String[] flags = flagString.split(";"); + + int z = 0; + for(String s : flags) { + String flag = s.split("\\(")[0]; + Color c = toColor(s); + flag2color.put(flag, c); + priority.put(flag, z); + z++; + } + } + + public Color getColor(List<String> strings) { + int minPriority = Integer.MAX_VALUE; + Color result = null; + + for(String s : strings) { + Color curColor = flag2color.get(s); + if(curColor != null) { + int curPriority = priority.get(s); + if(curPriority < minPriority) { + minPriority = curPriority; + result = curColor; + } + } + } + + return result; + } + + public static Color toColor(String s) { + String sArr[] = s.split("\\("); + String Color = sArr[1].substring(0, sArr[1].length() - 1); + String ColorArr[] = Color.split(","); + int r = Integer.parseInt(ColorArr[0]); + int g = Integer.parseInt(ColorArr[1]); + int b = Integer.parseInt(ColorArr[2]); + return new Color(r, g, b); + } + + public String getFlagString() { + return flagString; + } + + @Override + public boolean equals(Object o) { + if(o==null) + return false; + return this.toString().equals(o.toString()); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 19 * hash + (this.flagString != null ? this.flagString.hashCode() : 0); + return hash; + } + + @Override + public String toString(){ + return "FlagSetting[" + flagString + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FontChooserDialog.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,37 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Font; +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; + +/** + * + * @author Bernhard Stiftner + */ +public class FontChooserDialog { + + /* + * Displays a font selection dialog. + * @return The selected font, or the initial font if the user chose + * to bail out + */ + public static Font show(Font initialFont) { + PropertyEditor pe = PropertyEditorManager.findEditor(Font.class); + if (pe == null) { + throw new RuntimeException("Could not find font editor component."); + } + pe.setValue(initialFont); + DialogDescriptor dd = new DialogDescriptor( + pe.getCustomEditor(), + "Choose Font"); + DialogDisplayer.getDefault().createDialog(dd).setVisible(true); + if (dd.getValue() == DialogDescriptor.OK_OPTION) { + Font f = (Font)pe.getValue(); + return f; + } + return initialFont; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/BezierWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,345 @@ +package at.ssw.visualizer.cfg.visual; + +import org.netbeans.api.visual.widget.ConnectionWidget; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.util.List; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +/** + * In comparison to the default ConnectionWidget this class is able to connect + * Widgets with a curve instead of a straight line sequence. Between two control + * points a curve is painted as cubic bezier curve the control points are + * calculated automaticaly they depend on the position of the prior- and the + * following control points. + * In conjunction with a suitable router the connection will be a straight line + * or a curve depending on the amount and the position of the controlpoints. + * Controlpoints supplied by the router, are treated as curve intersection points. + * For Reflexive edges the router doesn`t need to supply controlpoints, they + * get painted by this class automatically. If the router supplys more as 2 + * control points for a recursive edge the edge gets painted with the default + * curve approximation algorithm. + */ +public class BezierWidget extends ConnectionWidget { + private static final double BEZIER_SCALE = 0.3; + private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy + + private GraphScene scene=null; + + public BezierWidget(Scene scene) { + super(scene); + } + + public BezierWidget(GraphScene scene) { + super(scene); + this.scene=scene; + } + + + private boolean isReflexive(){ + return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); + } + + + @Override + protected Rectangle calculateClientArea() { + Rectangle bounds = null; + if(this.getControlPoints().size()>0){ + for(Point p : this.getControlPoints()){ + if(bounds==null) + bounds = new Rectangle(p); + else + bounds.add(p); + } + bounds.grow(5,5); + } + if(isReflexive()){ + Widget related = this.getTargetAnchor().getRelatedWidget(); + bounds = related.convertLocalToScene(related.getBounds()); + bounds.grow(10, 10); + } + if(bounds==null) + bounds = super.calculateClientArea(); + + return bounds; + } + + + + //returns prefered location for an edge -1 for left and 1 for right + private int edgeBalance(Widget nodeWidget) { + if(scene == null) + return 1; + + Point nodeLocation = nodeWidget.getLocation(); + int left = 0, right = 0; + + Object node = scene.findObject(nodeWidget); + + for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges + ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); + + if(cw != this) { + Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); + + Point location; + if(targetNodeWidget == nodeWidget) { + Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); + location = sourceNodeWidget.getLocation(); + } else { + location = targetNodeWidget.getLocation(); + } + + if(location.x < nodeLocation.x) + left++; + else + right++; + } + } + if(left < right) + return -1; + else + return 1; + } + + + + + /** + * if the edge is reflexive its painted as a cyclic edge + * if there are 2 controlpoints the connection is painted as a straight line from the source to the targetanchor + * if there are more as 2 controlpoints the connection path between 2 control points is painted as bezier curve + */ + + @Override + protected void paintWidget () { + + List<Point> contrPoints = this.getControlPoints(); + int listSize = contrPoints.size(); + + Graphics2D gr = getGraphics (); + + if (listSize <= 2) { + if(isReflexive()) { //special case for reflexive connection widgets + Widget related = this.getTargetAnchor().getRelatedWidget(); + int position = this.edgeBalance(related); + Rectangle bounds = related.convertLocalToScene(related.getBounds()); + gr.setColor (getLineColor()); + Point first = new Point(); + Point last = new Point(); + double centerX = bounds.getCenterX(); + first.x = (int) (centerX + bounds.width / 4); + first.y = bounds.y + bounds.height; + last.x = first.x; + last.y = bounds.y; + + gr.setStroke(this.getStroke()); + + double cutDistance = this.getTargetAnchorShape().getCutDistance(); + double anchorAngle = Math.PI/-3.0; + double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); + double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); + int ydiff=first.y-last.y; + int endy = -ydiff; + double height=bounds.getHeight(); + double cy = height/4.0; + double cx=bounds.getWidth()/5.0; + double dcx = cx*2; + GeneralPath gp = new GeneralPath(); + gp.moveTo(0, 0); + gp.quadTo(0, cy, cx, cy); + gp.quadTo(dcx, cy, dcx, -height/2.0); + gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); + gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); + + AffineTransform af = new AffineTransform(); + AnchorShape anchorShape = this.getTargetAnchorShape(); + + if(position < 0) { + first.x = (int) (centerX - bounds.width / 4); + af.translate(first.x, first.y); + af.scale(-1.0, 1.0); + last.x = first.x; + } else { + af.translate(first.x, first.y); + } + Shape s = gp.createTransformedShape(af); + gr.draw(s); + + if (last != null) { + AffineTransform previousTransform = gr.getTransform (); + gr.translate (last.x, last.y); + + if(position < 0) + gr.rotate(Math.PI - anchorAngle); + else + gr.rotate (anchorAngle); + + anchorShape.paint (gr, false); + gr.setTransform (previousTransform); + } + + } else { + super.paintWidget(); + } + return; + } + + //bezier curve... + GeneralPath curvePath = new GeneralPath(); + Point lastControlPoint = null; + double lastControlPointRotation = 0.0; + + Point prev = null; + for (int i = 0; i < listSize - 1; i++) { + Point cur = contrPoints.get(i); + Point next = contrPoints.get(i + 1); + Point nextnext = null; + if (i < listSize - 2) { + nextnext = contrPoints.get(i + 2); + } + + double len = cur.distance(next); + double scale = len * BEZIER_SCALE; + Point bezierFrom = null;//first ControlPoint + Point bezierTo = null;//second ControlPoint + + if (prev == null) { + //first point + curvePath.moveTo(cur.x, cur.y);//startpoint + bezierFrom = cur; + } else { + bezierFrom = new Point(next.x - prev.x, next.y - prev.y); + bezierFrom = scaleVector(bezierFrom, scale); + bezierFrom.translate(cur.x, cur.y); + } + + if (nextnext == null) {//next== last point (curve to) + lastControlPoint=next; + bezierTo = next;//set 2nd intermediate point to endpoint + GeneralPath lastseg = this.subdivide(cur, bezierFrom, bezierTo, next); + if(lastseg != null) + curvePath.append(lastseg, true); + break; + } else { + bezierTo = new Point(cur.x - nextnext.x, cur.y - nextnext.y); + bezierTo = scaleVector(bezierTo, scale); + bezierTo.translate(next.x, next.y); + } + + curvePath.curveTo( + bezierFrom.x, bezierFrom.y,//controlPoint1 + bezierTo.x, bezierTo.y,//controlPoint2 + next.x,next.y + ); + prev = cur; + } + Point2D cur = curvePath.getCurrentPoint(); + Point next = lastControlPoint; + + lastControlPointRotation = //anchor anchorAngle + Math.atan2 (cur.getY() - next.y, cur.getX() - next.x); + + Color previousColor = gr.getColor(); + gr.setColor (getLineColor()); + Stroke s = this.getStroke(); + gr.setStroke(s); + gr.setColor(this.getLineColor()); + gr.draw(curvePath); + + AffineTransform previousTransform = gr.getTransform (); + gr.translate (lastControlPoint.x, lastControlPoint.y); + gr.rotate (lastControlPointRotation); + AnchorShape targetAnchorShape = this.getTargetAnchorShape(); + targetAnchorShape.paint (gr, false); + gr.setTransform (previousTransform); + + //paint ControlPoints if enabled + if (isPaintControlPoints()) { + int last = listSize - 1; + for (int index = 0; index <= last; index ++) { + Point point = contrPoints.get (index); + previousTransform = gr.getTransform (); + gr.translate (point.x, point.y); + if (index == 0 || index == last) + getEndPointShape().paint (gr); + else + getControlPointShape().paint (gr); + gr.setTransform (previousTransform); + } + + } + gr.setColor(previousColor); + } + + + + private GeneralPath subdivide (Point b0, Point b1, Point b2, Point b3) { + double cutDistance = getTargetAnchorShape().getCutDistance(); + double minDistance = cutDistance - ENDPOINT_DEVIATION; + /** + * if the cutDistance is valid the last segment of the curve + * gets reduced by subdivision until the distance of the endpoint(epDistance) + * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) + */ + if(cutDistance > minDistance && minDistance > 0 ) { + GeneralPath path = new GeneralPath(); + + path.moveTo(b0.x, b0.y); + + CubicCurve2D.Double left = new CubicCurve2D.Double( + b0.x, b0.y, + b1.x, b1.y, + b2.x, b2.y, + b3.x, b3.y); + + CubicCurve2D right=new CubicCurve2D.Double(); + left.subdivide(left, right); + double distance = b3.distance(left.getP2()); + //if the distance is bigger as the cutDistance the left segment is added + //and the right segment is divided again + while(distance>cutDistance){ + path.append(left, true); + right.subdivide(left, right); + distance = b3.distance(left.getP2()); + //if the devision removed to much the left segment is divided + while(distance < minDistance) { + //changes the distance to ~ (distance+distance/2) + left.subdivide(left, right); + distance = b3.distance(left.getP2()); + } + } + //append the last segment with (minDistance < distance < cutDistance) + //actually we should check if the a division happend, but this is very unlikly + path.append(left, true); + return path; + } + return null; + } + + + + + + private static Point scaleVector(Point vector, double len) { + double scale = Math.sqrt(vector.x * vector.x + vector.y * vector.y); + if(scale==0.0) return vector; + scale = len / scale; + return new Point( + Math.round(vector.x * (float)scale), + Math.round(vector.y * (float)scale)); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,360 @@ +package at.ssw.visualizer.cfg.visual; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.Widget; + +/** + * Router Class with Collision Detection + * + * + * The returned path is a straight line there is no node widget between the source and the target node, + * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. + * The algorithm for the search of this path is limited by a fixed number of iterations defined in + * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the + * path returned contains at least 1 collision with a nodewidget. + */ + +public class PolylineRouter implements Router { + private static final float FACTOR = 0.70f; + + private static final int HEXPAND = 3; + private static final int VEXPAND = 3; + private static final int NUMBER_OF_ITERATIONS = 8; + + WidgetCollisionCollector collector; + + + public PolylineRouter(WidgetCollisionCollector collector){ + this.collector=collector; + } + + + public List<Point> routeConnection(final ConnectionWidget widget) { + if(!widget.isVisible()) return Collections.<Point>emptyList(); + + Anchor sourceAnchor = widget.getSourceAnchor(); + Anchor targetAnchor = widget.getTargetAnchor(); + + if(sourceAnchor == null || targetAnchor == null) + return null; + + Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); + + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + + + if(sourceWidget == targetWidget){//reflexive edges doesnt need any path + return Collections.<Point>emptyList(); + } + + List<Widget> nodeWidgets = new ArrayList<>(); + + if(collector != null){ + collector.collectCollisions(nodeWidgets); + //source and target widget are not treatet as obstacle + nodeWidgets.remove(sourceWidget); + nodeWidgets.remove(targetWidget); + } + + List<Point> controlPoints = optimize(nodeWidgets, widget, start, end); + + //size==2 => straight line + //size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it + if(controlPoints.size() > 3) + controlPoints = simplify(nodeWidgets, controlPoints); + + return controlPoints; + } + + + private List<Point> simplify(Collection<Widget> nodeWidgets, List<Point> list) { + List<Point> result = new ArrayList<>(); + result.add( list.get(0) );//add startpoint + for (int i = 1; i < list.size(); i++) { + Point prev = list.get(i - 1); + for (int j = i; j < list.size(); j++) { + Point cur = list.get(j); + if (!intersects(nodeWidgets, prev, cur)) { + i = j; + } + } + result.add(list.get(i)); + } + return result; + } + + /** + * Computates the Anchorposition like the Rectangular anchor for a + * given widget as source/target and a controlpoint as opposit anchorposition + */ + + private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { + Rectangle bounds = relatedWidget.getBounds(); + Point relatedLocation = relatedWidget.getLocation();//center of the widget + + if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) + return relatedLocation; + + float dx = controlPoint.x - relatedLocation.x; + float dy = controlPoint.y - relatedLocation.y; + + float ddx = Math.abs (dx) / (float) bounds.width; + float ddy = Math.abs (dy) / (float) bounds.height; + + float scale = 0.5f / Math.max (ddx, ddy); + + Point point = new Point (Math.round (relatedLocation.x + scale * dx), + Math.round (relatedLocation.y + scale * dy)); + return point; + } + + + + private List<Point> optimize(Collection<Widget> nodeWidgets, ConnectionWidget connWidget, Point start, Point end) { + + List<Point> list = new ArrayList<>(); + list.add(start); + list.add(end); + + boolean progress = true; + + for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { + progress = false; + List<Point> newList = new ArrayList<>(); + for (int i = 0; i < list.size() - 1 ; i++) { + Point cur = list.get(i); + Point next = list.get(i + 1); + newList.add(cur); + List<Point> intermediate = optimizeLine(nodeWidgets, cur, next); + if (intermediate != null && intermediate.size() > 0) { + progress = true; + newList.addAll(intermediate);//insert new controlpoints between cur and next + } + } + newList.add(list.get(list.size()-1));//add endpoint of the polyline + list = newList; + + } + + if(list.size() > 2) { + Widget sourceNode = connWidget.getSourceAnchor().getRelatedWidget(); + Widget targetNode = connWidget.getTargetAnchor().getRelatedWidget(); + Rectangle sourceBounds = sourceNode.convertLocalToScene(sourceNode.getBounds()); + Rectangle targetBounds = targetNode.convertLocalToScene(targetNode.getBounds()); + sourceBounds.grow(HEXPAND, VEXPAND); + + /** + * add only points which are not intersecting the source and the target + * widget bounds caused by invalid bad anchor positions. The first + * and the last point is ignored cause the anchor is recalculated + * anyway. + */ + ArrayList<Point> tmp = new ArrayList<>(); + int listSize=list.size(); + tmp.add(list.get(0)); + int i=0; + while(++i < listSize-1) { + Point p = list.get(i); + if(!sourceBounds.contains(p) || !targetBounds.contains(p)) + tmp.add(p); + } + + tmp.add(list.get(i)); + if(tmp.size() < 3) + return tmp; + + list=tmp; + //calculate a proper anchor position using the second/penultimate controlpoint for start/end + start = this.computateAnchorPosition(connWidget.getSourceAnchor().getRelatedWidget(), list.get(1)); + end = this.computateAnchorPosition(connWidget.getTargetAnchor().getRelatedWidget(), list.get(list.size()-2)); + list.set(0,start); + list.set(list.size()-1, end); + } + return list; + } + + + /** + * trys to optimize a line from p1 to p2 to avoid collisions with node widgets + * returns null if the line doesn`t intersect with any nodewidget + * or a list with immediate points between p1 and p2 to avoid collisions + */ + private List<Point> optimizeLine(Collection<Widget> nodeWidgets, Point p1, Point p2) { + Line2D line = new Line2D.Double(p1, p2); + + for(Widget w : nodeWidgets ) { + if( w.isVisible() ) { + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + + if (!line.intersects(r)) continue; + + Point location = w.getLocation(); + int distx = (int) (r.width * FACTOR); + int disty = (int) (r.height * FACTOR); + + int minIntersects = Integer.MAX_VALUE; + int min = Integer.MAX_VALUE; + List<Point> minSol = null; + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + if (i != 0 || j != 0) { + Point cur = new Point(location.x + i * distx, location.y + j * disty); + List<Point> list1 = new ArrayList<>(); + list1.add(p1); + list1.add(cur); + list1.add(p2); + int crossProd = Math.abs(crossProduct(p1, cur, p2)); + if (!intersects(w, list1)) { + Line2D line1 = new Line2D.Float(p1, cur); + Line2D line2 = new Line2D.Float(p2, cur); + int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2); + + if (curIntersects < minIntersects + || (curIntersects == minIntersects && crossProd < min)) { + minIntersects = curIntersects; + min = crossProd; + minSol = new ArrayList<>(); + minSol.add(cur); + } + } + + if (i == 0 || j == 0) { + Point cur1, cur2; + if (i == 0) { + cur1 = new Point(location.x + distx/2, location.y + j * disty); + cur2 = new Point(location.x - distx/2, location.y + j * disty); + } else { // (j == 0) + cur1 = new Point(location.x + i * distx, location.y + disty/2); + cur2 = new Point(location.x + i * distx, location.y - disty/2); + } + + Point vec1 = new Point(p1.x - cur1.x, p1.y - cur1.y); + int offset1 = vec1.x * vec1.x + vec1.y * vec1.y; + + Point vec2 = new Point(p1.x - cur2.x, p1.y - cur2.y); + int offset2 = vec2.x * vec2.x + vec2.y * vec2.y; + + if (offset2 < offset1) { + Point tmp = cur1; + cur1 = cur2; + cur2 = tmp; + } + + List<Point> list2 = new ArrayList<>(); + list2.add(p1); + list2.add(cur1); + list2.add(cur2); + list2.add(p2); + + int cross1 = crossProduct(p1, cur1, cur2); + int cross2 = crossProduct(cur1, cur2, p2); + + if (cross1 > 0) { + cross1 = 1; + } else if (cross1 < 0) { + cross1 = -1; + } + + if (cross2 > 0) { + cross2 = 1; + } else if (cross2 < 0) { + cross2 = -1; + } + if ((cross1 == cross2 || cross1 == 0 || cross2 == 0) && !intersects(w, list2)) { + Line2D line1 = new Line2D.Float(p1, cur1); + Line2D line2 = new Line2D.Float(cur1, cur2); + Line2D line3 = new Line2D.Float(p2, cur2); + int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2, line3); + + // This is a bit better + crossProd--; + + if (curIntersects < minIntersects + || (curIntersects == minIntersects && crossProd < min)) { + minIntersects = curIntersects; + min = crossProd; + minSol = new ArrayList<>(); + minSol.add(cur1); + minSol.add(cur2); + } + } + } + } + } + } + if (minSol != null) { + return minSol; + } + } + } + return null; + } + + + + private int countNodeIntersections(Collection<Widget> nodeWidgets, Line2D... lines){ + int count=0; + for(Widget nw : nodeWidgets){ + if(nw.isVisible()) { + Rectangle bounds = nw.convertLocalToScene(nw.getBounds()); + for( Line2D line : lines){ + if(line.intersects(bounds)) + count++; + } + } + } + return count; + } + + + private boolean intersects(Collection<Widget> nodeWidgets, Point start, Point end) { + List<Point> pointlist = new ArrayList<>(); + pointlist.add(start); + pointlist.add(end); + + for(Widget w : nodeWidgets){ + if(w.isVisible() && intersects(w, pointlist)) { + return true; + } + } + return false; + } + + + private boolean intersects(Widget w, List<Point> list) { + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + return intersects(list, r); + } + + + private boolean intersects(List<Point> list, Rectangle rect){ + for(int i=1; i < list.size(); i++) { + Point cur = list.get(i-1); + Point next = list.get(i); + if(rect.intersectsLine(cur.x, cur.y, next.x, next.y)) + return true; + } + return false; + } + + + private int crossProduct(Point p1, Point p2, Point p3) { + Point off1 = new Point(p1.x - p2.x, p1.y - p2.y); + Point off2 = new Point(p3.x - p2.x, p3.y - p2.y); + return (off1.x * off2.y - off1.y * off2.x); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouterV2.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,393 @@ +package at.ssw.visualizer.cfg.visual; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.Widget; + +/** + * Router Class with Collision Detection + * + * + * The returned path is a straight line there is no node widget between the source and the target node, + * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. + * The algorithm for the search of this path is limited by a fixed number of iterations defined in + * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the + * path returned contains at least 1 collision with a nodewidget. + * + * This class intend to solve the same problem as the class PolyLineRouter but + * uses slightly different methods. + * + uses another algorithm for solving the collision. + * + the obstacle bounds are calulated in advance to avoid a recalculation. + * - there is no heuristic, the shortest path around the widget is choosen asap. + * + * + * + */ + +public class PolylineRouterV2 implements Router { + private static final int HEXPAND = 3; + private static final int VEXPAND = 3; + private static final int NUMBER_OF_ITERATIONS = 8; + + WidgetCollisionCollector collector; + + + public PolylineRouterV2(WidgetCollisionCollector collector){ + this.collector=collector; + } + + + public List<Point> routeConnection(final ConnectionWidget widget) { + if(!widget.isVisible()) return Collections.<Point>emptyList(); + + Anchor sourceAnchor = widget.getSourceAnchor(); + Anchor targetAnchor = widget.getTargetAnchor(); + + if(sourceAnchor == null || targetAnchor == null) + return null; + + Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); + + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + + + if(sourceWidget == targetWidget){//reflexive edges doesnt need any path + return Collections.<Point>emptyList(); + } + + + Point srcCenter = this.getSceneLocation(sourceWidget); + Point tarCenter = this.getSceneLocation(targetWidget); + + List<Widget> widgetObstacles = new ArrayList<>(); + + if(collector != null){ + collector.collectCollisions(widgetObstacles); + } + + List<Rectangle> obstacles = new ArrayList<>(widgetObstacles.size()); + this.collectObstacles(obstacles, widgetObstacles, widget); + + + List<Point> controlPoints = optimize(obstacles, srcCenter, tarCenter); +// size==2 => straight line +// size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it + if(controlPoints.size() > 3){ + Point rstart = this.computateAnchorPosition(sourceWidget, controlPoints.get(1)); + Point rend = this.computateAnchorPosition(targetWidget, controlPoints.get(controlPoints.size()-2)); + controlPoints.set(0, rstart); + controlPoints.set(controlPoints.size()-1, rend); + controlPoints = simplify(obstacles, controlPoints); + } else if (controlPoints.size()>=2){ + //use old points + controlPoints.set(0, start); + controlPoints.set(controlPoints.size()-1, end); + + } + return controlPoints; + } + + + private int collectObstacles(List<Rectangle> colrects, List<Widget> colwidgets , ConnectionWidget cw){ + int count=0; + Anchor sourceAnchor = cw.getSourceAnchor(); + Anchor targetAnchor = cw.getTargetAnchor(); + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + Point start = sourceAnchor.compute(cw.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(cw.getTargetAnchorEntry()).getAnchorSceneLocation(); + + for(Widget w : colwidgets){ + + if(w==sourceWidget || w == targetWidget) continue; + + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + if(r.intersectsLine(start.x,start.y,end.x,end.y)) + count++; + colrects.add(r); + } + return count; + } + + + private Point center (Rectangle bounds) { + return new Point (bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); + } + + /** + * Returns the scene location of a related widget. + * bounds might be null if the widget was not added to the scene + * @return the scene location; null if no related widget is assigned + */ + public Point getSceneLocation (Widget relatedWidget) { + if (relatedWidget != null) { + Rectangle bounds = relatedWidget.getBounds (); + if(bounds != null) + return center(relatedWidget.convertLocalToScene(bounds)); + } + return null; + } + + /** + * Computates the Anchorposition like the Rectangular anchor for a + * given widget as source/target and a controlpoint as opposit anchorposition + */ + + private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { + Rectangle bounds = relatedWidget.getBounds(); + + //todo: fix, center of widget must be cacluated trough the bounds + //since there are some wheird widgets where the location is not the center of the widget + Point relatedLocation = relatedWidget.getLocation();//center of the widget + + if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) + return relatedLocation; + + float dx = controlPoint.x - relatedLocation.x; + float dy = controlPoint.y - relatedLocation.y; + + float ddx = Math.abs (dx) / (float) bounds.width; + float ddy = Math.abs (dy) / (float) bounds.height; + + float scale = 0.5f / Math.max (ddx, ddy); + + Point point = new Point (Math.round (relatedLocation.x + scale * dx), + Math.round (relatedLocation.y + scale * dy)); + return point; + } + + private List<Point> simplify(List<Rectangle> obstacles, List<Point> list) { + List<Point> result = new ArrayList<>(list.size()); + result.add( list.get(0) );//add startpoint + for (int i = 1; i < list.size(); i++) { + Point prev = list.get(i - 1); + for (int j = i; j < list.size(); j++) { + Point cur = list.get(j); + if (!intersects(obstacles, prev, cur)) { + i = j; + } + } + result.add(list.get(i)); + } + return result; + } + + private List<Point> optimize(List<Rectangle> nodeWidgets, Point start, Point end) { + + List<Point> list = new ArrayList<>(); + list.add(start); + list.add(end); + + boolean progress = true; + + for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { + progress = false; + List<Point> newList = new ArrayList<>(); + for (int i = 0; i < list.size() - 1 ; i++) { + Point cur = list.get(i); + Point next = list.get(i + 1); + newList.add(cur); + List<Point> intermediate = optimizeLine(nodeWidgets, cur, next); + if (intermediate != null && intermediate.size() > 0) { + progress = true; + newList.addAll(intermediate);//insert new controlpoints between cur and next + } + } + newList.add(list.get(list.size()-1));//add endpoint of the polyline + list = newList; + + } + + return list; + } + + + /** + * trys to optimize a line from p1 to p2 to avoid collisions with rectangles + * returns null if the line doesn`t intersect with any nodewidget or + * if the obstacles are overlapping + * ---------------------------------------------------------------------- + * if the collision is solved it returns a list with immediate points + * between p1 and p2. The points are taken from hull points of and grown + * rectangle. + */ + private List<Point> optimizeLine(List<Rectangle> obstacles, Point p1, Point p2) { + Line2D line = new Line2D.Double(p1, p2); + boolean inbounds=false; + Rectangle ibr=null; + ArrayList<Point> sol = new ArrayList<>(); + boolean leftIntersection; + boolean rightIntersection; + boolean bottomIntersection; + boolean topIntersection; + Point interLeft=new Point(); + Point interRight=new Point(); + Point interBot=new Point(); + Point interTop=new Point(); + + + + for(Rectangle r : obstacles ) { + if (!line.intersects(r)) continue; + + int w=r.width+2; + int h=r.height+2; + Point topLeft = r.getLocation(); + topLeft.x-=1; + topLeft.y-=1; + Point topRight = new Point(topLeft.x+w, topLeft.y); + Point bottomLeft = new Point(topLeft.x, topLeft.y+h); + Point bottomRight = new Point(topRight.x, bottomLeft.y); + leftIntersection = findIntersectionPoint(p1, p2, topLeft, bottomLeft, interLeft); + rightIntersection = findIntersectionPoint(p1, p2, topRight, bottomRight, interRight); + bottomIntersection = findIntersectionPoint(p1, p2, bottomLeft, bottomRight, interBot); + topIntersection = findIntersectionPoint(p1, p2, topLeft, topRight, interTop); + + //Intersection points are not used yet. This could be actually a + //good approach to avoid additional collisions because it would be + //still the same vector. + + if(leftIntersection) { + if(topIntersection) {//left and top + sol.add(topLeft); + } + else if(bottomIntersection){//left and bottom + sol.add(bottomLeft); + } + else if(rightIntersection){//left and right + double disttl = topLeft.distance(p1); + double distbl = bottomLeft.distance(p1); + if(disttl > distbl){ + //pass at the bottom + double distbr = bottomRight.distance(p1); + if(distbl < distbr){ + //from the left to the right + sol.add(bottomLeft); + sol.add(bottomRight); + } else { + //from the right to the left + sol.add(bottomRight); + sol.add(bottomLeft); + } + } else { + //pass at the top + double disttr = topRight.distance(p1); + if(disttl < disttr){ + //from the left to the right + sol.add(topLeft); + sol.add(topRight); + } else { + //from the right to the left + sol.add(topRight); + sol.add(topLeft); + } + } + } else {//only left => inside bounds + inbounds=true; + } + } else if (rightIntersection) { + if(topIntersection) {//right and top + sol.add(topRight); + } + else if(bottomIntersection){//right and bottom + sol.add(bottomRight); + } else { //only right => inside the bounds + inbounds=true; + } + } else if (topIntersection && bottomIntersection) {//top and bottom + double disttop = interTop.distance(p1); + double distbot = interBot.distance(p1); + if(disttop < distbot ){ + //from the top to the bottom + double distleft = interTop.distance(topLeft); + double distright = interTop.distance(topRight); + if(distleft < distright){ + //pass left + sol.add(topLeft); + sol.add(bottomLeft); + } else { + //pass right + sol.add(topRight); + sol.add(bottomRight); + } + } else { + //from the bottom to the top + double distleft = interBot.distance(bottomLeft); + double distright = interBot.distance(bottomRight); + if(distleft < distright){ + //pass left + sol.add(bottomLeft); + sol.add(topLeft); + } else { + //pass right + sol.add(bottomRight); + sol.add(topRight); + } + } + } else {//only bottom or only top + inbounds=true; + } /* ENDIF */ + + //breakpoint <-- collision detected + + if(sol.size()>0) {//solution found + assert(!inbounds); + return sol; + } else { //no solution found=> inbounds + assert(inbounds); + assert(sol.size()==0); + //handle collision or just skip it and search for the next collisionj + ibr=r; + //jump out of the loop to able to interate over the obstacles + break; + } + }/* end foreach obstacle */ + + if(inbounds || ibr != null){ + assert(inbounds); + assert(ibr!=null); + } + return null;//no collison found + }/* end optimizeLine */ + + + + //check intersection between line p0->p1 for a given set of obstacles + private static boolean intersects(List<Rectangle> obstacles, Point p0, Point p1) { + for(Rectangle r : obstacles){ + if(r.intersectsLine(p0.x, p0.y, p1.x, p1.y)) + return true; + } + return false; + } + + + private boolean findIntersectionPoint( + Point p0, Point p1, Point p2, Point p3, Point pI) { + float q = (p0.y - p2.y)*(p3.x - p2.x) - (p0.x - p2.x)*(p3.y - p2.y); + float d = (p1.x - p0.x)*(p3.y - p2.y) - (p1.y - p0.y)*(p3.x - p2.x); + + //parallel ? + if(d==0) return false; + + float r = q / d; + q = (p0.y - p2.y)*(p1.x - p0.x) - (p0.x - p2.x)*(p1.y - p0.y); + + float s = q / d; + if(r<0 || r>1 || s<0 || s>1) return false; + + pI.x = p0.x + (int) (0.5f + r * (p1.x - p0.x)); + pI.y = p0.y + (int) (0.5f + r * (p1.y - p0.y)); + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/SplineConnectionWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,541 @@ +package at.ssw.visualizer.cfg.visual; + +import org.netbeans.api.visual.widget.ConnectionWidget; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.List; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +/** + * In comparison to the default ConnectionWidget this class is able to connect + * widgets with a curve instead of a straight line sequence. + * In conjunction with a suitable router the connection will be a straight line + * or a curve depending on the amount and the position of the controlpoints. + * Controlpoints supplied by the router, are treated as curve intersection points. + * For Reflexive edges the router doesn`t necessarily need to supply + * any controlpoints, they get painted by this automatically, this can be + * excepted if the router supplys more as 2 control points for a self edge, + * then the edge gets painted with the default curve interpolation algorithm. + * The method used for drawing curves uses a piecewise cubic interpolation + * algorithm. Between two control points a curve is painted as cubic bezier + * curve the, inner bezier points are calculated automatically with FMILL + * tangents and a chord parametrization, this interpolant is also known as + * cutmull-rom spline. The resulting spline fullfills c^1 continuity. + * The the end points the interpolation algorithm uses the bessel end condition. + */ + +public class SplineConnectionWidget extends ConnectionWidget { + private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy + private static final double HIT_DISTANCE_SQUARE = 4.0;//distance for intersection test + private GraphScene scene=null; + private Point2D [] bezierPoints = null; + + public SplineConnectionWidget(Scene scene) { + super(scene); + if(scene instanceof GraphScene) + this.scene=(GraphScene) scene; + } + + //check for self - edge + private boolean isReflexive(){ + return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); + } + + + @Override + protected Rectangle calculateClientArea() { + + Rectangle bounds = null; + + if(this.getControlPoints().size()>2){ + bezierPoints = createBezierPoints(getControlPoints()); + } + //minmax method - returns the smallest bounding rectangle + //Curves and surfaces for CAGD (3rd ed.), p.54 + //exact calculation of the bounding min rect + if(bezierPoints != null) { + Rectangle2D bounds2D = null; + for (int i = 0; i < bezierPoints.length; i++) { + Point2D point = bezierPoints[i]; + if(bounds2D==null) + bounds2D = new Rectangle2D.Double(point.getX(),point.getY(),0,0); + else + bounds2D.add(point); + } + bounds = bounds2D.getBounds(); + bounds.grow(2, 2); + + } else if (getControlPoints().size()>0){ + for(Point p : this.getControlPoints()){ + if(bounds==null) + bounds = new Rectangle(p); + else + bounds.add(p); + } + bounds.grow(5,5); + + } else if (isReflexive()) { + Widget related = this.getTargetAnchor().getRelatedWidget(); + bounds = related.convertLocalToScene(related.getBounds()); + bounds.grow(10, 10); + } + + if(bounds==null) + bounds = super.calculateClientArea(); + + return bounds; + } + + + /** + * if the edge is reflexive its painted as a cyclic self edge, if there + * are two controlpoints the connection is painted as a straight line from + * the source to the targetanchor, if there are more as 2 controlpoints the + * connection path between two control points is painted as cutmull rom + * spline with bessel end tangents. + */ + @Override + protected void paintWidget () { + List<Point> contrPoints = this.getControlPoints(); + int listSize = contrPoints.size(); + + Graphics2D gr = getGraphics (); + + if (listSize <= 2) { + this.bezierPoints=null;//set bezier Points null for calulateClientArea() + if(isReflexive()) { //special case for reflexive connection widgets + this.drawReflexive(gr); + } else { + super.paintWidget(); + } + return; + } + + //bezier curve... listSize > 2 + GeneralPath curvePath = new GeneralPath(); + double lastControlPointRotation = 0.0; + + + Point2D [] bezPoints = this.createBezierPoints(contrPoints); + curvePath.moveTo(bezPoints[0].getX(), bezPoints[0].getY());//b00 + + //last segment is added by subdivision thats why its -5 + for (int i = 1; i < bezPoints.length-5; i+=3) { + curvePath.curveTo( + bezPoints[i].getX(), bezPoints[i].getY(),//b1i + bezPoints[i+1].getX(), bezPoints[i+1].getY(),//b2i + bezPoints[i+2].getX(), bezPoints[i+2].getY());//b3i + + } + + GeneralPath lastseg = subdivide2D( + bezPoints[bezPoints.length-4], + bezPoints[bezPoints.length-3], + bezPoints[bezPoints.length-2], + bezPoints[bezPoints.length-1]); + + + if(lastseg != null) + curvePath.append(lastseg, true); + + Point2D cur = curvePath.getCurrentPoint(); + Point lastControlPoint = contrPoints.get(listSize-1); + + lastControlPointRotation = //anchor anchorAngle + Math.atan2 (cur.getY() - lastControlPoint.y, cur.getX() - lastControlPoint.x); + + gr.setStroke(getStroke()); + gr.setColor(getLineColor()); + gr.draw(curvePath); + + + AffineTransform previousTransform = gr.getTransform (); + gr.translate (lastControlPoint.x, lastControlPoint.y); + gr.rotate (lastControlPointRotation); + AnchorShape targetAnchorShape = this.getTargetAnchorShape(); + targetAnchorShape.paint (gr, false); + gr.setTransform (previousTransform); + + //paint ControlPoints if enabled + if (isPaintControlPoints()) { + int last = listSize - 1; + for (int index = 0; index <= last; index ++) { + Point point = contrPoints.get (index); + previousTransform = gr.getTransform (); + gr.translate (point.x, point.y); + if (index == 0 || index == last) + getEndPointShape().paint (gr); + else + getControlPointShape().paint (gr); + gr.setTransform (previousTransform); + } + + } + } + + private void drawReflexive(Graphics2D gr){ + Widget related = this.getTargetAnchor().getRelatedWidget(); + int position = this.edgeBalance(related); + Rectangle bounds = related.convertLocalToScene(related.getBounds()); + gr.setColor (getLineColor()); + Point first = new Point(); + Point last = new Point(); + double centerX = bounds.getCenterX(); + first.x = (int) (centerX + bounds.width / 4); + first.y = bounds.y + bounds.height; + last.x = first.x; + last.y = bounds.y; + + gr.setStroke(this.getStroke()); + + double cutDistance = this.getTargetAnchorShape().getCutDistance(); + double anchorAngle = Math.PI/-3.0; + double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); + double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); + int ydiff=first.y-last.y; + int endy = -ydiff; + double height=bounds.getHeight(); + double cy = height/4.0; + double cx=bounds.getWidth()/5.0; + double dcx = cx*2; + GeneralPath gp = new GeneralPath(); + gp.moveTo(0, 0); + gp.quadTo(0, cy, cx, cy); + gp.quadTo(dcx, cy, dcx, -height/2.0); + gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); + gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); + + AffineTransform af = new AffineTransform(); + AnchorShape anchorShape = this.getTargetAnchorShape(); + + if(position < 0) { + first.x = (int) (centerX - bounds.width / 4); + af.translate(first.x, first.y); + af.scale(-1.0, 1.0); + last.x = first.x; + } else { + af.translate(first.x, first.y); + } + Shape s = gp.createTransformedShape(af); + gr.draw(s); + + if (last != null) { + AffineTransform previousTransform = gr.getTransform (); + gr.translate (last.x, last.y); + + if(position < 0) + gr.rotate(Math.PI - anchorAngle); + else + gr.rotate (anchorAngle); + + anchorShape.paint (gr, false); + gr.setTransform (previousTransform); + } + } + + //returns prefered location for an edge -1 for left and 1 for right + private int edgeBalance(Widget nodeWidget) { + if(scene == null) + return 1; + + Point nodeLocation = nodeWidget.getLocation(); + int left = 0, right = 0; + + Object node = scene.findObject(nodeWidget); + + for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges + ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); + + if(cw != this) { + Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); + + Point location; + if(targetNodeWidget == nodeWidget) { + Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); + location = sourceNodeWidget.getLocation(); + } else { + location = targetNodeWidget.getLocation(); + } + + if(location.x < nodeLocation.x) + left++; + else + right++; + } + } + if(left < right) + return -1; + else + return 1; + } + + + private Point2D[] createBezierPoints(List<Point> list){ + if(list.size()<3) return null ; + + + int lastIdx = list.size()-1; + + + //chord length parametrization + double[] uis = new double[list.size()]; + uis[0]=0; + uis[1] = list.get(1).distance(list.get(0)); + for (int i = 1; i < uis.length; i++) { + Point cur = list.get(i); + Point prev = list.get(i-1); + uis[i]=uis[i-1]+ cur.distance(prev); + } + + + for (int i = 1; i < uis.length; i++) { + uis[i] /= uis[lastIdx]; + + } + double[] delta = new double[uis.length-1]; + for (int i = 0; i < delta.length; i++) { + double ui = uis[i]; + double uin = uis[i+1]; + delta[i] = uin-ui; + } + + + //FMILL tangent directions (chord length) + Point2D[] tangents = new Point2D[list.size()]; + + for (int i = 1; i < list.size()-1; i++) { + Point xBefore = list.get(i-1); + Point xAfter = list.get(i+1); + Point2D.Double tangent = new Point2D.Double (xAfter.x - xBefore.x, xAfter.y - xBefore.y); + tangents[i] = tangent; + } + + + Point2D [] bezPoints = new Point2D[(list.size()-1)*2+list.size()]; + //Catmull-Rom + for (int i = 1; i < list.size()-1; i++) { + Point b3i = list.get(i); + Point2D b3ib = b3iBefore(b3i, delta[i-1], delta[i], tangents[i]); + Point2D b3ia = b3iAfter(b3i, delta[i-1], delta[i], tangents[i]); + bezPoints[3*i] = b3i; + bezPoints[3*i-1] = b3ib; + bezPoints[3*i+1] = b3ia; + } + bezPoints[0] = list.get(0); + bezPoints[bezPoints.length-1] = list.get(list.size()-1); + + Point p0 = list.get(0); + Point p1 = list.get(1); + Point p2 = list.get(2); + Point pL_2 = list.get(lastIdx-2); + Point pL_1 = list.get(lastIdx-1); + Point pL = list.get(lastIdx); + + Point2D m1 = besselTangent(delta[0], delta[1], p0, p1, p2); + Point2D m0 = besselEndTangent(p0, p1, delta[0], m1); + + Point2D mLb = besselTangent(delta[delta.length-2], delta[delta.length-1], + pL_2,pL_1, pL); + Point2D mL = besselEndTangent(pL_1, pL, delta[delta.length-1], mLb); + + Point2D scaleM0 = scale(normalize(m0), p0.distance(p1));//increase distx/distxl to make curve rounder at the end + Point2D scaleML = scale(normalize(mL), pL.distance(pL_1)); + //Catmull-Rom for bessel points + Point2D b30a = b3iAfter(p0, delta[0], delta[0],scaleM0); + Point2D b33b = b3iBefore(pL, delta[delta.length-1], delta[delta.length-1],scaleML); + + bezPoints[1] = b30a; + bezPoints[bezPoints.length-2] = b33b; + + return bezPoints; + } + + + + private static Point2D besselTangent(double delta_ib, double delta_i, Point2D p0, Point2D p1 , Point2D p2){ + double alpha_i = delta_ib/(delta_ib+delta_i); + + double x = (1-alpha_i)/delta_ib * (p1.getX() - p0.getX()) + + alpha_i/delta_i * (p2.getX()-p1.getX()); + double y = (1-alpha_i)/delta_ib * (p1.getY() - p0.getY()) + + alpha_i/delta_i * (p2.getY()-p1.getY()); + + return new Point2D.Double(x,y); + } + + private static Point2D besselEndTangent(Point2D p0, Point2D p1, double delta_u, Point2D m){ + double x = 2*((p1.getX()-p0.getX())/delta_u) - m.getX(); + double y = 2*((p1.getY()-p0.getY())/delta_u) - m.getY(); + return new Point2D.Double(x,y); + } + + private static Point2D b3iBefore(Point2D b3i, double delta_ib, double delta_i, Point2D li){ + double x = b3i.getX() - (delta_ib/(3*(delta_ib+delta_i)))*li.getX(); + double y = b3i.getY() - (delta_ib/(3*(delta_ib+delta_i)))*li.getY(); + return new Point.Double(x,y); + } + + private static Point2D b3iAfter(Point2D b3i, double delta_ib,double delta_i,Point2D li){ + double x = b3i.getX() + (delta_i/(3*(delta_ib+delta_i)))*li.getX(); + double y = b3i.getY() + (delta_i/(3*(delta_ib+delta_i)))*li.getY(); + return new Point.Double(x,y); + } + + + + + //returns length of vector v + private static double norm(Point2D v){ + return Math.sqrt(v.getX()*v.getX()+v.getY()*v.getY()); + } + + //returns unity vector of vector v + private static Point2D normalize(Point2D v){ + double norm = norm(v); + if(norm==0) return new Point2D.Double(v.getX(), v.getY()); + return new Point2D.Double(v.getX()/norm , v.getY()/norm); + } + + //scale vector to size of length + private static Point2D scale(Point2D v, double length){ + Point2D tmp = normalize(v); + return new Point2D.Double(tmp.getX()*length, tmp.getY()*length); + } + + + + private GeneralPath subdivide2D (Point2D b0, Point2D b1, Point2D b2, Point2D b3) { + //set 2nd intermediate point to endpoint + //we could actually use another "better" point if we like to have a smoother curve + + double cutDistance = getTargetAnchorShape().getCutDistance(); + double minDistance = cutDistance - ENDPOINT_DEVIATION; + /** + * if the cutDistance is valid the last segment of the curve + * gets reduced by subdivision until the distance of the endpoint(epDistance) + * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) + */ + if(cutDistance > minDistance && minDistance > 0 ) { + GeneralPath path = new GeneralPath(); + + path.moveTo(b0.getX(), b0.getY()); + + CubicCurve2D.Double curve = new CubicCurve2D.Double( + b0.getX(), b0.getY(), + b1.getX(), b1.getY(), + b2.getX(), b2.getY(), + b3.getX(), b3.getY()); + + + + CubicCurve2D right=new CubicCurve2D.Double(); + CubicCurve2D left=new CubicCurve2D.Double(); + curve.subdivide(left, right); + double distance = b3.distance(left.getP2()); + //if the distance is bigger as the cutDistance the left segment is added + //and the right segment is divided again + while(distance>cutDistance){ + path.append(left, true); + right.subdivide(left, right); + distance = b3.distance(left.getP2()); + //if the devision removed to much the left segment is divided + while(distance < minDistance) { + //changes the distance to ~ (distance+distance/2) + left.subdivide(left, right); + distance = b3.distance(left.getP2()); + } + } + //append the last segment with (minDistance < distance < cutDistance) + path.append(left, true); + return path; + } + return null; + } + + + /** + * Returns whether a specified local point pL is a part of the connection + * widget. + * First it make a rough bounds check + * for Line Segments => use Super call (ConnectionWidget.isHitAt(pL)). + * for self-edges => its sufficent to return getBounds.contains(pL). + * for Splines => Interate over all Partitial segments of the curve and make + * a minmax check with the bezier points. If pL is inside the minmax + * rectangle of one segment the curve is constructed and subdivided until + * the distance d between center point pC (of the bounding rectangle) + * and pL is below HIT_DISTANCE_SQUARE, in this case it returns true. + * If no no minmax check was successful or the subdivision lead to an + * rectangle witch doesn`t contain pL return false. + * @param localLocation the local location + * @return true, if the location is a part of the connection widget + */ + @Override + public boolean isHitAt(Point localLocation) { + if(!isVisible() || !getBounds ().contains (localLocation)) + return false; + + List<Point> controlPoints = getControlPoints (); + if(controlPoints.size() <=2){ + if(isReflexive()) return true; + return super.isHitAt(localLocation); + } + + if(bezierPoints != null) { + for (int i = 0; i < bezierPoints.length-1; i+=3) { + Point2D b0 = bezierPoints[i]; + Point2D b1 = bezierPoints[i+1]; + Point2D b2 = bezierPoints[i+2]; + Point2D b3 = bezierPoints[i+3]; + + CubicCurve2D left = new CubicCurve2D.Double( + b0.getX(), b0.getY(), + b1.getX(), b1.getY(), + b2.getX(), b2.getY(), + b3.getX(), b3.getY()); + + + Rectangle2D bounds = left.getBounds2D(); + while(bounds.contains(localLocation)) { + //calculate the center and use HIT_DISTANCE_SQUARE for a range check + Point2D test = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY()); + if(test.distance(localLocation) < HIT_DISTANCE_SQUARE){ + return true; + } + + + CubicCurve2D right = new CubicCurve2D.Double(); + left.subdivide(left, right); + Rectangle2D lb2d = left.getBounds2D(); + Rectangle2D rb2d = right.getBounds2D(); + if( lb2d.contains(localLocation)){ + bounds = lb2d; + } else if (rb2d.contains(localLocation)) { + left = right; + bounds = rb2d; + } else { + return false; + } + + }//end while + }//end for + } + return false; + } + + +} + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/WidgetCollisionCollector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,12 @@ +package at.ssw.visualizer.cfg.visual; + +import java.util.List; +import org.netbeans.api.visual.widget.Widget; + + +public interface WidgetCollisionCollector { + + //returns a list of widgets which should be handled as obstacles + void collectCollisions(List<Widget> collisions); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.data" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.data.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.data +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.data-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=a403efd8 +build.xml.script.CRC32=b87f73ba +build.xml.stylesheet.CRC32=79c3b980 +# 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=a403efd8 +nbproject/build-impl.xml.script.CRC32=cc649146 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial +src.dir=src +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +test.src.dir=test +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <suite-component/> + <module-dependencies/> + <test-dependencies> + <test-type> + <name>unit</name> + <test-dependency> + <code-name-base>org.netbeans.libs.junit4</code-name-base> + <compile-dependency/> + </test-dependency> + <test-dependency> + <code-name-base>org.openide.util</code-name-base> + <compile-dependency/> + </test-dependency> + </test-type> + </test-dependencies> + <public-packages> + <package>at.ssw.visualizer.model.bc</package> + <package>at.ssw.visualizer.model.cfg</package> + <package>at.ssw.visualizer.model.interval</package> + <package>at.ssw.visualizer.model.nc</package> + <package>com.sun.hotspot.igv.data</package> + <package>com.sun.hotspot.igv.data.serialization</package> + <package>com.sun.hotspot.igv.data.services</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/bc/Bytecodes.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,33 @@ +package at.ssw.visualizer.model.bc; + +import at.ssw.visualizer.model.cfg.ControlFlowGraph; + +/** + * This class holds the bytecode of a method and provides severel methods + * accessing the details. + * + * @author Alexander Reder + * @author Christian Wimmer + */ +public interface Bytecodes { + /** + * Back-link to the control flow graph where the bytecodes were loaded from. + */ + public ControlFlowGraph getControlFlowGraph(); + + /** + * Called before the first call of getBytecodes() or getEpilogue(). Can be called multiple times. + */ + public void parseBytecodes(); + + /** + * The bytecodes of the method in the given bytecode range. + * + * @param fromBCI starting BCI (including this bci) + * @param toBCI ending BCI (not including this bci) + * @return string representation of the bytecodes + */ + public String getBytecodes(int fromBCI, int toBCI); + + public String getEpilogue(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/BasicBlock.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,41 @@ +package at.ssw.visualizer.model.cfg; + +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public interface BasicBlock { + public String getName(); + + public int getFromBci(); + + public int getToBci(); + + public List<? extends BasicBlock> getPredecessors(); + + public List<? extends BasicBlock> getSuccessors(); + + public List<? extends BasicBlock> getXhandlers(); + + public List<String> getFlags(); + + public BasicBlock getDominator(); + + public int getLoopIndex(); + + public int getLoopDepth(); + + public boolean hasState(); + + public List<State> getStates(); + + public boolean hasHir(); + + public List<IRInstruction> getHirInstructions(); + + public boolean hasLir(); + + public List<IRInstruction> getLirOperations(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/ControlFlowGraph.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,26 @@ +package at.ssw.visualizer.model.cfg; + +import at.ssw.visualizer.model.bc.Bytecodes; +import at.ssw.visualizer.model.nc.NativeMethod; +import com.sun.hotspot.igv.data.FolderElement; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public interface ControlFlowGraph extends FolderElement { + public List<BasicBlock> getBasicBlocks(); + + public BasicBlock getBasicBlockByName(String name); + + public Bytecodes getBytecodes(); + + public NativeMethod getNativeMethod(); + + public boolean hasState(); + + public boolean hasHir(); + + public boolean hasLir(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/IRInstruction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,19 @@ +package at.ssw.visualizer.model.cfg; + +import java.util.Collection; + +/** + * + * @author Christian Wimmer + */ +public interface IRInstruction { + public static String HIR_NAME = "tid"; + public static String HIR_TEXT = "instruction"; + public static String HIR_OPERAND = "result"; + + public static String LIR_NUMBER = "nr"; + public static String LIR_TEXT = "instruction"; + + public Collection<String> getNames(); + public String getValue(String name); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/State.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,17 @@ +package at.ssw.visualizer.model.cfg; + +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public interface State { + public String getKind(); + + public int getSize(); + + public String getMethod(); + + public List<StateEntry> getEntries(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/cfg/StateEntry.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,19 @@ +package at.ssw.visualizer.model.cfg; + +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public interface StateEntry { + public int getIndex(); + + public String getName(); + + public boolean hasPhiOperands(); + + public List<String> getPhiOperands(); + + public String getOperand(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/ChildInterval.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +package at.ssw.visualizer.model.interval; + +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public interface ChildInterval { + public Interval getParent(); + + public String getRegNum(); + + public String getType(); + + public String getOperand(); + + public String getSpillState(); + + public ChildInterval getRegisterHint(); + + public List<Range> getRanges(); + + public List<UsePosition> getUsePositions(); + + public int getFrom(); + + public int getTo(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/Interval.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,19 @@ +package at.ssw.visualizer.model.interval; + +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public interface Interval { + public IntervalList getParent(); + + public List<ChildInterval> getChildren(); + + public String getRegNum(); + + public int getFrom(); + + public int getTo(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/IntervalList.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,16 @@ +package at.ssw.visualizer.model.interval; + +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public interface IntervalList { + public List<Interval> getIntervals(); + + public ControlFlowGraph getControlFlowGraph(); + + public int getNumLIROperations(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/Range.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,11 @@ +package at.ssw.visualizer.model.interval; + +/** + * + * @author Christian Wimmer + */ +public interface Range { + public int getFrom(); + + public int getTo(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/interval/UsePosition.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,11 @@ +package at.ssw.visualizer.model.interval; + +/** + * + * @author Christian Wimmer + */ +public interface UsePosition { + public char getKind(); + + public int getPosition(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/model/nc/NativeMethod.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,15 @@ +package at.ssw.visualizer.model.nc; + +import at.ssw.visualizer.model.cfg.ControlFlowGraph; + +/** + * + * @author Alexander Reder + */ +public interface NativeMethod { + + public ControlFlowGraph getControlFlowGraph(); + + public String getMethodText(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/bc/BytecodesImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,166 @@ +package at.ssw.visualizer.modelimpl.bc; + +import at.ssw.visualizer.model.bc.Bytecodes; +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.modelimpl.cfg.BasicBlockImpl; +import java.util.Arrays; + +/** + * This class holds the bytecode of a method and provides severel methods + * accessing the details. + * + * @author Christian Wimmer + */ +public class BytecodesImpl implements Bytecodes { + private ControlFlowGraph controlFlowGraph; + private String bytecodeString; + + private String[] bytecodes; + private String epilogue; + + + public BytecodesImpl(ControlFlowGraph controlFlowGraph, String bytecodeString) { + this.controlFlowGraph = controlFlowGraph; + this.bytecodeString = bytecodeString; + } + + public void parseBytecodes() { + String[] lines = bytecodeString.split("\n"); + + boolean inPrologue = true; + String[] result = new String[lines.length * 3]; + int lastBci = -1; + int lnr = 0; + for (; lnr < lines.length; lnr++) { + String line = lines[lnr]; + + line = line.trim(); + if (line.startsWith("[")) { + int end = line.indexOf(']'); + if (end != -1) { + line = line.substring(end + 1, line.length()); + } + } + + line = line.trim(); + int space1 = line.indexOf(' '); + if (space1 <= 0) { + if (inPrologue) { + continue; + } else { + break; + } + } + String bciStr = line.substring(0, space1); + if (bciStr.endsWith(":")) { + bciStr = bciStr.substring(0, bciStr.length() - 1); + } + + int bci; + try { + bci = Integer.parseInt(bciStr); + } catch (NumberFormatException ex) { + // Ignore invalid lines. + if (inPrologue) { + continue; + } else { + break; + } + } + + String opcode = line.substring(space1 + 1); + String params = ""; + int space2 = opcode.indexOf(' '); + if (space2 > 0) { + params = opcode.substring(space2 + 1).trim(); + opcode = opcode.substring(0, space2); + } + String tail = ""; + int space3 = params.indexOf('|'); + if (space3 >= 0) { + tail = params.substring(space3); + params = params.substring(0, space3); + } + +// if (!"ldc".equals(opcode) || !params.startsWith("\"")) { +// // Separate packages with "." instead of "/" +// params = params.replace('/', '.'); +// } + + String printLine = bciStr + ":" + " ".substring(Math.min(bciStr.length(), 3)) + + opcode + " ".substring(Math.min(opcode.length(), 13)) + + params + " ".substring(Math.min(params.length(), 8)) + + tail; + + + if (bci >= result.length) { + result = Arrays.copyOf(result, Math.max(bci + 1, result.length * 2)); + } + result[bci] = printLine; + inPrologue = false; + lastBci = Math.max(lastBci, bci); + } + + StringBuilder epilogueBuilder = new StringBuilder(); + for (; lnr < lines.length; lnr++) { + epilogueBuilder.append(lines[lnr]).append("\n"); + } + epilogue = epilogueBuilder.toString(); + bytecodes = Arrays.copyOf(result, lastBci + 1); + + + BasicBlockImpl[] blocks = new BasicBlockImpl[bytecodes.length]; + for (BasicBlock b : controlFlowGraph.getBasicBlocks()) { + if (b instanceof BasicBlockImpl) { + BasicBlockImpl block = (BasicBlockImpl) b; + if (block.getToBci() != -1) { + // Do not override existing values. + return; + } + if (block.getFromBci() >= 0 && block.getFromBci() < blocks.length) { + blocks[block.getFromBci()] = block; + } + } + } + + int curToBci = -1; + for (int i = blocks.length - 1; i >= 0; i--) { + if (bytecodes[i] != null && curToBci == -1) { + curToBci = i; + } + if (blocks[i] != null) { + blocks[i].setToBci(curToBci); + curToBci = -1; + } + } + } + + public ControlFlowGraph getControlFlowGraph() { + return controlFlowGraph; + } + + public String getBytecodes(int fromBCI, int toBCI) { + if (fromBCI < 0) { + return ""; + } + toBCI = Math.min(toBCI, bytecodes.length); + StringBuilder sb = new StringBuilder(); + for (int i = fromBCI; i < toBCI; i++) { + if (bytecodes[i] != null) { + sb.append(bytecodes[i]).append("\n"); + } + } + return sb.toString(); + } + + @Override + public String getEpilogue() { + return epilogue; + } + + @Override + public String toString() { + return "Bytecodes " + getControlFlowGraph().getName(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/BasicBlockImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,143 @@ +package at.ssw.visualizer.modelimpl.cfg; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.model.cfg.IRInstruction; +import at.ssw.visualizer.model.cfg.State; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public class BasicBlockImpl implements BasicBlock { + + private ControlFlowGraph parent; + private String name; + private int fromBci; + private int toBci; + private BasicBlock[] predecessors; + private BasicBlock[] successors; + private BasicBlock[] xhandlers; + private String[] flags; + private BasicBlock dominator; + private int loopIndex; + private int loopDepth; + private int firstLirId; + private int lastLirId; + private State[] states; + private IRInstruction[] hirInstructions; + private IRInstruction[] lirOperations; + + public void setValues(String name, int fromBci, int toBci, BasicBlock[] predecessors, BasicBlock[] successors, BasicBlock[] xhandlers, String[] flags, BasicBlock dominator, int loopIndex, int loopDepth, int firstLirId, int lastLirId, State[] states, IRInstruction[] hirInstructions, IRInstruction[] lirOperations) { + this.name = name; + this.fromBci = fromBci; + this.toBci = toBci; + + this.predecessors = predecessors; + this.successors = successors; + this.xhandlers = xhandlers; + + this.flags = flags; + this.dominator = dominator; + this.loopIndex = loopIndex; + this.loopDepth = loopDepth; + this.firstLirId = firstLirId; + this.lastLirId = lastLirId; + + this.states = states; + this.hirInstructions = hirInstructions; + this.lirOperations = lirOperations; + } + + public ControlFlowGraph getParent() { + return parent; + } + + protected void setParent(ControlFlowGraph parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public int getFromBci() { + return fromBci; + } + + public int getToBci() { + return toBci; + } + + public void setToBci(int toBci) { + this.toBci = toBci; + } + + public List<BasicBlock> getPredecessors() { + return Collections.unmodifiableList(Arrays.asList(predecessors)); + } + + public List<BasicBlock> getSuccessors() { + return Collections.unmodifiableList(Arrays.asList(successors)); + } + + public List<BasicBlock> getXhandlers() { + return Collections.unmodifiableList(Arrays.asList(xhandlers)); + } + + public List<String> getFlags() { + return Collections.unmodifiableList(Arrays.asList(flags)); + } + + public BasicBlock getDominator() { + return dominator; + } + + public int getLoopIndex() { + return loopIndex; + } + + public int getLoopDepth() { + return loopDepth; + } + + public int getFirstLirId() { + return firstLirId; + } + + public int getLastLirId() { + return lastLirId; + } + + public boolean hasState() { + return states != null; + } + + public List<State> getStates() { + return Collections.unmodifiableList(Arrays.asList(states)); + } + + public boolean hasHir() { + return hirInstructions != null; + } + + public List<IRInstruction> getHirInstructions() { + return Collections.unmodifiableList(Arrays.asList(hirInstructions)); + } + + public boolean hasLir() { + return lirOperations != null; + } + + public List<IRInstruction> getLirOperations() { + return Collections.unmodifiableList(Arrays.asList(lirOperations)); + } + + @Override + public String toString() { + return name; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/IRInstructionImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,40 @@ +package at.ssw.visualizer.modelimpl.cfg; + +import at.ssw.visualizer.model.cfg.IRInstruction; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; + +public class IRInstructionImpl implements IRInstruction { + private LinkedHashMap<String, String> data; + + public IRInstructionImpl(LinkedHashMap<String, String> data) { + this.data = data; + } + + public IRInstructionImpl(String pinned, int bci, int useCount, String name, String text, String operand) { + data = new LinkedHashMap<String, String>(); + data.put("p", pinned); + data.put("bci", Integer.toString(bci)); + data.put("use", Integer.toString(useCount)); + data.put(HIR_NAME, name); + if (operand != null) { + data.put(HIR_OPERAND, operand); + } + data.put(HIR_TEXT, text); + } + + public IRInstructionImpl(int number, String text) { + data = new LinkedHashMap<String, String>(); + data.put(LIR_NUMBER, Integer.toString(number)); + data.put(LIR_TEXT, text); + } + + public Collection<String> getNames() { + return Collections.unmodifiableSet(data.keySet()); + } + + public String getValue(String name) { + return data.get(name); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateEntryImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,44 @@ +package at.ssw.visualizer.modelimpl.cfg; + +import at.ssw.visualizer.model.cfg.StateEntry; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public class StateEntryImpl implements StateEntry { + private int index; + private String name; + private String[] phiOperands; + private String operand; + + public StateEntryImpl(int index, String name, String[] phiOperands, String operand) { + this.index = index; + this.name = name; + this.phiOperands = phiOperands; + this.operand = operand; + } + + public int getIndex() { + return index; + } + + public String getName() { + return name; + } + + public boolean hasPhiOperands() { + return phiOperands != null; + } + + public List<String> getPhiOperands() { + return Collections.unmodifiableList(Arrays.asList(phiOperands)); + } + + public String getOperand() { + return operand; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,41 @@ +package at.ssw.visualizer.modelimpl.cfg; + +import at.ssw.visualizer.model.cfg.State; +import at.ssw.visualizer.model.cfg.StateEntry; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public class StateImpl implements State { + private String kind; + private int size; + private String method; + private StateEntry[] entries; + + public StateImpl(String kind, int size, String method, StateEntryImpl[] entries) { + this.kind = kind; + this.size = size; + this.method = method; + this.entries = entries; + } + + public String getKind() { + return kind; + } + + public int getSize() { + return size; + } + + public String getMethod() { + return method; + } + + public List<StateEntry> getEntries() { + return Collections.unmodifiableList(Arrays.asList(entries)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/ChildIntervalImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,118 @@ +package at.ssw.visualizer.modelimpl.interval; + +import at.ssw.visualizer.model.interval.ChildInterval; +import at.ssw.visualizer.model.interval.Interval; +import at.ssw.visualizer.model.interval.Range; +import at.ssw.visualizer.model.interval.UsePosition; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public class ChildIntervalImpl implements ChildInterval, Comparable<ChildIntervalImpl> { + private Interval parent; + private String regNum; + private String type; + private String operand; + private String spillState; + private ChildInterval registerHint; + private Range[] ranges; + private UsePosition[] usePositions; + + public void setValues(String regNum, String type, String operand, String spillState, ChildInterval registerHint, Range[] ranges, UsePosition[] usePositions) { + this.regNum = regNum; + this.type = type; + this.operand = operand; + this.spillState = spillState; + this.registerHint = registerHint; + this.ranges = ranges; + this.usePositions = usePositions; + } + + public Interval getParent() { + return parent; + } + + protected void setParent(IntervalImpl parent) { + this.parent = parent; + } + + public String getRegNum() { + return regNum; + } + + public String getType() { + return type; + } + + public String getOperand() { + return operand; + } + + public String getSpillState() { + return spillState; + } + + public ChildInterval getRegisterHint() { + return registerHint; + } + + public List<Range> getRanges() { + return Collections.unmodifiableList(Arrays.asList(ranges)); + } + + public List<UsePosition> getUsePositions() { + return Collections.unmodifiableList(Arrays.asList(usePositions)); + } + + + public int getFrom() { + return ranges[0].getFrom(); + } + + public int getTo() { + return ranges[ranges.length - 1].getTo(); + } + + + public int compareTo(ChildIntervalImpl other) { + return getFrom() - other.getFrom(); + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append(regNum); + result.append(": "); + result.append(getType()); + result.append(", "); + result.append(getOperand()); + result.append(", "); + if (registerHint != null) { + result.append(registerHint.getRegNum()); + } else { + result.append("null"); + } + + result.append(" "); + for (int i = 0; i < ranges.length; i++) { + if (i > 0) { + result.append(", "); + } + result.append(ranges[i]); + } + + result.append(" "); + for (int i = 0; i < usePositions.length; i++) { + if (i > 0) { + result.append(", "); + } + result.append(usePositions[i]); + } + + return result.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,60 @@ +package at.ssw.visualizer.modelimpl.interval; + +import at.ssw.visualizer.model.interval.ChildInterval; +import at.ssw.visualizer.model.interval.Interval; +import at.ssw.visualizer.model.interval.IntervalList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public class IntervalImpl implements Interval { + private IntervalList parent; + private ChildInterval[] children; + + public IntervalImpl(ChildIntervalImpl[] children) { + this.children = children; + for (ChildIntervalImpl child : children) { + child.setParent(this); + } + } + + public IntervalList getParent() { + return parent; + } + + protected void setParent(IntervalListImpl parent) { + this.parent = parent; + } + + public List<ChildInterval> getChildren() { + return Collections.unmodifiableList(Arrays.asList(children)); + } + + public String getRegNum() { + return children[0].getRegNum(); + } + + public int getFrom() { + return children[0].getFrom(); + } + + public int getTo() { + return children[children.length - 1].getTo(); + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < children.length; i++) { + if (i > 0) { + result.append("\n "); + } + result.append(children[i]); + } + return result.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalListImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,54 @@ +package at.ssw.visualizer.modelimpl.interval; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.model.interval.Interval; +import at.ssw.visualizer.model.interval.IntervalList; +import com.sun.hotspot.igv.data.AbstractFolderElement; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Christian Wimmer + */ +public class IntervalListImpl extends AbstractFolderElement implements IntervalList { + private Interval[] intervals; + private ControlFlowGraph controlFlowGraph; + private int numLIROperations; + + public IntervalListImpl(String shortName, String name, IntervalImpl[] intervals, ControlFlowGraph controlFlowGraph) { + super(shortName, name); + this.intervals = intervals; + this.controlFlowGraph = controlFlowGraph; + + for (IntervalImpl interval : intervals) { + interval.setParent(this); + numLIROperations = Math.max(numLIROperations, interval.getTo()); + } +// for (BasicBlock basicBlock : controlFlowGraph.getBasicBlocks()) { +// numLIROperations = Math.max(numLIROperations, basicBlock.getLastLirId() + 2); +// } + // TODO(tw): Add number of LIR operations to output. + } + + + public List<Interval> getIntervals() { + return Collections.unmodifiableList(Arrays.asList(intervals)); + } + + public ControlFlowGraph getControlFlowGraph() { + return controlFlowGraph; + } + + public int getNumLIROperations() { + return numLIROperations; + } + + + @Override + public String toString() { + return " Intervals \"" + getName() + "\": " + intervals.length + " intervals\n"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/RangeImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,36 @@ +package at.ssw.visualizer.modelimpl.interval; + +import at.ssw.visualizer.model.interval.Range; + +/** + * + * @author Christian Wimmer + */ +public class RangeImpl implements Range, Comparable<RangeImpl> { + private int from; + private int to; + + public RangeImpl(int from, int to) { + this.from = from; + this.to = to; + } + + + public int getFrom() { + return from; + } + + public int getTo() { + return to; + } + + + public int compareTo(RangeImpl other) { + return getFrom() - other.getFrom(); + } + + @Override + public String toString() { + return "[" + from + ", " + to + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/UsePositionImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,36 @@ +package at.ssw.visualizer.modelimpl.interval; + +import at.ssw.visualizer.model.interval.UsePosition; + +/** + * + * @author Christian Wimmer + */ +public class UsePositionImpl implements UsePosition, Comparable<UsePositionImpl> { + private int position; + private char kind; + + public UsePositionImpl(int position, char kind) { + this.position = position; + this.kind = kind; + } + + + public char getKind() { + return kind; + } + + public int getPosition() { + return position; + } + + + public int compareTo(UsePositionImpl other) { + return getPosition() - other.getPosition(); + } + + @Override + public String toString() { + return position + "(" + kind + ")"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/at/ssw/visualizer/modelimpl/nc/NativeMethodImpl.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,28 @@ +package at.ssw.visualizer.modelimpl.nc; + +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.model.nc.NativeMethod; + +/** + * + * @author Alexander Reder + */ +public class NativeMethodImpl implements NativeMethod { + + private ControlFlowGraph controlFlowGraph; + private String methodText; + + public NativeMethodImpl(ControlFlowGraph controlFlowGraph, String methodText) { + this.controlFlowGraph = controlFlowGraph; + this.methodText = methodText; + } + + public ControlFlowGraph getControlFlowGraph() { + return controlFlowGraph; + } + + public String getMethodText() { + return methodText; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/AbstractFolderElement.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,57 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data; + +public class AbstractFolderElement implements FolderElement { + + private String name; + private String shortName; + private Folder parent; + + public AbstractFolderElement(String name, String shortName) { + this.name = name; + this.shortName = shortName; + } + + public String getShortName() { + return shortName; + } + + @Override + public String getName() { + return name; + } + + @Override + public Folder getParent() { + return parent; + } + + @Override + public void setParent(Folder parent) { + this.parent = parent; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Data
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +/* + * 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.sun.hotspot.igv.data; + +public class ChangedEvent<T> extends Event<ChangedListener<T>> { + + private T object; + + public ChangedEvent(T object) { + this.object = object; + } + + @Override + protected void fire(ChangedListener<T> l) { + l.changed(object); + } + + public void changeObject(T newObject) { + if (object != newObject) { + this.object = newObject; + fire(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data; + +/** + * Provides a changed event object. + * @author Thomas Wuerthinger + * @param <T> Class for which the changed event fires. + */ +public interface ChangedEventProvider<T> { + + /** + * Returns the changed event object. Should always return the same instance. + */ + ChangedEvent<T> getChangedEvent(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +/** + * Listens to changed events. + * @author Thomas Wuerthinger + * @param <T> Class for which the changed event fires. + */ +public interface ChangedListener<T> { + + /** + * This method is called everytime a changed event is fired. + * @param source Object that has changed. + */ + void changed(T source); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/ControllableChangedListener.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +/** + * + * @author Thomas Wuerthinger + */ +public abstract class ControllableChangedListener<T> implements ChangedListener<T>{ + + private boolean enabled; + + + public ControllableChangedListener() { + enabled = true; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean b) { + enabled = b; + } + + @Override + public void changed(T source) { + if(enabled) { + filteredChanged(source); + } + } + + public abstract void filteredChanged(T source); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Event.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public abstract class Event<L> { + + private List<L> listener; + private boolean fireEvents; + private boolean eventWasFired; + + public Event() { + listener = new ArrayList<>(); + fireEvents = true; + } + + public void addListener(L l) { + listener.add(l); + } + + public void addListenerAndFire(L l) { + addListener(l); + fire(l); + } + + /** + * Remove listener + * @param l + */ + public void removeListener(final L l) { + listener.remove(l); + } + + public void fire() { + if(fireEvents) { + List<L> tmpList = new ArrayList<>(listener); + for (L l : tmpList) { + fire(l); + } + } else { + eventWasFired = true; + } + } + + public void beginAtomic() { + assert fireEvents : "endAtomic has to be called before another beginAtomic may be called"; + this.fireEvents = false; + this.eventWasFired = false; + } + + public void endAtomic() { + assert !fireEvents : "beginAtomic has to be called first"; + this.fireEvents = true; + if(eventWasFired) { + fire(); + } + } + + protected abstract void fire(L l); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Folder.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,34 @@ +/* + * 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.sun.hotspot.igv.data; + +import java.util.List; + +public interface Folder { + String getName(); + List<? extends FolderElement> getElements(); + void removeElement(FolderElement element); + void addElement(FolderElement group); + ChangedEvent<? extends Folder> getChangedEvent(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/FolderElement.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,31 @@ +/* + * 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.sun.hotspot.igv.data; + +public interface FolderElement { + + Folder getParent(); + String getName(); + void setParent(Folder parent); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class GraphDocument extends Properties.Entity implements ChangedEventProvider<GraphDocument>, Folder { + + private List<FolderElement> elements; + private ChangedEvent<GraphDocument> changedEvent; + + public GraphDocument() { + elements = new ArrayList<>(); + changedEvent = new ChangedEvent<>(this); + } + + public void clear() { + elements.clear(); + getChangedEvent().fire(); + } + + @Override + public ChangedEvent<GraphDocument> getChangedEvent() { + return changedEvent; + } + + public void addGraphDocument(GraphDocument document) { + for (FolderElement e : document.elements) { + e.setParent(this); + this.addElement(e); + } + document.clear(); + getChangedEvent().fire(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("GraphDocument: ").append(getProperties().toString()).append(" \n\n"); + for (FolderElement g : getElements()) { + sb.append(g.toString()); + sb.append("\n\n"); + } + + return sb.toString(); + } + + @Override + public List<? extends FolderElement> getElements() { + return elements; + } + + @Override + public void removeElement(FolderElement element) { + if (elements.remove(element)) { + getChangedEvent().fire(); + } + } + + @Override + public void addElement(FolderElement element) { + elements.add(element); + element.setParent(this); + getChangedEvent().fire(); + } + + @Override + public String getName() { + return "root"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Group.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class Group extends Properties.Entity implements ChangedEventProvider<Group>, Folder, FolderElement { + + private final List<FolderElement> elements; + private final List<InputGraph> graphs; + + private InputMethod method; + private transient ChangedEvent<Group> changedEvent; + private Folder parent; + + public Group(Folder parent) { + elements = new ArrayList<>(); + graphs = new ArrayList<>(); + changedEvent = new ChangedEvent<>(this); + this.parent = parent; + + // Ensure that name and type are never null + getProperties().setProperty("name", ""); + getProperties().setProperty("type", ""); + } + + public void fireChangedEvent() { + changedEvent.fire(); + } + + public void setMethod(InputMethod method) { + this.method = method; + } + + public InputMethod getMethod() { + return method; + } + + @Override + public ChangedEvent<Group> getChangedEvent() { + return changedEvent; + } + + @Override + public List<FolderElement> getElements() { + return Collections.unmodifiableList(elements); + } + + public int getGraphsCount() { + return elements.size(); + } + + @Override + public void addElement(FolderElement element) { + elements.add(element); + if (element instanceof InputGraph) { + graphs.add((InputGraph) element); + } else { + + } + element.setParent(this); + changedEvent.fire(); + } + + public Set<Integer> getAllNodes() { + Set<Integer> result = new HashSet<>(); + for (FolderElement e : elements) { + if (e instanceof InputGraph) { + InputGraph g = (InputGraph) e; + result.addAll(g.getNodesAsSet()); + } + } + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Group ").append(getProperties()).append("\n"); + for (FolderElement g : elements) { + sb.append(g.toString()); + sb.append('\n'); + } + return sb.toString(); + } + + @Override + public String getName() { + return getProperties().get("name"); + } + + public String getType() { + return getProperties().get("type"); + + } + + InputGraph getPrev(InputGraph graph) { + InputGraph lastGraph = null; + for (FolderElement e : elements) { + if (e == graph) { + return lastGraph; + } + if (e instanceof InputGraph) { + lastGraph = (InputGraph) e; + } + } + return null; + } + + InputGraph getNext(InputGraph graph) { + boolean found = false; + for (FolderElement e : elements) { + if (e == graph) { + found = true; + } else if (found && e instanceof InputGraph) { + return (InputGraph) e; + } + } + return null; + } + + public InputGraph getLastGraph() { + InputGraph lastGraph = null; + for (FolderElement e : elements) { + if (e instanceof InputGraph) { + lastGraph = (InputGraph) e; + } + } + return lastGraph; + } + + @Override + public Folder getParent() { + return parent; + } + + @Override + public void removeElement(FolderElement element) { + if (elements.remove(element)) { + if (element instanceof InputGraph) { + graphs.remove((InputGraph) element); + } + changedEvent.fire(); + } + } + + public List<InputGraph> getGraphs() { + return graphs; + } + + @Override + public void setParent(Folder parent) { + this.parent = parent; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.model.cfg.IRInstruction; +import at.ssw.visualizer.model.cfg.State; +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputBlock implements BasicBlock { + + private List<InputNode> nodes; + private String name; + private InputGraph graph; + private List<InputBlock> successors; + private List<InputBlock> predecessors; + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object o) { + + if (o == this) { + return true; + } + + if (o == null || (!(o instanceof InputBlock))) { + return false; + } + + final InputBlock b = (InputBlock)o; + final boolean result = b.nodes.equals(nodes) && b.name.equals(name) && b.successors.size() == successors.size(); + if (!result) { + return false; + } + + final HashSet<String> s = new HashSet<>(); + for (InputBlock succ : successors) { + s.add(succ.name); + } + + for (InputBlock succ : b.successors) { + if (!s.contains(succ.name)) { + return false; + } + } + + return true; + } + + InputBlock(InputGraph graph, String name) { + this.graph = graph; + this.name = name; + nodes = new ArrayList<>(); + successors = new ArrayList<>(); + predecessors = new ArrayList<>(); + } + + public String getName() { + return name; + } + + public List<InputNode> getNodes() { + return Collections.unmodifiableList(nodes); + } + + public void addNode(int id) { + InputNode n = graph.getNode(id); + assert n != null; + graph.setBlock(n, this); + final InputNode node = graph.getNode(id); + assert node != null; + assert !nodes.contains(node) : "duplicate : " + node; + nodes.add(node); + } + + @Override + public List<InputBlock> getSuccessors() { + return Collections.unmodifiableList(successors); + } + + @Override + public String toString() { + return "Block " + this.getName(); + } + + void addSuccessor(InputBlock b) { + if (!successors.contains(b)) { + successors.add(b); + b.predecessors.add(this); + } + } + + @Override + public int getFromBci() { + // TODO(tw): Implement. + return -1; + } + + @Override + public int getToBci() { + // TODO(tw): Implement. + return -1; + } + + @Override + public List<InputBlock> getPredecessors() { + return Collections.unmodifiableList(predecessors); + } + + @Override + public List<BasicBlock> getXhandlers() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public List<String> getFlags() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public BasicBlock getDominator() { + // TODO(tw): Implement. + return null; + } + + @Override + public int getLoopIndex() { + // TODO(tw): Implement. + return -1; + } + + @Override + public int getLoopDepth() { + // TODO(tw): Implement. + return -1; + } + + @Override + public boolean hasState() { + // TODO(tw): Implement. + return false; + } + + @Override + public List<State> getStates() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public boolean hasHir() { + // TODO(tw): Implement. + return false; + } + + @Override + public List<IRInstruction> getHirInstructions() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public boolean hasLir() { + // TODO(tw): Implement. + return false; + } + + @Override + public List<IRInstruction> getLirOperations() { + // TODO(tw): Implement. + return Collections.emptyList(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputBlockEdge { + + public enum State { + SAME, + NEW, + DELETED + } + + private InputBlock from; + private InputBlock to; + private State state = State.SAME; + + public InputBlockEdge(InputBlock from, InputBlock to) { + assert from != null; + assert to != null; + this.from = from; + this.to = to; + } + + public InputBlock getFrom() { + return from; + } + + public InputBlock getTo() { + return to; + } + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + @Override + public boolean equals(Object obj) { + if (obj != null && obj instanceof InputBlockEdge) { + InputBlockEdge e = (InputBlockEdge) obj; + return e.from.equals(from) && e.to.equals(to); + } + return false; + } + + @Override + public int hashCode() { + int hash = from.hashCode(); + hash = 59 * hash + to.hashCode(); + return hash; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputBytecode { + + private int bci; + private String name; + private InputMethod inlined; + + public InputBytecode(int bci, String name) { + this.bci = bci; + this.name = name; + } + + public InputMethod getInlined() { + return inlined; + } + + public void setInlined(InputMethod inlined) { + this.inlined = inlined; + } + + public int getBci() { + return bci; + } + + public String getName() { + return name; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.Comparator; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputEdge { + + public enum State { + + SAME, + NEW, + DELETED + } + + public static final Comparator<InputEdge> OUTGOING_COMPARATOR = new Comparator<InputEdge>(){ + + @Override + public int compare(InputEdge o1, InputEdge o2) { + if(o1.getFromIndex() == o2.getFromIndex()) { + return o1.getTo() - o2.getTo(); + } + return o1.getFromIndex() - o2.getFromIndex(); + } + }; + + + public static final Comparator<InputEdge> INGOING_COMPARATOR = new Comparator<InputEdge>(){ + + @Override + public int compare(InputEdge o1, InputEdge o2) { + if(o1.getToIndex() == o2.getToIndex()) { + return o1.getFrom() - o2.getFrom(); + } + return o1.getToIndex() - o2.getToIndex(); + } + }; + + private char toIndex; + private char fromIndex; + private int from; + private int to; + private State state; + private String label; + + public InputEdge(char toIndex, int from, int to) { + this((char) 0, toIndex, from, to, null); + } + + public InputEdge(char fromIndex, char toIndex, int from, int to) { + this(fromIndex, toIndex, from, to, null); + } + + public InputEdge(char fromIndex, char toIndex, int from, int to, String label) { + this.toIndex = toIndex; + this.fromIndex = fromIndex; + this.from = from; + this.to = to; + this.state = State.SAME; + this.label = label; + } + + public State getState() { + return state; + } + + public void setState(State x) { + this.state = x; + } + + public char getToIndex() { + return toIndex; + } + + public char getFromIndex() { + return fromIndex; + } + + public String getName() { + return "in" + toIndex; + } + + public int getFrom() { + return from; + } + + public int getTo() { + return to; + } + + public String getLabel() { + return label; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof InputEdge)) { + return false; + } + InputEdge conn2 = (InputEdge) o; + return conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to; + } + + @Override + public String toString() { + return "Edge from " + from + " to " + to + "(" + (int) fromIndex + ", " + (int) toIndex + ") "; + } + + @Override + public int hashCode() { + return (from << 20 | to << 8 | toIndex << 4 | fromIndex); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import at.ssw.visualizer.model.bc.Bytecodes; +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.model.nc.NativeMethod; +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputGraph extends Properties.Entity implements FolderElement, ControlFlowGraph { + + private Map<Integer, InputNode> nodes; + private Set<InputEdge> edges; + private Folder parent; + private Group parentGroup; + private Map<String, InputBlock> blocks; + private Set<InputBlockEdge> blockEdges; + private Map<Integer, InputBlock> nodeToBlock; + + public InputGraph(String name) { + setName(name); + nodes = new LinkedHashMap<>(); + edges = new LinkedHashSet<>(); + blocks = new LinkedHashMap<>(); + blockEdges = new LinkedHashSet<>(); + nodeToBlock = new LinkedHashMap<>(); + } + + @Override + public void setParent(Folder parent) { + this.parent = parent; + if (parent instanceof Group) { + assert this.parentGroup == null; + this.parentGroup = (Group) parent; + } + } + + public InputBlockEdge addBlockEdge(InputBlock left, InputBlock right) { + InputBlockEdge edge = new InputBlockEdge(left, right); + blockEdges.add(edge); + left.addSuccessor(right); + return edge; + } + + public List<InputNode> findRootNodes() { + List<InputNode> result = new ArrayList<>(); + Set<Integer> nonRoot = new HashSet<>(); + for(InputEdge curEdges : getEdges()) { + nonRoot.add(curEdges.getTo()); + } + + for(InputNode node : getNodes()) { + if(!nonRoot.contains(node.getId())) { + result.add(node); + } + } + + return result; + } + + public Map<InputNode, List<InputEdge>> findAllOutgoingEdges() { + + Map<InputNode, List<InputEdge>> result = new HashMap<>(getNodes().size()); + for(InputNode n : this.getNodes()) { + result.put(n, new ArrayList<InputEdge>()); + } + + for(InputEdge e : this.edges) { + int from = e.getFrom(); + InputNode fromNode = this.getNode(from); + List<InputEdge> fromList = result.get(fromNode); + assert fromList != null; + fromList.add(e); + } + + for(InputNode n : this.getNodes()) { + List<InputEdge> list = result.get(n); + Collections.sort(list, InputEdge.OUTGOING_COMPARATOR); + } + + return result; + } + + public Map<InputNode, List<InputEdge>> findAllIngoingEdges() { + + Map<InputNode, List<InputEdge>> result = new HashMap<>(getNodes().size()); + for(InputNode n : this.getNodes()) { + result.put(n, new ArrayList<InputEdge>()); + } + + for(InputEdge e : this.edges) { + int to = e.getTo(); + InputNode toNode = this.getNode(to); + List<InputEdge> toList = result.get(toNode); + assert toList != null; + toList.add(e); + } + + for(InputNode n : this.getNodes()) { + List<InputEdge> list = result.get(n); + Collections.sort(list, InputEdge.INGOING_COMPARATOR); + } + + return result; + } + + public List<InputEdge> findOutgoingEdges(InputNode n) { + List<InputEdge> result = new ArrayList<>(); + + for(InputEdge e : this.edges) { + if(e.getFrom() == n.getId()) { + result.add(e); + } + } + + Collections.sort(result, InputEdge.OUTGOING_COMPARATOR); + + return result; + } + + public void clearBlocks() { + blocks.clear(); + nodeToBlock.clear(); + } + + public void setEdge(int fromIndex, int toIndex, int from, int to) { + assert fromIndex == ((char)fromIndex) : "Downcast must be safe"; + assert toIndex == ((char)toIndex) : "Downcast must be safe"; + + InputEdge edge = new InputEdge((char)fromIndex, (char)toIndex, from, to); + if(!this.getEdges().contains(edge)) { + this.addEdge(edge); + } + } + + public void ensureNodesInBlocks() { + InputBlock noBlock = null; + Set<InputNode> scheduledNodes = new HashSet<>(); + + for (InputBlock b : getBlocks()) { + for (InputNode n : b.getNodes()) { + assert !scheduledNodes.contains(n); + scheduledNodes.add(n); + } + } + + for (InputNode n : this.getNodes()) { + assert nodes.get(n.getId()) == n; + if (!scheduledNodes.contains(n)) { + if (noBlock == null) { + noBlock = this.addBlock("(no block)"); + } + noBlock.addNode(n.getId()); + } + assert this.getBlock(n) != null; + } + } + + public void setBlock(InputNode node, InputBlock block) { + nodeToBlock.put(node.getId(), block); + } + + public InputBlock getBlock(int nodeId) { + return nodeToBlock.get(nodeId); + } + + public InputBlock getBlock(InputNode node) { + assert nodes.containsKey(node.getId()); + assert nodes.get(node.getId()).equals(node); + return getBlock(node.getId()); + } + + public InputGraph getNext() { + return parentGroup.getNext(this); + } + + public InputGraph getPrev() { + return parentGroup.getPrev(this); + } + + private void setName(String name) { + this.getProperties().setProperty("name", name); + } + + @Override + public String getName() { + return getProperties().get("name"); + } + + public Collection<InputNode> getNodes() { + return Collections.unmodifiableCollection(nodes.values()); + } + + public Set<Integer> getNodesAsSet() { + return Collections.unmodifiableSet(nodes.keySet()); + } + + public Collection<InputBlock> getBlocks() { + return Collections.unmodifiableCollection(blocks.values()); + } + + public void addNode(InputNode node) { + nodes.put(node.getId(), node); + } + + public InputNode getNode(int id) { + return nodes.get(id); + } + + public InputNode removeNode(int index) { + return nodes.remove(index); + } + + public Collection<InputEdge> getEdges() { + return Collections.unmodifiableSet(edges); + } + + public void removeEdge(InputEdge c) { + boolean removed = edges.remove(c); + assert removed; + } + + public void addEdge(InputEdge c) { + // Be tolerant with duplicated edges. + if (!edges.contains(c)) { + edges.add(c); + } + } + + public Group getGroup() { + return parentGroup; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Graph ").append(getName()).append(" ").append(getProperties().toString()).append("\n"); + for (InputNode n : nodes.values()) { + sb.append(n.toString()); + sb.append("\n"); + } + + for (InputEdge c : edges) { + sb.append(c.toString()); + sb.append("\n"); + } + + for (InputBlock b : getBlocks()) { + sb.append(b.toString()); + sb.append("\n"); + } + + return sb.toString(); + } + + public InputBlock addBlock(String name) { + final InputBlock b = new InputBlock(this, name); + blocks.put(b.getName(), b); + return b; + } + + public InputBlock getBlock(String s) { + return blocks.get(s); + } + + public Collection<InputBlockEdge> getBlockEdges() { + return Collections.unmodifiableSet(blockEdges); + } + + @Override + public Folder getParent() { + return parent; + } + + @Override + public List<BasicBlock> getBasicBlocks() { + return new ArrayList<BasicBlock>(blocks.values()); + } + + @Override + public BasicBlock getBasicBlockByName(String name) { + return blocks.get(name); + } + + @Override + public Bytecodes getBytecodes() { + // TODO(tw): no bytecodes + return null; + } + + @Override + public NativeMethod getNativeMethod() { + // TODO(tw): No native method. + return null; + } + + @Override + public boolean hasState() { + // TODO(tw): implement + return false; + } + + @Override + public boolean hasHir() { + // TODO(tw): Implement + return false; + } + + @Override + public boolean hasLir() { + // TODO(tw): Implement + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputMethod extends Properties.Entity { + + private String name; + private int bci; + private String shortName; + private List<InputMethod> inlined; + private InputMethod parentMethod; + private Group group; + private List<InputBytecode> bytecodes; + + @Override + public int hashCode() { + int result = name.hashCode(); + result = result * 31 + bci; + result = result * 31 + shortName.hashCode(); + result = result * 31 + inlined.hashCode(); + result = result * 31 + bytecodes.hashCode(); + return result; + } + + @Override + public boolean equals(Object o) { + if (o == null || (!(o instanceof InputMethod))) { + return false; + } + + final InputMethod im = (InputMethod)o; + return name.equals(im.name) && bci == im.bci && shortName.equals(im.shortName) && + inlined.equals(im.inlined) && bytecodes.equals(im.bytecodes); + } + + + + /** Creates a new instance of InputMethod */ + public InputMethod(Group parent, String name, String shortName, int bci) { + this.group = parent; + this.name = name; + this.bci = bci; + this.shortName = shortName; + inlined = new ArrayList<>(); + bytecodes = new ArrayList<>(); + } + + public List<InputBytecode> getBytecodes() { + return Collections.unmodifiableList(bytecodes); + } + + public List<InputMethod> getInlined() { + return Collections.unmodifiableList(inlined); + } + + public void addInlined(InputMethod m) { + + // assert bci unique + for (InputMethod m2 : inlined) { + assert m2.getBci() != m.getBci(); + } + + inlined.add(m); + assert m.parentMethod == null; + m.parentMethod = this; + + for (InputBytecode bc : bytecodes) { + if (bc.getBci() == m.getBci()) { + bc.setInlined(m); + } + } + } + + public Group getGroup() { + return group; + } + + public String getShortName() { + return shortName; + } + + public void setBytecodes(String text) { + + String[] strings = text.split("\n"); + int oldNumber = -1; + for (String s : strings) { + + if (s.length() > 0 && Character.isDigit(s.charAt(0))) { + s = s.trim(); + int spaceIndex = s.indexOf(' '); + String numberString = s.substring(0, spaceIndex); + String tmpName = s.substring(spaceIndex + 1, s.length()); + + int number = -1; + number = Integer.parseInt(numberString); + + // assert correct order of bytecodes + assert number > oldNumber; + + InputBytecode bc = new InputBytecode(number, tmpName); + bytecodes.add(bc); + + for (InputMethod m : inlined) { + if (m.getBci() == number) { + bc.setInlined(m); + break; + } + } + } + } + } + + public String getName() { + return name; + } + + public int getBci() { + return bci; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.Comparator; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputNode extends Properties.Entity { + + private int id; + + public static final Comparator<InputNode> COMPARATOR = new Comparator<InputNode>() { + @Override + public int compare(InputNode o1, InputNode o2) { + return o1.getId() - o2.getId(); + } + }; + + public static Comparator<InputNode> getPropertyComparator(final String propertyName) { + return new Comparator<InputNode>() { + + @Override + public int compare(InputNode o1, InputNode o2) { + + int i1 = 0; + try { + i1 = Integer.parseInt(o1.getProperties().get(propertyName)); + } catch(NumberFormatException e) { + } + + int i2 = 0; + try { + i2 = Integer.parseInt(o2.getProperties().get(propertyName)); + } catch(NumberFormatException e) { + } + + return i1 - i2; + } + }; + } + + public InputNode(InputNode n) { + super(n); + setId(n.id); + } + + public InputNode(int id) { + setId(id); + } + + public void setId(int id) { + this.id = id; + getProperties().setProperty("id", "" + id); + } + + public int getId() { + return id; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof InputNode)) { + return false; + } + InputNode n = (InputNode) o; + return n.id == id; + } + + @Override + public int hashCode() { + return id * 13; + } + + @Override + public String toString() { + return "Node " + id + " " + getProperties().toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Pair.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +/** + * + * @author Thomas Wuerthinger + */ +public class Pair<L, R> { + + private L l; + private R r; + + public Pair() { + } + + public Pair(L l, R r) { + this.l = l; + this.r = r; + } + + public L getLeft() { + return l; + } + + public void setLeft(L l) { + this.l = l; + } + + public R getRight() { + return r; + } + + public void setRight(R r) { + this.r = r; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof Pair)) { + return false; + } + Pair<?,?> obj = (Pair<?,?>) o; + boolean b1 = (l == obj.l); + if (l != null) { + b1 = l.equals(obj.l); + } + + boolean b2 = (r == obj.r); + if (r != null) { + b2 = r.equals(obj.r); + } + + return b1 && b2; + } + + @Override + public int hashCode() { + return ((l == null) ? 0 : l.hashCode()) * 71 + ((r == null) ? 0 : r.hashCode()); + } + + @Override + public String toString() { + return "[" + l + "/" + r + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Properties.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.io.Serializable; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * + * @author Thomas Wuerthinger + */ +public class Properties implements Serializable, Iterable<Property> { + + public static final long serialVersionUID = 1L; + private String[] map = new String[4]; + + public Properties() { + } + + @Override + public boolean equals(java.lang.Object o) { + if (!(o instanceof Properties)) { + return false; + } + + Properties p = (Properties) o; + + for (Property prop : this) { + String value = p.get(prop.getName()); + if (value == null || !value.equals(prop.getValue())) { + return false; + } + } + + for (Property prop : p) { + String value = this.get(prop.getName()); + if (value == null || !value.equals(prop.getValue())) { + return false; + } + } + + return true; + } + + @Override + public int hashCode() { + int hash = 5; + + if (map != null) { + for (int i = 0; i < this.map.length; i++) { + if (map[i] == null) { + i++; + } else { + hash = hash * 83 + map[i].hashCode(); + } + } + } + return hash; + } + + public Properties(String name, String value) { + this(); + this.setProperty(name, value); + } + + public Properties(String name, String value, String name1, String value1) { + this(name, value); + this.setProperty(name1, value1); + } + + public Properties(String name, String value, String name1, String value1, String name2, String value2) { + this(name, value, name1, value1); + this.setProperty(name2, value2); + } + + public Properties(Properties p) { + map = new String[p.map.length]; + System.arraycopy(p.map, 0, map, 0, p.map.length); + } + + public static class Entity implements Provider { + + private Properties properties; + + public Entity() { + properties = new Properties(); + } + + public Entity(Properties.Entity object) { + properties = new Properties(object.getProperties()); + } + + @Override + public Properties getProperties() { + return properties; + } + } + + public interface PropertyMatcher { + + String getName(); + + boolean match(String value); + } + + public static class InvertPropertyMatcher implements PropertyMatcher { + + private PropertyMatcher matcher; + + public InvertPropertyMatcher(PropertyMatcher matcher) { + this.matcher = matcher; + } + + @Override + public String getName() { + return matcher.getName(); + } + + @Override + public boolean match(String p) { + if (p == null) { + return false; + } + return !matcher.match(p); + } + } + + public static class StringPropertyMatcher implements PropertyMatcher { + + private String name; + private String value; + + public StringPropertyMatcher(String name, String value) { + if (name == null) { + throw new IllegalArgumentException("Property name must not be null!"); + } + if (value == null) { + throw new IllegalArgumentException("Property value must not be null!"); + } + this.name = name; + this.value = value; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean match(String p) { + if (p == null) { + throw new IllegalArgumentException("Property value must not be null!"); + } + return p.equals(value); + } + } + + public static class RegexpPropertyMatcher implements PropertyMatcher { + + private String name; + private Pattern valuePattern; + + public RegexpPropertyMatcher(String name, String value) { + this(name, value, 0); + } + + public RegexpPropertyMatcher(String name, String value, int flags) { + + if (name == null) { + throw new IllegalArgumentException("Property name must not be null!"); + } + + if (value == null) { + throw new IllegalArgumentException("Property value pattern must not be null!"); + } + + this.name = name; + + try { + valuePattern = Pattern.compile(value, flags); + } catch (PatternSyntaxException e) { + throw new IllegalArgumentException("Bad pattern: " + value); + } + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean match(String p) { + if (p == null) { + throw new IllegalArgumentException("Property value must not be null!"); + } + Matcher m = valuePattern.matcher(p); + return m.matches(); + } + } + + public Property selectSingle(PropertyMatcher matcher) { + + final String name = matcher.getName(); + String value = null; + for (int i = 0; i < map.length; i += 2) { + if (map[i] != null && name.equals(map[i])) { + value = map[i + 1]; + break; + } + } + if (value != null && matcher.match(value)) { + return new Property(name, value); + } else { + return null; + } + } + + public interface Provider { + + public Properties getProperties(); + } + + @Override + public String toString() { + List<String[]> pairs = new ArrayList<>(); + for (int i = 0; i < map.length; i += 2) { + if (map[i + 1] != null) { + pairs.add(new String[]{map[i], map[i + 1]}); + } + } + + Collections.sort(pairs, new Comparator<String[]>() { + @Override + public int compare(String[] o1, String[] o2) { + assert o1.length == 2; + assert o2.length == 2; + return o1[0].compareTo(o2[0]); + } + }); + + StringBuilder sb = new StringBuilder(); + sb.append("["); + boolean first = true; + for (String[] p : pairs) { + if (first) { + first = false; + } else { + sb.append(", "); + } + sb.append(p[0] + "=" + p[1]); + } + return sb.append("]").toString(); + } + + public static class PropertySelector<T extends Properties.Provider> { + + private Collection<T> objects; + + public PropertySelector(Collection<T> objects) { + this.objects = objects; + } + + public T selectSingle(PropertyMatcher matcher) { + + for (T t : objects) { + Property p = t.getProperties().selectSingle(matcher); + if (p != null) { + return t; + } + } + + return null; + } + + public List<T> selectMultiple(PropertyMatcher matcher) { + List<T> result = new ArrayList<>(); + + for (T t : objects) { + Property p = t.getProperties().selectSingle(matcher); + if (p != null) { + result.add(t); + } + } + + return result; + } + } + + public String get(String key) { + for (int i = 0; i < map.length; i += 2) { + if (map[i] != null && map[i].equals(key)) { + return map[i + 1]; + } + } + return null; + } + + public void setProperty(String name, String value) { + + for (int i = 0; i < map.length; i += 2) { + if (map[i] != null && map[i].equals(name)) { + String p = map[i + 1]; + if (value == null) { + // remove this property + map[i] = null; + map[i + 1] = null; + } else { + map[i + 1] = value; + } + return; + } + } + if (value == null) { + return; + } + for (int i = 0; i < map.length; i += 2) { + if (map[i] == null) { + map[i] = name; + map[i + 1] = value; + return; + } + } + String[] newMap = new String[map.length + 4]; + System.arraycopy(map, 0, newMap, 0, map.length); + newMap[map.length] = name; + newMap[map.length + 1] = value; + map = newMap; + } + + public void add(Properties properties) { + for (Property p : properties) { + setProperty(p.getName(), p.getValue()); + } + } + + private class PropertiesIterator implements Iterator<Property> { + + int index; + + @Override + public boolean hasNext() { + while (index < map.length && map[index + 1] == null) { + index += 2; + } + return index < map.length; + } + + @Override + public Property next() { + if (index < map.length) { + index += 2; + return new Property(map[index - 2], map[index - 1]); + } + return null; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Not supported yet."); + } + } + + @Override + public Iterator<Property> iterator() { + return new PropertiesIterator(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Property.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.io.Serializable; + +/** + * + * @author Thomas Wuerthinger + */ +public class Property implements Serializable { + + public static final long serialVersionUID = 1L; + private String name; + private String value; + + Property(String name, String value) { + this.name = name; + this.value = value; + + if (value == null) { + throw new IllegalArgumentException("Property value must not be null!"); + } + + if (name == null) { + throw new IllegalArgumentException("Property name must not be null!"); + } + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return name + "=" + value; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Property)) { + return false; + } + Property p2 = (Property) o; + return name.equals(p2.name) && value.equals(p2.value); + } + + @Override + public int hashCode() { + return name.hashCode() * 13 + value.hashCode(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/Source.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class Source { + + private List<InputNode> sourceNodes; + private Set<Integer> set; + + public Source() { + sourceNodes = new ArrayList<>(1); + set = new LinkedHashSet<>(1); + } + + public List<InputNode> getSourceNodes() { + return Collections.unmodifiableList(sourceNodes); + } + + public Set<Integer> getSourceNodesAsSet() { + return Collections.unmodifiableSet(set); + } + + public void addSourceNode(InputNode n) { + if (!set.contains(n.getId())) { + sourceNodes.add(n); + set.add(n.getId()); + } + } + + public interface Provider { + + public Source getSource(); + } + + public void addSourceNodes(Source s) { + for (InputNode n : s.getSourceNodes()) { + addSourceNode(n); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data.serialization; + +import com.sun.hotspot.igv.data.*; +import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler; +import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler; +import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor; +import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler; +import com.sun.hotspot.igv.data.services.GroupCallback; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import javax.swing.SwingUtilities; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.SchemaFactory; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +/** + * + * @author Thomas Wuerthinger + */ +public class Parser { + + public static final String INDENT = " "; + public static final String TOP_ELEMENT = "graphDocument"; + public static final String GROUP_ELEMENT = "group"; + public static final String GRAPH_ELEMENT = "graph"; + public static final String ROOT_ELEMENT = "graphDocument"; + public static final String PROPERTIES_ELEMENT = "properties"; + public static final String EDGES_ELEMENT = "edges"; + public static final String PROPERTY_ELEMENT = "p"; + public static final String EDGE_ELEMENT = "edge"; + public static final String NODE_ELEMENT = "node"; + public static final String NODES_ELEMENT = "nodes"; + public static final String REMOVE_EDGE_ELEMENT = "removeEdge"; + public static final String REMOVE_NODE_ELEMENT = "removeNode"; + public static final String METHOD_NAME_PROPERTY = "name"; + public static final String GROUP_NAME_PROPERTY = "name"; + public static final String METHOD_IS_PUBLIC_PROPERTY = "public"; + public static final String METHOD_IS_STATIC_PROPERTY = "static"; + public static final String TRUE_VALUE = "true"; + public static final String NODE_NAME_PROPERTY = "name"; + public static final String EDGE_NAME_PROPERTY = "name"; + public static final String NODE_ID_PROPERTY = "id"; + public static final String FROM_PROPERTY = "from"; + public static final String TO_PROPERTY = "to"; + public static final String PROPERTY_NAME_PROPERTY = "name"; + public static final String GRAPH_NAME_PROPERTY = "name"; + public static final String FROM_INDEX_PROPERTY = "fromIndex"; + public static final String TO_INDEX_PROPERTY = "toIndex"; + public static final String TO_INDEX_ALT_PROPERTY = "index"; + public static final String LABEL_PROPERTY = "label"; + public static final String METHOD_ELEMENT = "method"; + public static final String INLINE_ELEMENT = "inline"; + public static final String BYTECODES_ELEMENT = "bytecodes"; + public static final String METHOD_BCI_PROPERTY = "bci"; + public static final String METHOD_SHORT_NAME_PROPERTY = "shortName"; + public static final String CONTROL_FLOW_ELEMENT = "controlFlow"; + public static final String BLOCK_NAME_PROPERTY = "name"; + public static final String BLOCK_ELEMENT = "block"; + public static final String SUCCESSORS_ELEMENT = "successors"; + public static final String SUCCESSOR_ELEMENT = "successor"; + public static final String ASSEMBLY_ELEMENT = "assembly"; + public static final String DIFFERENCE_PROPERTY = "difference"; + private TopElementHandler<GraphDocument> xmlDocument = new TopElementHandler<>(); + private Map<Group, Boolean> differenceEncoding = new HashMap<>(); + private Map<Group, InputGraph> lastParsedGraph = new HashMap<>(); + private GroupCallback groupCallback; + private HashMap<String, Integer> idCache = new HashMap<>(); + private ArrayList<Pair<String, String>> blockConnections = new ArrayList<>(); + private int maxId = 0; + private GraphDocument graphDocument; + + private int lookupID(String i) { + try { + return Integer.parseInt(i); + } catch (NumberFormatException nfe) { + // ignore + } + Integer id = idCache.get(i); + if (id == null) { + id = maxId++; + idCache.put(i, id); + } + return id.intValue(); + } + + // <graphDocument> + private ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<GraphDocument, Object>(TOP_ELEMENT) { + + @Override + protected GraphDocument start() throws SAXException { + graphDocument = new GraphDocument(); + return graphDocument; + } + }; + // <group> + private ElementHandler<Group, Folder> groupHandler = new XMLParser.ElementHandler<Group, Folder>(GROUP_ELEMENT) { + + @Override + protected Group start() throws SAXException { + final Group group = new Group(this.getParentObject()); + + String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY); + Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true")))); + + ParseMonitor monitor = getMonitor(); + if (monitor != null) { + monitor.setState(group.getName()); + } + + final Folder parent = getParentObject(); + if (groupCallback == null || parent instanceof Group) { + SwingUtilities.invokeLater(new Runnable(){ + @Override + public void run() { + parent.addElement(group); + } + }); + } + + return group; + } + + @Override + protected void end(String text) throws SAXException { + } + }; + // <method> + private ElementHandler<InputMethod, Group> methodHandler = new XMLParser.ElementHandler<InputMethod, Group>(METHOD_ELEMENT) { + + @Override + protected InputMethod start() throws SAXException { + + InputMethod method = parseMethod(this, getParentObject()); + getParentObject().setMethod(method); + return method; + } + }; + + private InputMethod parseMethod(XMLParser.ElementHandler<?,?> handler, Group group) throws SAXException { + String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY); + int bci = 0; + try { + bci = Integer.parseInt(s); + } catch (NumberFormatException e) { + throw new SAXException(e); + } + InputMethod method = new InputMethod(group, handler.readRequiredAttribute(METHOD_NAME_PROPERTY), handler.readRequiredAttribute(METHOD_SHORT_NAME_PROPERTY), bci); + return method; + } + // <bytecodes> + private HandoverElementHandler<InputMethod> bytecodesHandler = new XMLParser.HandoverElementHandler<InputMethod>(BYTECODES_ELEMENT, true) { + + @Override + protected void end(String text) throws SAXException { + getParentObject().setBytecodes(text); + } + }; + // <inlined> + private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT); + // <inlined><method> + private ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<InputMethod, InputMethod>(METHOD_ELEMENT) { + + @Override + protected InputMethod start() throws SAXException { + InputMethod method = parseMethod(this, getParentObject().getGroup()); + getParentObject().addInlined(method); + return method; + } + }; + // <graph> + private ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<InputGraph, Group>(GRAPH_ELEMENT) { + + @Override + protected InputGraph start() throws SAXException { + String name = readAttribute(GRAPH_NAME_PROPERTY); + InputGraph curGraph = new InputGraph(name); + if (differenceEncoding.get(getParentObject())) { + InputGraph previous = lastParsedGraph.get(getParentObject()); + lastParsedGraph.put(getParentObject(), curGraph); + if (previous != null) { + for (InputNode n : previous.getNodes()) { + curGraph.addNode(n); + } + for (InputEdge e : previous.getEdges()) { + curGraph.addEdge(e); + } + } + } + return curGraph; + } + + @Override + protected void end(String text) throws SAXException { + // NOTE: Some graphs intentionally don't provide blocks. Instead + // they later generate the blocks from other information such + // as node properties (example: ServerCompilerScheduler). + // Thus, we shouldn't assign nodes that don't belong to any + // block to some artificial block below unless blocks are + // defined and nodes are assigned to them. + + final InputGraph graph = getObject(); + final Group parent = getParentObject(); + if (graph.getBlocks().size() > 0) { + boolean blocksContainNodes = false; + for (InputBlock b : graph.getBlocks()) { + if (b.getNodes().size() > 0) { + blocksContainNodes = true; + break; + } + } + + if (!blocksContainNodes) { + graph.clearBlocks(); + blockConnections.clear(); + } else { + // Blocks and their nodes defined: add other nodes to an + // artificial "no block" block + InputBlock noBlock = null; + for (InputNode n : graph.getNodes()) { + if (graph.getBlock(n) == null) { + if (noBlock == null) { + noBlock = graph.addBlock("(no block)"); + } + + noBlock.addNode(n.getId()); + } + + assert graph.getBlock(n) != null; + } + } + } + + // Resolve block successors + for (Pair<String, String> p : blockConnections) { + final InputBlock left = graph.getBlock(p.getLeft()); + assert left != null; + final InputBlock right = graph.getBlock(p.getRight()); + assert right != null; + graph.addBlockEdge(left, right); + } + blockConnections.clear(); + + SwingUtilities.invokeLater(new Runnable(){ + + @Override + public void run() { + // Add to group + parent.addElement(graph); + } + }); + } + }; + // <nodes> + private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT); + // <controlFlow> + private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT); + // <block> + private ElementHandler<InputBlock, InputGraph> blockHandler = new ElementHandler<InputBlock, InputGraph>(BLOCK_ELEMENT) { + + @Override + protected InputBlock start() throws SAXException { + InputGraph graph = getParentObject(); + String name = readRequiredAttribute(BLOCK_NAME_PROPERTY); + InputBlock b = graph.addBlock(name); + for (InputNode n : b.getNodes()) { + assert graph.getBlock(n).equals(b); + } + return b; + } + }; + // <nodes> + private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT); + // <node> + private ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<InputBlock, InputBlock>(NODE_ELEMENT) { + + @Override + protected InputBlock start() throws SAXException { + String s = readRequiredAttribute(NODE_ID_PROPERTY); + + int id = 0; + try { + id = lookupID(s); + } catch (NumberFormatException e) { + throw new SAXException(e); + } + getParentObject().addNode(id); + return getParentObject(); + } + }; + // <successors> + private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT); + // <successor> + private ElementHandler<InputBlock, InputBlock> successorHandler = new ElementHandler<InputBlock, InputBlock>(SUCCESSOR_ELEMENT) { + + @Override + protected InputBlock start() throws SAXException { + String name = readRequiredAttribute(BLOCK_NAME_PROPERTY); + blockConnections.add(new Pair<>(getParentObject().getName(), name)); + return getParentObject(); + } + }; + // <node> + private ElementHandler<InputNode, InputGraph> nodeHandler = new ElementHandler<InputNode, InputGraph>(NODE_ELEMENT) { + + @Override + protected InputNode start() throws SAXException { + String s = readRequiredAttribute(NODE_ID_PROPERTY); + int id = 0; + try { + id = lookupID(s); + } catch (NumberFormatException e) { + throw new SAXException(e); + } + InputNode node = new InputNode(id); + getParentObject().addNode(node); + return node; + } + }; + // <removeNode> + private ElementHandler<InputNode, InputGraph> removeNodeHandler = new ElementHandler<InputNode, InputGraph>(REMOVE_NODE_ELEMENT) { + + @Override + protected InputNode start() throws SAXException { + String s = readRequiredAttribute(NODE_ID_PROPERTY); + int id = 0; + try { + id = lookupID(s); + } catch (NumberFormatException e) { + throw new SAXException(e); + } + return getParentObject().removeNode(id); + } + }; + // <graph> + private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT); + + // Local class for edge elements + private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> { + + public EdgeElementHandler(String name) { + super(name); + } + + @Override + protected InputEdge start() throws SAXException { + int fromIndex = 0; + int toIndex = 0; + int from = -1; + int to = -1; + String label = null; + + try { + String fromIndexString = readAttribute(FROM_INDEX_PROPERTY); + if (fromIndexString != null) { + fromIndex = Integer.parseInt(fromIndexString); + } + + String toIndexString = readAttribute(TO_INDEX_PROPERTY); + if (toIndexString == null) { + toIndexString = readAttribute(TO_INDEX_ALT_PROPERTY); + } + if (toIndexString != null) { + toIndex = Integer.parseInt(toIndexString); + } + + label = readAttribute(LABEL_PROPERTY); + + from = lookupID(readRequiredAttribute(FROM_PROPERTY)); + to = lookupID(readRequiredAttribute(TO_PROPERTY)); + } catch (NumberFormatException e) { + throw new SAXException(e); + } + + InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label); + return start(conn); + } + + protected InputEdge start(InputEdge conn) throws SAXException { + return conn; + } + } + // <edge> + private EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) { + + @Override + protected InputEdge start(InputEdge conn) throws SAXException { + getParentObject().addEdge(conn); + return conn; + } + }; + // <removeEdge> + private EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) { + + @Override + protected InputEdge start(InputEdge conn) throws SAXException { + getParentObject().removeEdge(conn); + return conn; + } + }; + // <properties> + private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT); + // <properties> + private HandoverElementHandler<Group> groupPropertiesHandler = new HandoverElementHandler<Group>(PROPERTIES_ELEMENT) { + + @Override + public void end(String text) throws SAXException { + if (groupCallback != null && getParentObject().getParent() instanceof GraphDocument) { + final Group group = getParentObject(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + groupCallback.started(group); + } + }); + } + } + }; + // <property> + private ElementHandler<String, Properties.Provider> propertyHandler = new XMLParser.ElementHandler<String, Properties.Provider>(PROPERTY_ELEMENT, true) { + + @Override + public String start() throws SAXException { + return readRequiredAttribute(PROPERTY_NAME_PROPERTY); + } + + @Override + public void end(String text) { + getParentObject().getProperties().setProperty(getObject(), text.trim()); + } + }; + + public Parser() { + this(null); + } + + public Parser(GroupCallback groupCallback) { + + this.groupCallback = groupCallback; + + // Initialize dependencies + xmlDocument.addChild(topHandler); + topHandler.addChild(groupHandler); + + groupHandler.addChild(methodHandler); + groupHandler.addChild(graphHandler); + groupHandler.addChild(groupHandler); + + methodHandler.addChild(inlinedHandler); + methodHandler.addChild(bytecodesHandler); + + inlinedHandler.addChild(inlinedMethodHandler); + inlinedMethodHandler.addChild(bytecodesHandler); + inlinedMethodHandler.addChild(inlinedHandler); + + graphHandler.addChild(nodesHandler); + graphHandler.addChild(edgesHandler); + graphHandler.addChild(controlFlowHandler); + + controlFlowHandler.addChild(blockHandler); + + blockHandler.addChild(successorsHandler); + successorsHandler.addChild(successorHandler); + blockHandler.addChild(blockNodesHandler); + blockNodesHandler.addChild(blockNodeHandler); + + nodesHandler.addChild(nodeHandler); + nodesHandler.addChild(removeNodeHandler); + edgesHandler.addChild(edgeHandler); + edgesHandler.addChild(removeEdgeHandler); + + methodHandler.addChild(propertiesHandler); + inlinedMethodHandler.addChild(propertiesHandler); + topHandler.addChild(propertiesHandler); + groupHandler.addChild(groupPropertiesHandler); + graphHandler.addChild(propertiesHandler); + nodeHandler.addChild(propertiesHandler); + propertiesHandler.addChild(propertyHandler); + groupPropertiesHandler.addChild(propertyHandler); + } + + // Returns a new GraphDocument object deserialized from an XML input source. + public GraphDocument parse(InputSource source, XMLParser.ParseMonitor monitor) throws SAXException { + XMLReader reader = createReader(); + + reader.setContentHandler(new XMLParser(xmlDocument, monitor)); + try { + reader.parse(source); + } catch (IOException ex) { + throw new SAXException(ex); + } + + return graphDocument; + } + + private XMLReader createReader() throws SAXException { + try { + SAXParserFactory pfactory = SAXParserFactory.newInstance(); + pfactory.setValidating(false); + pfactory.setNamespaceAware(true); + + // Enable schema validation + SchemaFactory sfactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); + InputStream stream = Parser.class.getResourceAsStream("graphdocument.xsd"); + pfactory.setSchema(sfactory.newSchema(new Source[]{new StreamSource(stream)})); + + return pfactory.newSAXParser().getXMLReader(); + } catch (ParserConfigurationException ex) { + throw new SAXException(ex); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data.serialization; + +import com.sun.hotspot.igv.data.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author Thomas Wuerthinger + */ +public class Printer { + + private InputStream in; + + public Printer() { + this(null); + } + + public Printer(InputStream inputStream) { + this.in = inputStream; + } + + public void export(Writer writer, GraphDocument document) { + + XMLWriter xmlWriter = new XMLWriter(writer); + + try { + export(xmlWriter, document); + } catch (IOException ex) { + } + } + + private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException { + xmlWriter.startTag(Parser.ROOT_ELEMENT); + xmlWriter.writeProperties(document.getProperties()); + for (FolderElement e : document.getElements()) { + if (e instanceof Group) { + export(xmlWriter, (Group) e); + } else if (e instanceof InputGraph) { + export(xmlWriter, (InputGraph)e, null, false); + } + } + + xmlWriter.endTag(); + xmlWriter.flush(); + } + + private void export(XMLWriter writer, Group g) throws IOException { + Properties attributes = new Properties(); + attributes.setProperty("difference", Boolean.toString(true)); + writer.startTag(Parser.GROUP_ELEMENT, attributes); + writer.writeProperties(g.getProperties()); + + boolean shouldExport = true; + if (in != null) { + char c = (char) in.read(); + if (c != 'y') { + shouldExport = false; + } + } + + if (shouldExport) { + if (g.getMethod() != null) { + export(writer, g.getMethod()); + } + + InputGraph previous = null; + for (FolderElement e : g.getElements()) { + if (e instanceof InputGraph) { + InputGraph graph = (InputGraph) e; + export(writer, graph, previous, true); + previous = graph; + } else if (e instanceof Group) { + export(writer, (Group) e); + } + } + } + + writer.endTag(); + } + + public void export(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference) throws IOException { + + writer.startTag(Parser.GRAPH_ELEMENT); + writer.writeProperties(graph.getProperties()); + writer.startTag(Parser.NODES_ELEMENT); + + Set<InputNode> removed = new HashSet<>(); + Set<InputNode> equal = new HashSet<>(); + + if (previous != null) { + for (InputNode n : previous.getNodes()) { + int id = n.getId(); + InputNode n2 = graph.getNode(id); + if (n2 == null) { + removed.add(n); + } else if (n.equals(n2)) { + equal.add(n); + } + } + } + + if (difference) { + for (InputNode n : removed) { + writer.simpleTag(Parser.REMOVE_NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); + } + } + + for (InputNode n : graph.getNodes()) { + if (!difference || !equal.contains(n)) { + writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); + writer.writeProperties(n.getProperties()); + writer.endTag(); + } + } + + writer.endTag(); + + writer.startTag(Parser.EDGES_ELEMENT); + Set<InputEdge> removedEdges = new HashSet<>(); + Set<InputEdge> equalEdges = new HashSet<>(); + + if (previous != null) { + for (InputEdge e : previous.getEdges()) { + if (graph.getEdges().contains(e)) { + equalEdges.add(e); + } else { + removedEdges.add(e); + } + } + } + + if (difference) { + for (InputEdge e : removedEdges) { + writer.simpleTag(Parser.REMOVE_EDGE_ELEMENT, createProperties(e)); + } + } + + for (InputEdge e : graph.getEdges()) { + if (!difference || !equalEdges.contains(e)) { + if (!equalEdges.contains(e)) { + writer.simpleTag(Parser.EDGE_ELEMENT, createProperties(e)); + } + } + } + + writer.endTag(); + + writer.startTag(Parser.CONTROL_FLOW_ELEMENT); + for (InputBlock b : graph.getBlocks()) { + writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName())); + + if (b.getSuccessors().size() > 0) { + writer.startTag(Parser.SUCCESSORS_ELEMENT); + for (InputBlock s : b.getSuccessors()) { + writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName())); + } + writer.endTag(); + } + + if (b.getNodes().size() > 0) { + writer.startTag(Parser.NODES_ELEMENT); + for (InputNode n : b.getNodes()) { + writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + "")); + } + writer.endTag(); + } + + writer.endTag(); + } + + writer.endTag(); + writer.endTag(); + } + + private void export(XMLWriter w, InputMethod method) throws IOException { + + w.startTag(Parser.METHOD_ELEMENT, new Properties(Parser.METHOD_BCI_PROPERTY, method.getBci() + "", Parser.METHOD_NAME_PROPERTY, method.getName(), Parser.METHOD_SHORT_NAME_PROPERTY, method.getShortName())); + + w.writeProperties(method.getProperties()); + + if (method.getInlined().size() > 0) { + w.startTag(Parser.INLINE_ELEMENT); + for (InputMethod m : method.getInlined()) { + export(w, m); + } + w.endTag(); + } + + w.startTag(Parser.BYTECODES_ELEMENT); + + StringBuilder b = new StringBuilder(); + b.append("<![CDATA[\n"); + for (InputBytecode code : method.getBytecodes()) { + b.append(code.getBci()); + b.append(" "); + b.append(code.getName()); + b.append("\n"); + } + + b.append("]]>"); + w.write(b.toString()); + w.endTag(); + w.endTag(); + } + + private Properties createProperties(InputEdge edge) { + Properties p = new Properties(); + if (edge.getToIndex() != 0) { + p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex())); + } + if (edge.getFromIndex() != 0) { + p.setProperty(Parser.FROM_INDEX_PROPERTY, Integer.toString(edge.getFromIndex())); + } + p.setProperty(Parser.TO_PROPERTY, Integer.toString(edge.getTo())); + p.setProperty(Parser.FROM_PROPERTY, Integer.toString(edge.getFrom())); + return p; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data.serialization; + +import com.sun.hotspot.igv.data.Properties; +import java.util.HashMap; +import java.util.Stack; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +/** + * + * @author Thomas Wuerthinger + */ +public class XMLParser implements ContentHandler { + + public static interface ParseMonitor { + + public void setProgress(double d); + + public void setState(String state); + } + + public static class MissingAttributeException extends SAXException { + + private String name; + + public MissingAttributeException(String name) { + super("Missing attribute \"" + name + "\""); + this.name = name; + } + + public String getAttributeName() { + return this.getMessage(); + } + } + + public static class HandoverElementHandler<P> extends ElementHandler<P, P> { + + @Override + protected P start() throws SAXException { + return getParentObject(); + } + + public HandoverElementHandler(String name) { + super(name); + } + + public HandoverElementHandler(String name, boolean needsText) { + super(name, needsText); + } + } + + public static class TopElementHandler<P> extends ElementHandler<P, Object> { + + public TopElementHandler() { + super(null); + } + } + + public static class ElementHandler<T, P> { + + private String name; + private Stack<T> object = new Stack<>(); + private Attributes attr; + private StringBuilder currentText; + private ParseMonitor monitor; + private HashMap<String, ElementHandler<?, ? super T>> hashtable; + private boolean needsText; + private Stack<ElementHandler<P, ?>> parentElement = new Stack<>(); + private Stack<P> parentObject = new Stack<>(); + + public ElementHandler(String name) { + this(name, false); + } + + public ElementHandler<P, ?> getParentElement() { + return parentElement.peek(); + } + + public P getParentObject() { + return parentObject.peek(); + } + + protected boolean needsText() { + return needsText; + } + + public ElementHandler(String name, boolean needsText) { + this.hashtable = new HashMap<>(); + this.name = name; + this.needsText = needsText; + } + + public ParseMonitor getMonitor() { + return monitor; + } + + public ElementHandler<?, ? super T> getChild(String name) { + return hashtable.get(name); + } + + public void addChild(ElementHandler<?, ? super T> handler) { + assert handler != null; + hashtable.put(handler.getName(), handler); + } + + public String getName() { + return name; + } + + public T getObject() { + return object.size() == 0 ? null : object.peek(); + } + + public String readAttribute(String name) { + return attr.getValue(name); + } + + public String readRequiredAttribute(String name) throws SAXException { + String s = readAttribute(name); + if (s == null) { + throw new MissingAttributeException(name); + } + return s; + } + + public void processAttributesAsProperties(Properties p) { + int length = attr.getLength(); + for (int i = 0; i < length; i++) { + String val = attr.getValue(i); + String localName = attr.getLocalName(i); + p.setProperty(val, localName); + } + } + + public void startElement(ElementHandler<P, ?> parentElement, Attributes attr, ParseMonitor monitor) throws SAXException { + this.currentText = new StringBuilder(); + this.attr = attr; + this.monitor = monitor; + this.parentElement.push(parentElement); + parentObject.push(parentElement.getObject()); + object.push(start()); + } + + protected T start() throws SAXException { + return null; + } + + protected void end(String text) throws SAXException { + + } + + public void endElement() throws SAXException { + end(currentText.toString()); + object.pop(); + parentElement.pop(); + parentObject.pop(); + } + + protected void text(char[] c, int start, int length) { + assert currentText != null; + currentText.append(c, start, length); + } + } + private Stack<ElementHandler> stack; + private ParseMonitor monitor; + + public XMLParser(TopElementHandler rootHandler, ParseMonitor monitor) { + this.stack = new Stack<>(); + this.monitor = monitor; + this.stack.push(rootHandler); + } + + @Override + public void setDocumentLocator(Locator locator) { + if (monitor != null) { + monitor.setState("Starting parsing"); + } + } + + @Override + public void startDocument() throws SAXException { + } + + @Override + public void endDocument() throws SAXException { + } + + @Override + public void startPrefixMapping(String prefix, String uri) throws SAXException { + } + + @Override + public void endPrefixMapping(String prefix) throws SAXException { + } + + @SuppressWarnings("unchecked") + @Override + public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { + assert !stack.isEmpty(); + + ElementHandler parent = stack.peek(); + if (parent != null) { + ElementHandler child = parent.getChild(qName); + if (child != null) { + child.startElement(parent, atts, monitor); + stack.push(child); + return; + } + } + + stack.push(null); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + ElementHandler handler = stack.pop(); + if (handler != null) { + handler.endElement(); + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + + assert !stack.isEmpty(); + + + ElementHandler top = stack.peek(); + if (top != null && top.needsText()) { + top.text(ch, start, length); + } + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + } + + @Override + public void processingInstruction(String target, String data) throws SAXException { + } + + @Override + public void skippedEntity(String name) throws SAXException { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1998, 2008, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data.serialization; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Property; +import java.io.IOException; +import java.io.Writer; +import java.util.Stack; + +/** + * + * @author Thomas Wuerthinger + */ +public class XMLWriter extends Writer { + + private Writer inner; + private Stack<String> elementStack; + + public XMLWriter(Writer inner) { + this.inner = inner; + elementStack = new Stack<>(); + } + + @Override + public void write(char[] arr) throws IOException { + write(arr, 0, arr.length); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + for (int i = off; i < off + len; i++) { + char c = cbuf[i]; + if (c == '>') { + inner.write(">"); + } else if (c == '<') { + inner.write("<"); + } else if (c == '&') { + inner.write("&"); + } else { + inner.write(c); + } + } + } + + @Override + public void flush() throws IOException { + inner.flush(); + } + + @Override + public void close() throws IOException { + inner.close(); + } + + public void endTag() throws IOException { + inner.write("</" + elementStack.pop() + ">\n"); + } + + public void startTag(String name) throws IOException { + inner.write("<" + name + ">\n"); + elementStack.push(name); + } + + public void simpleTag(String name) throws IOException { + inner.write("<" + name + "/>\n"); + } + + public void startTag(String name, Properties attributes) throws IOException { + inner.write("<" + name); + elementStack.push(name); + + for (Property p : attributes) { + inner.write(" " + p.getName() + "=\""); + write(p.getValue().toCharArray()); + inner.write("\""); + } + + inner.write(">\n"); + } + + public void simpleTag(String name, Properties attributes) throws IOException { + inner.write("<" + name); + + for (Property p : attributes) { + inner.write(" " + p.getName() + "=\""); + write(p.getValue().toCharArray()); + inner.write("\""); + } + + inner.write("/>\n"); + } + + public void writeProperties(Properties props) throws IOException { + if (props.iterator().hasNext() == false) { + return; + } + + startTag(Parser.PROPERTIES_ELEMENT); + + for (Property p : props) { + startTag(Parser.PROPERTY_ELEMENT, new Properties(Parser.PROPERTY_NAME_PROPERTY, p.getName())); + this.write(p.getValue().toCharArray()); + endTag(); + } + + endTag(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + + <xsd:element name="graphDocument"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" /> + <xsd:element name="group" type="groupType" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:complexType name="groupType"> + <xsd:sequence> + <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" /> + <xsd:element name="assembly" type="assemblyType" minOccurs="0" maxOccurs="1" /> + <xsd:element name="method" type="methodType" minOccurs="0" maxOccurs="1" /> + <xsd:element name="graph" type="graphType" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + <xsd:attribute name="difference" use="optional" /> + </xsd:complexType> + + <xsd:complexType name="propertiesType"> + <xsd:sequence> + <xsd:element name="p" minOccurs="0" maxOccurs="unbounded"> + <xsd:complexType> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="name" use="required" /> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:simpleType name="assemblyType"> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + + <xsd:complexType name="methodType"> + <xsd:all> + <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" /> + <xsd:element name="bytecodes" minOccurs="0" maxOccurs="1"> + <xsd:simpleType> + <xsd:restriction base="xsd:string" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="inlined" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="method" type="methodType" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:all> + <xsd:attribute name="bci" type="xsd:int" use="required" /> + <xsd:attribute name="shortName" type="xsd:string" use="required" /> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + + <xsd:complexType name="graphType"> + <xsd:sequence> + <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" /> + + <xsd:element name="nodes" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="node" type="nodeType" /> + <xsd:element name="removeNode" type="nodeRefType" /> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="edges" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="edge" type="edgeType" /> + <xsd:element name="removeEdge" type="edgeType" /> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="controlFlow" type="controlFlowType" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + + <xsd:attribute name="name" use="optional" /> + </xsd:complexType> + + <xsd:complexType name="nodeType"> + <xsd:sequence> + <xsd:element name="properties" type="propertiesType" minOccurs="0" maxOccurs="1" /> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:int" use="required" /> + </xsd:complexType> + + <xsd:complexType name="nodeRefType"> + <xsd:attribute name="id" type="xsd:int" use="required" /> + </xsd:complexType> + + <xsd:complexType name="edgeType"> + <xsd:attribute name="from" type="xsd:int" use="required" /> + <xsd:attribute name="to" type="xsd:int" use="required" /> + <xsd:attribute name="label" type="xsd:string" use="optional" /> + <xsd:attribute name="fromIndex" type="xsd:int" use="optional" /> + + <!-- These are aliases and should be mutually exclusive --> + <xsd:attribute name="toIndex" type="xsd:int" use="optional" /> + <xsd:attribute name="index" type="xsd:int" use="optional" /> + </xsd:complexType> + + <xsd:complexType name="controlFlowType"> + <xsd:sequence> + <xsd:element name="block" type="blockType" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="blockType"> + <xsd:all> + <xsd:element name="successors" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="successor" minOccurs="0" maxOccurs="unbounded"> + <xsd:complexType> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="nodes" minOccurs="0" maxOccurs="1"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="node" type="nodeRefType" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:all> + + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> +</xsd:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data.services; + +import com.sun.hotspot.igv.data.InputGraph; + +/** + * + * @author Thomas Wuerthinger + */ +public interface GraphViewer { + + public void view(InputGraph graph); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data.services; + +import com.sun.hotspot.igv.data.Group; + +/** + * + * @author Thomas Wuerthinger + */ +public interface GroupCallback { + + public void started(Group g); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data.services; + +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.data.InputNode; +import java.util.Set; + +/** + * + * @author Thomas Wuerthinger + */ +public interface InputGraphProvider { + + InputGraph getGraph(); + + void setSelectedNodes(Set<InputNode> nodes); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data.services; + +import com.sun.hotspot.igv.data.InputBlock; +import com.sun.hotspot.igv.data.InputGraph; +import java.util.Collection; + +/** + * + * @author Thomas Wuerthinger + */ +public interface Scheduler { + + public Collection<InputBlock> schedule(InputGraph graph); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ChangedEventTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import static org.junit.Assert.assertEquals; +import org.junit.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class ChangedEventTest { + + public ChangedEventTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of addListener method, of class Event. + */ + @Test + public void testBase() { + + ChangedEvent<Integer> e = new ChangedEvent<>(5); + final int[] fireCount = new int[1]; + + e.addListener(new ChangedListener<Integer>() { + @Override + public void changed(Integer s) { + assertEquals(s.intValue(), 5); + fireCount[0]++; + } + }); + + e.fire(); + assertEquals(1, fireCount[0]); + + e.fire(); + assertEquals(2, fireCount[0]); + + e.beginAtomic(); + + e.fire(); + assertEquals(2, fireCount[0]); + + e.fire(); + assertEquals(2, fireCount[0]); + + e.fire(); + assertEquals(2, fireCount[0]); + + e.endAtomic(); + assertEquals(3, fireCount[0]); + + } + + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ControllableChangedListenerTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import static org.junit.Assert.*; +import org.junit.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class ControllableChangedListenerTest { + + public ControllableChangedListenerTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of isEnabled method, of class ControllableChangedListener. + */ + @Test + public void testBase() { + + final boolean[] hasFired = new boolean[1]; + final boolean[] shouldFire = new boolean[1]; + final Integer[] valueToFire = new Integer[1]; + ControllableChangedListener<Integer> l = new ControllableChangedListener<Integer>() { + + @Override + public void filteredChanged(Integer value) { + assertTrue(shouldFire[0]); + assertEquals(valueToFire[0], value); + hasFired[0] = true; + } + }; + + shouldFire[0] = true; + valueToFire[0] = 1; + hasFired[0] = false; + l.changed(1); + assertTrue(hasFired[0]); + + shouldFire[0] = false; + hasFired[0] = false; + l.setEnabled(false); + l.changed(1); + assertFalse(hasFired[0]); + + shouldFire[0] = true; + valueToFire[0] = 1; + hasFired[0] = false; + l.setEnabled(true); + l.changed(1); + assertTrue(hasFired[0]); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/GroupTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.Arrays; +import java.util.HashSet; +import static org.junit.Assert.assertEquals; +import org.junit.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class GroupTest { + + public GroupTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of getAllNodes method, of class Group. + */ + @Test + public void testGetAllNodes() { + final Group g = new Group(null); + final InputGraph graph1 = new InputGraph("1"); + final InputGraph graph2 = new InputGraph("2"); + g.addElement(graph1); + g.addElement(graph2); + graph1.addNode(new InputNode(1)); + graph1.addNode(new InputNode(2)); + graph2.addNode(new InputNode(2)); + graph2.addNode(new InputNode(3)); + assertEquals(g.getAllNodes(), new HashSet(Arrays.asList(1, 2, 3))); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputGraphTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.data; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputGraphTest { + + /** + * 1 + * / \ + * 2 3 + * \ | 5 + * \ | / + * 4 + */ + private static InputGraph referenceGraph; + + private static InputGraph emptyGraph; + + private static final InputNode N1 = new InputNode(1); + private static final InputNode N2 = new InputNode(2); + private static final InputNode N3 = new InputNode(3); + private static final InputNode N4 = new InputNode(4); + private static final InputNode N5 = new InputNode(5); + private static final InputEdge E12 = new InputEdge((char)0, 1, 2); + private static final InputEdge E13 = new InputEdge((char)0, 1, 3); + private static final InputEdge E24 = new InputEdge((char)0, 2, 4); + private static final InputEdge E34 = new InputEdge((char)0, 3, 4); + private static final InputEdge E54 = new InputEdge((char)0, 5, 4); + + public InputGraphTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + Group group = new Group(null); + + emptyGraph = new InputGraph("emptyGraph"); + group.addElement(emptyGraph); + + referenceGraph = new InputGraph("referenceGraph"); + group.addElement(referenceGraph); + referenceGraph.addNode(N1); + referenceGraph.addNode(N2); + referenceGraph.addNode(N3); + referenceGraph.addNode(N4); + referenceGraph.addNode(N5); + + referenceGraph.addEdge(E12); + referenceGraph.addEdge(E13); + referenceGraph.addEdge(E24); + referenceGraph.addEdge(E34); + referenceGraph.addEdge(E54); + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of equals method, of class InputGraph. + */ + @Test + public void testEquals() { + + Group parentA = new Group(null); + InputGraph a = new InputGraph("graph"); + parentA.addElement(a); + + Group parentB = new Group(null); + InputGraph b = new InputGraph("graph"); + parentB.addElement(b); + + InputGraph c = new InputGraph("graph"); + parentB.addElement(b); + + Util.assertGraphEquals(a, b); + Util.assertGraphEquals(b, c); + + a.addNode(new InputNode(1)); + Util.assertGraphNotEquals(a, b); + + b.addNode(new InputNode(1)); + Util.assertGraphEquals(a, b); + } + + /** + * Test of findRootNodes method, of class InputGraph. + */ + @Test + public void testFindRootNodes() { + assertTrue(emptyGraph.findRootNodes().isEmpty()); + + List<InputNode> result = referenceGraph.findRootNodes(); + assertTrue(result.size() == 2); + assertTrue(result.contains(N1)); + assertTrue(result.contains(N5)); + } + + /** + * Test of findAllOutgoingEdges method, of class InputGraph. + */ + @Test + public void testFindAllOutgoingEdges() { + assertTrue(emptyGraph.findAllOutgoingEdges().isEmpty()); + + Map<InputNode, List<InputEdge>> result = referenceGraph.findAllOutgoingEdges(); + assertTrue(result.size() == 5); + assertEquals(result.get(N1), Arrays.asList(E12, E13)); + assertEquals(result.get(N2), Arrays.asList(E24)); + assertEquals(result.get(N3), Arrays.asList(E34)); + assertEquals(result.get(N4), Arrays.asList()); + assertEquals(result.get(N5), Arrays.asList(E54)); + } + + /** + * Test of findAllIngoingEdges method, of class InputGraph. + */ + @Test + public void testFindAllIngoingEdges() { + assertTrue(emptyGraph.findAllIngoingEdges().isEmpty()); + + Map<InputNode, List<InputEdge>> result = referenceGraph.findAllIngoingEdges(); + assertTrue(result.size() == 5); + assertEquals(result.get(N1), Arrays.asList()); + assertEquals(result.get(N2), Arrays.asList(E12)); + assertEquals(result.get(N3), Arrays.asList(E13)); + assertEquals(result.get(N4), Arrays.asList(E24, E34, E54)); + assertEquals(result.get(N5), Arrays.asList()); + } + + /** + * Test of findOutgoingEdges method, of class InputGraph. + */ + @Test + public void testFindOutgoingEdges() { + assertTrue(emptyGraph.findOutgoingEdges(new InputNode(1)).isEmpty()); + + assertEquals(referenceGraph.findOutgoingEdges(N1), Arrays.asList(E12, E13)); + assertEquals(referenceGraph.findOutgoingEdges(N2), Arrays.asList(E24)); + assertEquals(referenceGraph.findOutgoingEdges(N3), Arrays.asList(E34)); + assertEquals(referenceGraph.findOutgoingEdges(N4), Arrays.asList()); + assertEquals(referenceGraph.findOutgoingEdges(N5), Arrays.asList(E54)); + } + + /** + * Test of getNext method, of class InputGraph. + */ + @Test + public void testGetNextPrev() { + final Group group = new Group(null); + + final InputGraph a = new InputGraph("a"); + + final InputGraph b = new InputGraph("b"); + + final InputGraph c = new InputGraph("c"); + group.addElement(a); + group.addElement(b); + group.addElement(c); + + assertEquals(null, a.getPrev()); + assertEquals(b, a.getNext()); + + assertEquals(a, b.getPrev()); + assertEquals(c, b.getNext()); + + assertEquals(b, c.getPrev()); + assertEquals(null, c.getNext()); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputMethodTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,93 @@ +/* + * 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.sun.hotspot.igv.data; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import org.junit.*; + +/** + * + * @author Thomas + */ +public class InputMethodTest { + + public InputMethodTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + + /** + * Test of getBytecodes method, of class InputMethod. + */ + @Test + public void testGetSetBytecodes() { + + final String input = "0 iload_0\n" + + "1 iconst_1\n" + + "2 if_icmpne 7\n" + + "5 iconst_1\n" + + "6 ireturn\n" + + "7 iconst_0\n" + + "8 ireturn"; + + final Group g = new Group(null); + InputMethod m = new InputMethod(g, "name", "shortName", -1); + m.setBytecodes(input); + + assertThat(m.getBytecodes().size(), is(7)); + + assertThat(m.getBytecodes().get(0).getBci(), is(0)); + assertThat(m.getBytecodes().get(1).getBci(), is(1)); + assertThat(m.getBytecodes().get(2).getBci(), is(2)); + assertThat(m.getBytecodes().get(3).getBci(), is(5)); + + assertThat(m.getBytecodes().get(0).getName(), is("iload_0")); + assertThat(m.getBytecodes().get(1).getName(), is("iconst_1")); + assertThat(m.getBytecodes().get(2).getName(), is("if_icmpne 7")); + assertThat(m.getBytecodes().get(6).getName(), is("ireturn")); + + assertThat(m.getBytecodes().get(2).getInlined(), nullValue()); + assertThat(m.getBytecodes().get(6).getInlined(), nullValue()); + } + + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PairTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data; + +import static org.junit.Assert.*; +import org.junit.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class PairTest { + + public PairTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of getLeft method, of class Pair. + */ + @Test + public void testBase() { + Pair p = new Pair(); + assertTrue(p.getLeft() == null); + assertTrue(p.getRight() == null); + assertEquals("[null/null]", p.toString()); + assertFalse(p.equals(null)); + + Pair<Integer, Integer> p2 = new Pair(1, 2); + assertTrue(p2.getLeft().intValue() == 1); + assertTrue(p2.getRight().intValue() == 2); + assertFalse(p.equals(p2)); + assertFalse(p2.equals(p)); + assertFalse(p.hashCode() == p2.hashCode()); + assertEquals("[1/2]", p2.toString()); + + Pair p3 = new Pair(1, 2); + assertTrue(p2.equals(p3)); + assertTrue(p2.hashCode() == p3.hashCode()); + + p2.setLeft(2); + assertFalse(p2.equals(p3)); + assertTrue(p2.getLeft().intValue() == 2); + assertTrue(p2.getRight().intValue() == 2); + assertFalse(p2.hashCode() == p3.hashCode()); + assertEquals("[2/2]", p2.toString()); + + p2.setRight(1); + assertFalse(p2.equals(p3)); + assertTrue(p2.getLeft().intValue() == 2); + assertTrue(p2.getRight().intValue() == 1); + assertFalse(p2.hashCode() == p3.hashCode()); + assertEquals("[2/1]", p2.toString()); + + p3.setLeft(2); + p3.setRight(1); + assertTrue(p2.hashCode() == p3.hashCode()); + assertTrue(p2.equals(p3)); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertiesTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,401 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data; + +import com.sun.hotspot.igv.data.Properties.InvertPropertyMatcher; +import com.sun.hotspot.igv.data.Properties.PropertyMatcher; +import com.sun.hotspot.igv.data.Properties.PropertySelector; +import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher; +import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import junit.framework.TestCase; + +/** + * + * @author Thomas Wuerthinger + */ +public class PropertiesTest extends TestCase { + + + + public PropertiesTest(String testName) { + super(testName); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + /** + * Test of equals method, of class Properties. + */ + public void testEquals() { + Properties a = new Properties(); + assertFalse(a.equals(null)); + assertTrue(a.equals(a)); + + Properties b = new Properties(); + assertTrue(a.equals(b)); + assertTrue(a.hashCode() == b.hashCode()); + + a.setProperty("p1", "1"); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + assertFalse(a.hashCode() == b.hashCode()); + + b.setProperty("p1", "1"); + assertTrue(a.equals(b)); + assertTrue(a.hashCode() == b.hashCode()); + + Properties c = new Properties(a); + assertTrue(c.equals(a)); + assertTrue(c.equals(b)); + + c.setProperty("p1", "2"); + assertFalse(c.equals(b)); + assertFalse(c.hashCode() == b.hashCode()); + assertFalse(c.equals(a)); + assertFalse(c.hashCode() == a.hashCode()); + + a.setProperty("p2", "2"); + Properties d = new Properties(); + d.setProperty("p2", "2"); + d.setProperty("p1", "1"); + assertTrue(d.equals(a)); + } + + /** + * Test of selectSingle method, of class Properties. + */ + public void testSelectSingle() { + + final boolean[] called = new boolean[1]; + final String v = "2"; + final String n = "p2"; + + PropertyMatcher matcher = new PropertyMatcher() { + + @Override + public String getName() { + assertFalse(called[0]); + called[0] = true; + return n; + } + + @Override + public boolean match(String value) { + assertTrue(v.equals(value)); + return true; + } + }; + + Properties instance = new Properties(); + instance.setProperty("p1", "1"); + instance.setProperty(n, v); + instance.setProperty("p3", "3"); + Property result = instance.selectSingle(matcher); + assertEquals(result, new Property(n, v)); + + + called[0] = false; + PropertyMatcher matcher2 = new PropertyMatcher() { + + @Override + public String getName() { + assertFalse(called[0]); + called[0] = true; + return n; + } + + @Override + public boolean match(String value) { + return false; + } + }; + + + Property result2 = instance.selectSingle(matcher2); + assertTrue(result2 == null); + } + + /** + * Test of get method, of class Properties. + */ + public void testGet() { + Properties instance = new Properties(); + instance.setProperty("p1", "1"); + assertEquals("1", instance.get("p1")); + assertEquals(null, instance.get("p2")); + } + + /** + * Test of getProperties method, of class Properties. + */ + public void testIterator() { + Properties instance = new Properties(); + instance.setProperty("p1", "1"); + instance.setProperty("p2", "2"); + Iterator<Property> result = instance.iterator(); + assertTrue(result.hasNext()); + assertEquals(new Property("p1", "1"), result.next()); + assertTrue(result.hasNext()); + assertEquals(new Property("p2", "2"), result.next()); + assertFalse(result.hasNext()); + assertTrue(result.next() == null); + + try { + result.remove(); + fail(); + } catch(UnsupportedOperationException e) {} + } + + /** + * Test of add method, of class Properties. + */ + public void testAdd() { + Properties a = new Properties(); + a.setProperty("p1", "1"); + a.setProperty("p2", "2"); + + Properties b = new Properties(); + b.setProperty("p1", "1"); + + Properties c = new Properties(); + c.setProperty("p2", "2"); + + assertFalse(a.equals(b)); + b.add(c); + + assertTrue(a.equals(b)); + + b.setProperty("p3", null); + assertTrue(a.equals(b)); + + Properties empty = new Properties(); + b.add(empty); + assertTrue(a.equals(b)); + + empty.add(b); + assertTrue(a.equals(empty)); + } + + + /** + * Test the multiple argument constructors. + */ + public void testConstructors() { + Properties a = new Properties("p1", "1", "p2", "2", "p3", "3"); + Properties b = new Properties("p1", "1", "p2", "2"); + Properties c = new Properties("p1", "1"); + + assertTrue(a.get("p3").equals("3")); + assertTrue(b.get("p2").equals("2")); + assertTrue(b.get("p1").equals("1")); + + b.setProperty("p3", "3"); + c.setProperty("p2", "2"); + c.setProperty("p3", "3"); + + assertTrue(a.equals(b)); + assertTrue(a.equals(c)); + } + + /** + * Test Entity class + */ + public void testEntity() { + + Properties p = new Properties(); + + Properties.Entity entity = new Properties.Entity(); + assertEquals(entity.getProperties(), p); + + entity.getProperties().setProperty("p1", "1"); + Properties.Entity entity2 = new Properties.Entity(entity); + assertEquals(entity.getProperties(), entity2.getProperties()); + } + + /** + * Test property selector + */ + public void testPropertySelector() { + final Collection<Properties.Entity> c = new ArrayList<>(); + + final Properties.Entity e1 = new Properties.Entity(); + e1.getProperties().setProperty("p1", "1"); + e1.getProperties().setProperty("p2", "2"); + c.add(e1); + + final Properties.Entity e2 = new Properties.Entity(); + e2.getProperties().setProperty("p2", "2"); + e2.getProperties().setProperty("p1", "1"); + e2.getProperties().setProperty("p3", "3"); + c.add(e2); + + final Properties.Entity e3 = new Properties.Entity(); + e3.getProperties().setProperty("p3", "3"); + e3.getProperties().setProperty("p4", "4"); + c.add(e3); + + final PropertySelector<Properties.Entity> sel = new PropertySelector<>(c); + + final StringPropertyMatcher matcher1 = new StringPropertyMatcher("p2", "2"); + assertTrue(sel.selectMultiple(matcher1).size() == 2); + assertTrue(sel.selectMultiple(matcher1).contains(e1)); + assertTrue(sel.selectMultiple(matcher1).contains(e2)); + assertTrue(sel.selectSingle(matcher1).equals(e1) || sel.selectSingle(matcher1).equals(e2)); + + final StringPropertyMatcher matcher2 = new StringPropertyMatcher("p3", "3"); + assertTrue(sel.selectMultiple(matcher2).size() == 2); + assertTrue(sel.selectMultiple(matcher2).contains(e2)); + assertTrue(sel.selectMultiple(matcher2).contains(e3)); + assertTrue(sel.selectSingle(matcher2).equals(e2) || sel.selectSingle(matcher2).equals(e3)); + + final StringPropertyMatcher matcher3 = new StringPropertyMatcher("p4", "4"); + assertTrue(sel.selectMultiple(matcher3).size() == 1); + assertTrue(sel.selectMultiple(matcher3).contains(e3)); + assertTrue(sel.selectSingle(matcher3).equals(e3)); + + final StringPropertyMatcher matcher4 = new StringPropertyMatcher("p5", "5"); + assertTrue(sel.selectMultiple(matcher4).size() == 0); + assertTrue(sel.selectSingle(matcher4) == null); + } + + public void testRemoveProperty() { + final Properties p = new Properties(); + p.setProperty("p1", "1"); + p.setProperty("p2", "2"); + + assertTrue(p.get("p1").equals("1")); + assertTrue(p.get("p2").equals("2")); + + p.setProperty("p1", null); + assertTrue(p.get("p1") == null); + assertTrue(p.get("p2").equals("2")); + + p.setProperty("p2", null); + assertTrue(p.get("p1") == null); + assertTrue(p.get("p2") == null); + + p.setProperty("p3", "3"); + assertTrue(p.get("p1") == null); + assertTrue(p.get("p2") == null); + assertTrue(p.get("p3").equals("3")); + } + + /** + * Test property matchers + */ + public void testPropertyMatchers() { + final StringPropertyMatcher matcher = new StringPropertyMatcher("p1", "1"); + assertTrue(matcher.getName().equals("p1")); + assertTrue(matcher.match("1")); + assertFalse(matcher.match("2")); + try { + matcher.match(null); + fail(); + } catch(IllegalArgumentException e) {} + + try { + new StringPropertyMatcher(null, "**"); + fail(); + } catch(IllegalArgumentException e) {} + + try { + new StringPropertyMatcher("p1", null); + fail(); + } catch(IllegalArgumentException e) {} + + final RegexpPropertyMatcher matcher2 = new RegexpPropertyMatcher("p1", "C.*"); + assertTrue(matcher2.getName().equals("p1")); + assertTrue(matcher2.match("C")); + assertTrue(matcher2.match("Casdf")); + assertFalse(matcher2.match(" C")); + assertFalse(matcher2.match("c")); + assertFalse(matcher2.match("asdfC")); + + try { + matcher2.match(null); + fail(); + } catch(IllegalArgumentException e) {} + + try { + new RegexpPropertyMatcher("p1", "**"); + fail(); + } catch(IllegalArgumentException e) {} + + try { + new RegexpPropertyMatcher(null, "1"); + fail(); + } catch(IllegalArgumentException e) {} + + try { + new RegexpPropertyMatcher("p1", null); + fail(); + } catch(IllegalArgumentException e) {} + + final InvertPropertyMatcher matcher3 = new InvertPropertyMatcher(matcher); + assertTrue(matcher3.getName().equals("p1")); + assertFalse(matcher3.match("1")); + assertTrue(matcher3.match("2")); + assertFalse(matcher3.match(null)); + } + + public void testToString() { + Properties p = new Properties(); + assertEquals(p.toString(), "[]"); + + p.setProperty("p1", "1"); + assertEquals(p.toString(), "[p1=1]"); + + Properties p2 = new Properties(); + p2.setProperty("p1", "1"); + p2.setProperty("p2", "2"); + assertEquals(p2.toString(), "[p1=1, p2=2]"); + + Properties p3 = new Properties(); + p3.setProperty("p2", "2"); + p3.setProperty("p1", "1"); + assertEquals(p3.toString(), "[p1=1, p2=2]"); + + p3.setProperty("p0", "0"); + assertEquals(p3.toString(), "[p0=0, p1=1, p2=2]"); + + p2.setProperty("p1", null); + assertEquals(p2.toString(), "[p2=2]"); + + p2.setProperty("p2", null); + assertEquals(p2.toString(), "[]"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertyTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data; + +import static org.junit.Assert.*; +import org.junit.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class PropertyTest { + + public PropertyTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of getName method, of class Property. + */ + @Test + public void testGetNameAndValue() { + final Property p = new Property("name", "value"); + assertEquals(p.getName(), "name"); + assertEquals(p.getValue(), "value"); + + try { + new Property(null, "value"); + fail(); + } catch(IllegalArgumentException e) { + } + + + try { + new Property("name", null); + fail(); + } catch(IllegalArgumentException e) { + } + } + + /** + * Test of toString method, of class Property. + */ + @Test + public void testToString() { + final Property p = new Property("name", "value"); + assertEquals(p.toString(), "name=value"); + } + + /** + * Test of equals method, of class Property. + */ + @Test + public void testEquals() { + final Property p = new Property("name", "value"); + final Object o = new Object(); + assertFalse(p.equals(o)); + assertFalse(p.equals(null)); + assertTrue(p.equals(p)); + + final Property p2 = new Property("name", "value1"); + assertFalse(p.equals(p2)); + assertTrue(p.hashCode() != p2.hashCode()); + + final Property p3 = new Property("name2", "value"); + assertFalse(p.equals(p3)); + assertTrue(p.hashCode() != p3.hashCode()); + assertTrue(p2.hashCode() != p3.hashCode()); + + final Property p4 = new Property("name", "value"); + assertEquals(p, p4); + assertEquals(p.hashCode(), p4.hashCode()); + + final Property p5 = new Property("value", "name"); + assertFalse(p.equals(p5)); + assertTrue(p.hashCode() != p5.hashCode()); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/SourceTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,79 @@ +/* + * 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.sun.hotspot.igv.data; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import static org.junit.Assert.assertEquals; +import org.junit.*; + +/** + * + * @author Thomas + */ +public class SourceTest { + + public SourceTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of getSourceNodes method, of class Source. + */ + @Test + public void testBase() { + final Source s = new Source(); + + final InputNode N1 = new InputNode(1); + final InputNode N2 = new InputNode(2); + + s.addSourceNode(N1); + assertEquals(s.getSourceNodes(), Arrays.asList(N1)); + assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1))); + + s.addSourceNode(N2); + assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2)); + assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1, 2))); + + s.addSourceNode(N1); + assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2)); + assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1, 2))); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/Util.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data; + +import static org.junit.Assert.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class Util { + + public static void assertGraphDocumentNotEquals(GraphDocument a, GraphDocument b) { + try { + assertGraphDocumentEquals(a, b); + } catch(AssertionError e) { + return; + } + + fail("Graphs documents are equal!"); + } + + public static void assertGraphDocumentEquals(GraphDocument a, GraphDocument b) { + + if (a.getElements().size() != b.getElements().size()) { + fail(); + } + + int z = 0; + for (FolderElement e : b.getElements()) { + + if (e instanceof Group) { + Group g = (Group) e; + Group thisG = (Group) a.getElements().get(z); + assertGroupEquals(thisG, g); + z++; + } + } + } + + public static void assertGroupNotEquals(Group a, Group b) { + try { + assertGroupEquals(a, b); + } catch(AssertionError e) { + return; + } + + fail("Groups are equal!"); + } + + public static void assertGroupEquals(Group a, Group b) { + + if (a.getGraphsCount() != b.getGraphsCount()) { + fail(); + } + + int z = 0; + for (InputGraph graph : a.getGraphs()) { + InputGraph otherGraph = b.getGraphs().get(z); + assertGraphEquals(graph, otherGraph); + z++; + } + + if (a.getMethod() == null || b.getMethod() == null) { + if (a.getMethod() != b.getMethod()) { + fail(); + } + } else { + if (!a.getMethod().equals(b.getMethod())) { + fail(); + } + } + } + + public static void assertGraphNotEquals(InputGraph a, InputGraph b) { + try { + assertGraphEquals(a, b); + } catch(AssertionError e) { + return; + } + + fail("Graphs are equal!"); + } + + public static void assertGraphEquals(InputGraph a, InputGraph b) { + + if(!a.getNodesAsSet().equals(b.getNodesAsSet())) { + fail(); + } + + if (!a.getEdges().equals(b.getEdges())) { + fail(); + } + + if (a.getBlocks().equals(b.getBlocks())) { + fail(); + } + + for (InputNode n : a.getNodes()) { + assertEquals(a.getBlock(n), b.getBlock(n)); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.data.serialization; + +import com.sun.hotspot.igv.data.*; +import java.io.CharArrayWriter; +import java.io.StringReader; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import org.junit.*; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * + * @author Thomas Wuerthinger + */ +public class ParserTest { + + public ParserTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + private void test(GraphDocument document) { + final Printer printer = new Printer(); + final CharArrayWriter writer = new CharArrayWriter(); + printer.export(writer, document); + test(document, writer.toString()); + } + + private void test(GraphDocument document, String xmlString) { + + StringReader sr = new StringReader(xmlString); + InputSource is = new InputSource(sr); + + try { + Parser parser = new Parser(); + final GraphDocument parsedDocument = parser.parse(is, null); + Util.assertGraphDocumentEquals(document, parsedDocument); + } catch (SAXException ex) { + fail(ex.toString()); + } + } + + private void testBoth(GraphDocument document, String xmlString) { + test(document); + test(document, xmlString); + } + + /** + * Test of graph document serialization + */ + @Test + public void testSerialization() { + final GraphDocument doc = new GraphDocument(); + + test(doc); + + final Group group1 = new Group(doc); + doc.addElement(group1); + test(doc); + + final Group group2 = new Group(doc); + doc.addElement(group2); + test(doc); + + final InputGraph graph = new InputGraph(""); + group1.addElement(graph); + test(doc); + + graph.addNode(new InputNode(0)); + test(doc); + + graph.addNode(new InputNode(1)); + test(doc); + + graph.addNode(new InputNode(2)); + test(doc); + + graph.addNode(new InputNode(3)); + test(doc); + + graph.addEdge(new InputEdge((char)0, (char)0, 0, 1)); + test(doc); + + graph.addEdge(new InputEdge((char)1, (char)1, 0, 1)); + test(doc); + + graph.addEdge(new InputEdge((char)0, (char)0, 1, 2)); + test(doc); + + graph.addEdge(new InputEdge((char)0, (char)0, 2, 3)); + test(doc); + + group1.setMethod(new InputMethod(group1, "testMethod", "tM", 1)); + test(doc); + + final InputBlock b1 = graph.addBlock("1"); + b1.addNode(0); + b1.addNode(1); + + final InputBlock b2 = graph.addBlock("2"); + b2.addNode(2); + b2.addNode(3); + test(doc); + + final GraphDocument document2 = new GraphDocument(); + doc.addGraphDocument(document2); + test(doc); + assertTrue(doc.getElements().size() == 2); + + final Group group3 = new Group(document2); + document2.addElement(group3); + doc.addGraphDocument(document2); + assertTrue(doc.getElements().size() == 3); + assertTrue(document2.getElements().size() == 0); + + doc.clear(); + test(doc); + Util.assertGraphDocumentEquals(doc, new GraphDocument()); + } + + @Test + public void testSimpleExport() { + GraphDocument document = new GraphDocument(); + Group g = new Group(document); + document.addElement(g); + + InputGraph graph = new InputGraph("TestGraph"); + g.addElement(graph); + graph.getProperties().setProperty("testName", "testValue"); + + InputNode n1 = new InputNode(0); + InputNode n2 = new InputNode(1); + InputEdge e1 = new InputEdge((char)0, 0, 1); + InputEdge e2 = new InputEdge((char)1, 0, 1); + graph.addNode(n1); + graph.addNode(n2); + graph.addEdge(e1); + graph.addEdge(e2); + + test(document); + } + + @Test + public void testComplexExport() { + + GraphDocument document = new GraphDocument(); + Group g = new Group(document); + document.addElement(g); + + InputGraph graph = new InputGraph("TestGraph"); + g.addElement(graph); + graph.getProperties().setProperty("testName", "testValue"); + + InputNode n1 = new InputNode(0); + InputNode n2 = new InputNode(1); + InputEdge e1 = new InputEdge((char)0, 0, 0); + InputEdge e2 = new InputEdge((char)1, 1, 1); + graph.addNode(n1); + graph.addNode(n2); + graph.addEdge(e1); + graph.addEdge(e2); + + InputGraph graph2 = new InputGraph("TestGraph2"); + g.addElement(graph2); + graph2.addNode(n1); + InputNode n3 = new InputNode(2); + graph2.addNode(n3); + InputEdge e3 = new InputEdge((char)0, 0, 2); + graph2.addEdge(e3); + + test(document); + } + + + /** + * Test of parse method, of class Parser. + */ + @Test + public void testParse() { + testBoth(new GraphDocument(), "<graphDocument></graphDocument>"); + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.difference" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.difference.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.difference +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/difference/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.difference-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=1657ecfe +build.xml.script.CRC32=03909051 +build.xml.stylesheet.CRC32=79c3b980 +# 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=1657ecfe +nbproject/build-impl.xml.script.CRC32=2208e770 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.difference</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.sun.hotspot.igv.difference</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/src/com/sun/hotspot/igv/difference/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Difference
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1998, 2008, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.difference; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.*; +import com.sun.hotspot.igv.data.services.Scheduler; +import java.util.*; +import org.openide.util.Lookup; + +/** + * + * @author Thomas Wuerthinger + */ +public class Difference { + + public static final String PROPERTY_STATE = "state"; + public static final String VALUE_NEW = "new"; + public static final String VALUE_CHANGED = "changed"; + public static final String VALUE_SAME = "same"; + public static final String VALUE_DELETED = "deleted"; + public static final String OLD_PREFIX = "OLD_"; + public static final String MAIN_PROPERTY = "name"; + public static final double LIMIT = 100.0; + public static final String[] IGNORE_PROPERTIES = new String[]{"idx", "debug_idx"}; + + public static InputGraph createDiffGraph(InputGraph a, InputGraph b) { + if (a.getGroup() == b.getGroup()) { + return createDiffSameGroup(a, b); + } else { + return createDiff(a, b); + } + } + + private static InputGraph createDiffSameGroup(InputGraph a, InputGraph b) { + Map<Integer, InputNode> keyMapB = new HashMap<>(b.getNodes().size()); + for (InputNode n : b.getNodes()) { + Integer key = n.getId(); + assert !keyMapB.containsKey(key); + keyMapB.put(key, n); + } + + Set<NodePair> pairs = new HashSet<>(); + + for (InputNode n : a.getNodes()) { + Integer key = n.getId(); + + + if (keyMapB.containsKey(key)) { + InputNode nB = keyMapB.get(key); + pairs.add(new NodePair(n, nB)); + } + } + + return createDiff(a, b, pairs); + } + + private static void ensureScheduled(InputGraph a) { + if (a.getBlocks().isEmpty()) { + Scheduler s = Lookup.getDefault().lookup(Scheduler.class); + a.clearBlocks(); + s.schedule(a); + a.ensureNodesInBlocks(); + } + } + + private static InputGraph createDiff(InputGraph a, InputGraph b, Set<NodePair> pairs) { + ensureScheduled(a); + ensureScheduled(b); + + Group g = new Group(null); + g.setMethod(a.getGroup().getMethod()); + if (a.getGroup() == b.getGroup()) { + g.getProperties().add(a.getGroup().getProperties()); + } else { + // copy properties that have the same value in both groups + Properties bps = b.getGroup().getProperties(); + for (Property p : a.getGroup().getProperties()) { + String value = p.getValue(); + if (value != null && value.equals(bps.get(p.getName()))) { + g.getProperties().setProperty(p.getName(), value); + } + } + } + g.getProperties().setProperty("name", "Difference"); + InputGraph graph = new InputGraph(a.getName() + ", " + b.getName()); + g.addElement(graph); + + Map<InputBlock, InputBlock> blocksMap = new HashMap<>(); + for (InputBlock blk : a.getBlocks()) { + InputBlock diffblk = graph.addBlock(blk.getName()); + blocksMap.put(blk, diffblk); + } + for (InputBlock blk : b.getBlocks()) { + InputBlock diffblk = graph.getBlock(blk.getName()); + if (diffblk == null) { + diffblk = graph.addBlock(blk.getName()); + } + blocksMap.put(blk, diffblk); + } + + // Difference between block edges + Set<Pair<String, String>> aEdges = new HashSet<>(); + for (InputBlockEdge edge : a.getBlockEdges()) { + aEdges.add(new Pair<>(edge.getFrom().getName(), edge.getTo().getName())); + } + for (InputBlockEdge bEdge : b.getBlockEdges()) { + InputBlock from = bEdge.getFrom(); + InputBlock to = bEdge.getTo(); + Pair<String, String> pair = new Pair<>(from.getName(), to.getName()); + if (aEdges.contains(pair)) { + // same + graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to)); + aEdges.remove(pair); + } else { + // added + InputBlockEdge edge = graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to)); + edge.setState(InputBlockEdge.State.NEW); + } + } + for (Pair<String, String> deleted : aEdges) { + // removed + InputBlock from = graph.getBlock(deleted.getLeft()); + InputBlock to = graph.getBlock(deleted.getRight()); + InputBlockEdge edge = graph.addBlockEdge(from, to); + edge.setState(InputBlockEdge.State.DELETED); + } + + Set<InputNode> nodesA = new HashSet<>(a.getNodes()); + Set<InputNode> nodesB = new HashSet<>(b.getNodes()); + + Map<InputNode, InputNode> inputNodeMap = new HashMap<>(pairs.size()); + for (NodePair p : pairs) { + InputNode n = p.getLeft(); + assert nodesA.contains(n); + InputNode nB = p.getRight(); + assert nodesB.contains(nB); + + nodesA.remove(n); + nodesB.remove(nB); + InputNode n2 = new InputNode(n); + inputNodeMap.put(n, n2); + inputNodeMap.put(nB, n2); + graph.addNode(n2); + InputBlock block = blocksMap.get(a.getBlock(n)); + block.addNode(n2.getId()); + markAsChanged(n2, n, nB); + } + + for (InputNode n : nodesA) { + InputNode n2 = new InputNode(n); + graph.addNode(n2); + InputBlock block = blocksMap.get(a.getBlock(n)); + block.addNode(n2.getId()); + markAsDeleted(n2); + inputNodeMap.put(n, n2); + } + + int curIndex = 0; + for (InputNode n : nodesB) { + InputNode n2 = new InputNode(n); + + // Find new ID for node of b, does not change the id property + while (graph.getNode(curIndex) != null) { + curIndex++; + } + + n2.setId(curIndex); + graph.addNode(n2); + InputBlock block = blocksMap.get(b.getBlock(n)); + block.addNode(n2.getId()); + markAsNew(n2); + inputNodeMap.put(n, n2); + } + + Collection<InputEdge> edgesA = a.getEdges(); + Collection<InputEdge> edgesB = b.getEdges(); + + Set<InputEdge> newEdges = new HashSet<>(); + + for (InputEdge e : edgesA) { + int from = e.getFrom(); + int to = e.getTo(); + InputNode nodeFrom = inputNodeMap.get(a.getNode(from)); + InputNode nodeTo = inputNodeMap.get(a.getNode(to)); + char fromIndex = e.getFromIndex(); + char toIndex = e.getToIndex(); + + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + if (!newEdges.contains(newEdge)) { + markAsDeleted(newEdge); + newEdges.add(newEdge); + graph.addEdge(newEdge); + } + } + + for (InputEdge e : edgesB) { + int from = e.getFrom(); + int to = e.getTo(); + InputNode nodeFrom = inputNodeMap.get(b.getNode(from)); + InputNode nodeTo = inputNodeMap.get(b.getNode(to)); + char fromIndex = e.getFromIndex(); + char toIndex = e.getToIndex(); + + InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); + if (!newEdges.contains(newEdge)) { + markAsNew(newEdge); + newEdges.add(newEdge); + graph.addEdge(newEdge); + } else { + newEdges.remove(newEdge); + graph.removeEdge(newEdge); + markAsSame(newEdge); + newEdges.add(newEdge); + graph.addEdge(newEdge); + } + } + + return graph; + } + + private static class NodePair extends Pair<InputNode, InputNode> { + + + public NodePair(InputNode n1, InputNode n2) { + super(n1, n2); + } + + public double getValue() { + + double result = 0.0; + for (Property p : getLeft().getProperties()) { + double faktor = 1.0; + for (String forbidden : IGNORE_PROPERTIES) { + if (p.getName().equals(forbidden)) { + faktor = 0.1; + break; + } + } + String p2 = getRight().getProperties().get(p.getName()); + result += evaluate(p.getValue(), p2) * faktor; + } + + return result; + } + + private double evaluate(String p, String p2) { + if (p2 == null) { + return 1.0; + } + if (p.equals(p2)) { + return 0.0; + } else { + return (double) (Math.abs(p.length() - p2.length())) / p.length() + 0.5; + } + } + } + + private static InputGraph createDiff(InputGraph a, InputGraph b) { + + Set<InputNode> matched = new HashSet<>(); + + Set<NodePair> pairs = new HashSet<>(); + for (InputNode n : a.getNodes()) { + String s = n.getProperties().get(MAIN_PROPERTY); + if (s == null) { + s = ""; + } + for (InputNode n2 : b.getNodes()) { + String s2 = n2.getProperties().get(MAIN_PROPERTY); + if (s2 == null) { + s2 = ""; + } + + if (s.equals(s2)) { + NodePair p = new NodePair(n, n2); + pairs.add(p); + } + } + } + + Set<NodePair> selectedPairs = new HashSet<>(); + while (pairs.size() > 0) { + + double min = Double.MAX_VALUE; + NodePair minPair = null; + for (NodePair p : pairs) { + double cur = p.getValue(); + if (cur < min) { + minPair = p; + min = cur; + } + } + + if (min > LIMIT) { + break; + } else { + selectedPairs.add(minPair); + + Set<NodePair> toRemove = new HashSet<>(); + for (NodePair p : pairs) { + if (p.getLeft() == minPair.getLeft() || p.getRight() == minPair.getRight()) { + toRemove.add(p); + } + } + pairs.removeAll(toRemove); + } + } + + return createDiff(a, b, selectedPairs); + } + + private static void markAsNew(InputEdge e) { + e.setState(InputEdge.State.NEW); + } + + private static void markAsDeleted(InputEdge e) { + e.setState(InputEdge.State.DELETED); + + } + + private static void markAsSame(InputEdge e) { + e.setState(InputEdge.State.SAME); + } + + private static void markAsChanged(InputNode n, InputNode firstNode, InputNode otherNode) { + + boolean difference = false; + for (Property p : otherNode.getProperties()) { + String s = firstNode.getProperties().get(p.getName()); + if (!p.getValue().equals(s)) { + difference = true; + n.getProperties().setProperty(OLD_PREFIX + p.getName(), p.getValue()); + } + } + + for (Property p : firstNode.getProperties()) { + String s = otherNode.getProperties().get(p.getName()); + if (s == null && p.getValue().length() > 0) { + difference = true; + n.getProperties().setProperty(OLD_PREFIX + p.getName(), ""); + } + } + + if (difference) { + n.getProperties().setProperty(PROPERTY_STATE, VALUE_CHANGED); + } else { + n.getProperties().setProperty(PROPERTY_STATE, VALUE_SAME); + } + } + + private static void markAsDeleted(InputNode n) { + n.getProperties().setProperty(PROPERTY_STATE, VALUE_DELETED); + } + + private static void markAsNew(InputNode n) { + n.getProperties().setProperty(PROPERTY_STATE, VALUE_NEW); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="org.eclipse.draw2d" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project org.eclipse.draw2d.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: org.eclipse.draw2d +OpenIDE-Module-Localizing-Bundle: org/eclipse/draw2d/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="org.eclipse.draw2d-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=36988202 +build.xml.script.CRC32=0429cbcb +build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 +# 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=36988202 +nbproject/build-impl.xml.script.CRC32=92856d71 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,204 @@ +cluster.path=\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + com.jcraft.jsch,\ + com.jcraft.jzlib,\ + org.apache.commons.codec,\ + org.apache.commons.httpclient,\ + org.apache.commons.io,\ + org.apache.commons.lang,\ + org.apache.commons.logging,\ + org.apache.ws.commons.util,\ + org.apache.xml.resolver,\ + org.apache.xmlrpc,\ + org.eclipse.core.contenttype,\ + org.eclipse.core.jobs,\ + org.eclipse.core.net,\ + org.eclipse.core.runtime,\ + org.eclipse.core.runtime.compatibility.auth,\ + org.eclipse.equinox.app,\ + org.eclipse.equinox.common,\ + org.eclipse.equinox.preferences,\ + org.eclipse.equinox.registry,\ + org.eclipse.equinox.security,\ + org.eclipse.jgit,\ + org.eclipse.mylyn.bugzilla.core,\ + org.eclipse.mylyn.commons.core,\ + org.eclipse.mylyn.commons.net,\ + org.eclipse.mylyn.commons.xmlrpc,\ + org.eclipse.mylyn.tasks.core,\ + org.mozilla.rhino.patched,\ + org.netbeans.api.debugger,\ + org.netbeans.api.java.classpath,\ + org.netbeans.api.xml,\ + org.netbeans.core.browser,\ + org.netbeans.core.execution,\ + org.netbeans.core.ide,\ + org.netbeans.core.io.ui,\ + org.netbeans.core.multiview,\ + org.netbeans.core.nativeaccess,\ + org.netbeans.core.osgi,\ + org.netbeans.lib.cvsclient,\ + org.netbeans.lib.terminalemulator,\ + org.netbeans.libs.antlr3.runtime,\ + org.netbeans.libs.bytelist,\ + org.netbeans.libs.commons_net,\ + org.netbeans.libs.freemarker,\ + org.netbeans.libs.git,\ + org.netbeans.libs.ini4j,\ + org.netbeans.libs.jaxb,\ + org.netbeans.libs.jsr223,\ + org.netbeans.libs.junit4,\ + org.netbeans.libs.jvyamlb,\ + org.netbeans.libs.lucene,\ + org.netbeans.libs.smack,\ + org.netbeans.libs.svnClientAdapter,\ + org.netbeans.libs.svnClientAdapter.javahl,\ + org.netbeans.libs.svnClientAdapter.svnkit,\ + org.netbeans.libs.swingx,\ + org.netbeans.libs.xerces,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.bugtracking,\ + org.netbeans.modules.bugtracking.bridge,\ + org.netbeans.modules.bugzilla,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.csl.api,\ + org.netbeans.modules.css.editor,\ + org.netbeans.modules.css.lib,\ + org.netbeans.modules.css.visual,\ + org.netbeans.modules.db,\ + org.netbeans.modules.db.core,\ + org.netbeans.modules.db.dataview,\ + org.netbeans.modules.db.drivers,\ + org.netbeans.modules.db.kit,\ + org.netbeans.modules.db.metadata.model,\ + org.netbeans.modules.db.mysql,\ + org.netbeans.modules.db.sql.editor,\ + org.netbeans.modules.db.sql.visualeditor,\ + org.netbeans.modules.dbapi,\ + org.netbeans.modules.defaults,\ + org.netbeans.modules.derby,\ + org.netbeans.modules.dlight.nativeexecution,\ + org.netbeans.modules.dlight.terminal,\ + org.netbeans.modules.editor.bookmarks,\ + org.netbeans.modules.editor.bracesmatching,\ + org.netbeans.modules.editor.codetemplates,\ + org.netbeans.modules.editor.completion,\ + org.netbeans.modules.editor.guards,\ + org.netbeans.modules.editor.indent.project,\ + org.netbeans.modules.editor.kit,\ + org.netbeans.modules.editor.macros,\ + org.netbeans.modules.editor.structure,\ + org.netbeans.modules.extbrowser,\ + org.netbeans.modules.extexecution,\ + org.netbeans.modules.extexecution.destroy,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.git,\ + org.netbeans.modules.glassfish.common,\ + org.netbeans.modules.gototest,\ + org.netbeans.modules.gsf.codecoverage,\ + org.netbeans.modules.gsf.testrunner,\ + org.netbeans.modules.html,\ + org.netbeans.modules.html.editor,\ + org.netbeans.modules.html.editor.lib,\ + org.netbeans.modules.html.lexer,\ + org.netbeans.modules.html.parser,\ + org.netbeans.modules.html.validation,\ + org.netbeans.modules.httpserver,\ + org.netbeans.modules.hudson,\ + org.netbeans.modules.hudson.git,\ + org.netbeans.modules.hudson.mercurial,\ + org.netbeans.modules.hudson.subversion,\ + org.netbeans.modules.hudson.tasklist,\ + org.netbeans.modules.ide.kit,\ + org.netbeans.modules.image,\ + org.netbeans.modules.javascript.editing,\ + org.netbeans.modules.javascript.hints,\ + org.netbeans.modules.javascript.kit,\ + org.netbeans.modules.javascript.refactoring,\ + org.netbeans.modules.jellytools.ide,\ + org.netbeans.modules.jumpto,\ + org.netbeans.modules.keyring.impl,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.languages.diff,\ + org.netbeans.modules.languages.manifest,\ + org.netbeans.modules.languages.yaml,\ + org.netbeans.modules.lexer.nbbridge,\ + org.netbeans.modules.localhistory,\ + org.netbeans.modules.mercurial,\ + org.netbeans.modules.netbinox,\ + org.netbeans.modules.parsing.api,\ + org.netbeans.modules.parsing.lucene,\ + org.netbeans.modules.print.editor,\ + org.netbeans.modules.project.ant,\ + org.netbeans.modules.project.libraries,\ + org.netbeans.modules.projectui,\ + org.netbeans.modules.projectui.buildmenu,\ + org.netbeans.modules.projectuiapi,\ + org.netbeans.modules.properties,\ + org.netbeans.modules.properties.syntax,\ + org.netbeans.modules.refactoring.api,\ + org.netbeans.modules.schema2beans,\ + org.netbeans.modules.server,\ + org.netbeans.modules.servletapi,\ + org.netbeans.modules.spellchecker,\ + org.netbeans.modules.spellchecker.apimodule,\ + org.netbeans.modules.spellchecker.bindings.htmlxml,\ + org.netbeans.modules.spellchecker.bindings.properties,\ + org.netbeans.modules.spellchecker.dictionary_en,\ + org.netbeans.modules.spellchecker.kit,\ + org.netbeans.modules.spi.actions,\ + org.netbeans.modules.subversion,\ + org.netbeans.modules.swing.validation,\ + org.netbeans.modules.target.iterator,\ + org.netbeans.modules.tasklist.kit,\ + org.netbeans.modules.tasklist.projectint,\ + org.netbeans.modules.tasklist.todo,\ + org.netbeans.modules.tasklist.ui,\ + org.netbeans.modules.terminal,\ + org.netbeans.modules.usersguide,\ + org.netbeans.modules.utilities,\ + org.netbeans.modules.utilities.project,\ + org.netbeans.modules.versioning,\ + org.netbeans.modules.versioning.indexingbridge,\ + org.netbeans.modules.versioning.system.cvss.installer,\ + org.netbeans.modules.versioning.util,\ + org.netbeans.modules.web.client.tools.api,\ + org.netbeans.modules.web.common,\ + org.netbeans.modules.web.indent,\ + org.netbeans.modules.xml,\ + org.netbeans.modules.xml.axi,\ + org.netbeans.modules.xml.catalog,\ + org.netbeans.modules.xml.core,\ + org.netbeans.modules.xml.jaxb.api,\ + org.netbeans.modules.xml.lexer,\ + org.netbeans.modules.xml.multiview,\ + org.netbeans.modules.xml.retriever,\ + org.netbeans.modules.xml.schema.completion,\ + org.netbeans.modules.xml.schema.model,\ + org.netbeans.modules.xml.tax,\ + org.netbeans.modules.xml.text,\ + org.netbeans.modules.xml.tools,\ + org.netbeans.modules.xml.wsdl.model,\ + org.netbeans.modules.xml.xam,\ + org.netbeans.modules.xml.xdm,\ + org.netbeans.modules.xsl,\ + org.netbeans.spi.debugger.ui,\ + org.netbeans.spi.editor.hints,\ + org.netbeans.spi.navigator,\ + org.netbeans.spi.palette,\ + org.netbeans.spi.tasklist,\ + org.netbeans.spi.viewmodel,\ + org.netbeans.swing.dirchooser,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.options,\ + org.openide.util.enumerations +## Not disabled because of NetBeans bug 206347: +## Applications not using OSGi don't start on NbP 7.1 +# org.netbeans.core.netigso,\ +# org.netbeans.libs.felix,\ +# org.netbeans.libs.osgi,\ +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +is.autoload=true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>org.eclipse.draw2d</code-name-base> + <suite-component/> + <module-dependencies/> + <public-packages> + <package>org.eclipse.draw2d</package> + <package>org.eclipse.draw2d.geometry</package> + <package>org.eclipse.draw2d.graph</package> + <package>org.eclipse.draw2d.internal</package> + <package>org.eclipse.draw2d.internal.graph</package> + <package>org.eclipse.draw2d.parts</package> + <package>org.eclipse.draw2d.text</package> + <package>org.eclipse.draw2d.widgets</package> + </public-packages> + <class-path-extension> + <runtime-relative-path>ext/org.eclipse.draw2d_3.1.0.jar</runtime-relative-path> + <binary-origin>release/modules/ext/org.eclipse.draw2d_3.1.0.jar</binary-origin> + </class-path-extension> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Draw2DLibrary/src/org/eclipse/draw2d/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Draw2DLibrary
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.oracle.graal.visualizer.editor" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.oracle.graal.visualizer.editor.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.oracle.graal.visualizer.editor +OpenIDE-Module-Layer: com/oracle/graal/visualizer/editor/layer.xml +OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/editor/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.oracle.graal.visualizer.editor-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=5dcda8e3 +build.xml.script.CRC32=98c4f3b3 +build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 +# 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=5dcda8e3 +nbproject/build-impl.xml.script.CRC32=6243c7e2 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.oracle.graal.visualizer.editor</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.difference</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.filter</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.graph</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.settings</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.spi.quicksearch</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.12.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.actions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.24.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.39.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.dialogs</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.23.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.filesystems</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.53.2</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.loaders</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.32.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.19.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.11.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.48.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.oracle.graal.visualizer.editor</package> + <package>com.oracle.graal.visualizer.editor.actions</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/META-INF/services/com.sun.hotspot.igv.data.services.GraphViewer Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +com.oracle.graal.visualizer.editor.GraphViewerImplementation
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,3 @@ +OpenIDE-Module-Name=Editor +CTL_EditorTopComponent=Compilation +HINT_EditorTopComponent=Shows the snapshots of a single compilation. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2008, 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.editor; + +import com.sun.hotspot.igv.graph.Figure; +import java.awt.Component; +import java.awt.Graphics2D; +import java.util.Collection; +import org.openide.awt.UndoRedo; +import org.openide.util.Lookup; + +/** + * + * @author Thomas Wuerthinger + */ +public interface CompilationViewer { + + public Lookup getLookup(); + + public Component getComponent(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewerFactory.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,31 @@ +/* + * 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.editor; + +import com.sun.hotspot.igv.data.InputGraph; + +public interface CompilationViewerFactory { + CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph); + String getName(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/DiagramViewModel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,289 @@ +/* + * Copyright (c) 1998, 2008, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.editor; + +import com.sun.hotspot.igv.data.*; +import com.sun.hotspot.igv.difference.Difference; +import com.sun.hotspot.igv.filter.CustomFilter; +import com.sun.hotspot.igv.filter.FilterChain; +import com.sun.hotspot.igv.graph.Diagram; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.settings.Settings; +import java.util.*; + +public class DiagramViewModel { + + private Set<Integer> hiddenNodes; + private Set<Integer> onScreenNodes; + private Set<Integer> selectedNodes; + private FilterChain filterChain; + private FilterChain sequenceFilterChain; + private Diagram diagram; + private InputGraph inputGraph; + private ChangedEvent<DiagramViewModel> diagramChangedEvent; + private ChangedEvent<DiagramViewModel> viewChangedEvent; + private ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent; + private ChangedEvent<DiagramViewModel> viewPropertiesChangedEvent; + private boolean showNodeHull; + private final InputGraph secondGraph; + private final InputGraph firstGraph; + private ChangedListener<FilterChain> filterChainChangedListener = new ChangedListener<FilterChain>() { + + @Override + public void changed(FilterChain source) { + diagramChanged(); + } + }; + + public boolean getShowNodeHull() { + return showNodeHull; + } + + public void setShowNodeHull(boolean b) { + showNodeHull = b; + viewPropertiesChangedEvent.fire(); + } + + public DiagramViewModel(InputGraph firstGraph, InputGraph secondGraph, Group g, FilterChain filterChain, FilterChain sequenceFilterChain) { + + this.firstGraph = firstGraph; + this.secondGraph = secondGraph; + this.showNodeHull = true; + assert filterChain != null; + this.filterChain = filterChain; + assert sequenceFilterChain != null; + this.sequenceFilterChain = sequenceFilterChain; + hiddenNodes = new HashSet<>(); + onScreenNodes = new HashSet<>(); + selectedNodes = new HashSet<>(); + diagramChangedEvent = new ChangedEvent<>(this); + viewChangedEvent = new ChangedEvent<>(this); + hiddenNodesChangedEvent = new ChangedEvent<>(this); + viewPropertiesChangedEvent = new ChangedEvent<>(this); + + filterChain.getChangedEvent().addListener(filterChainChangedListener); + sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener); + } + + public ChangedEvent<DiagramViewModel> getDiagramChangedEvent() { + return diagramChangedEvent; + } + + public ChangedEvent<DiagramViewModel> getViewChangedEvent() { + return viewChangedEvent; + } + + public ChangedEvent<DiagramViewModel> getHiddenNodesChangedEvent() { + return hiddenNodesChangedEvent; + } + + public ChangedEvent<DiagramViewModel> getViewPropertiesChangedEvent() { + return viewPropertiesChangedEvent; + } + + public Set<Integer> getSelectedNodes() { + return selectedNodes; + } + + public Set<Integer> getHiddenNodes() { + return hiddenNodes; + } + + public Set<Integer> getOnScreenNodes() { + return onScreenNodes; + } + + public void setSelectedNodes(Set<Integer> nodes) { + this.selectedNodes = nodes; + /* List<Color> colors = new ArrayList<>(); + for (int i = 0; i < group.getGraphs().size(); ++i) { + colors.add(Color.black); + } + if (nodes.size() >= 1) { + for (Integer id : nodes) { + if (id < 0) { + id = -id; + } + InputNode last = null; + int index = 0; + for (InputGraph g : group.getGraphs()) { + Color curColor = colors.get(index); + InputNode cur = g.getNode(id); + if (cur != null) { + if (last == null) { + curColor = Color.green; + } else { + if (last.equals(cur)) { + if (curColor == Color.black) { + curColor = Color.white; + } + } else { + if (curColor != Color.green) { + curColor = Color.orange; + } + } + } + } + last = cur; + colors.set(index, curColor); + index++; + } + } + } + compilationViewModel.setColors(colors);*/ + // TODO: Add colorization. + viewChangedEvent.fire(); + } + + public void showNot(final Set<Integer> nodes) { + System.out.println("Shownot called with " + nodes); + setHiddenNodes(nodes); + } + + public void showFigures(Collection<Figure> f) { + HashSet<Integer> newHiddenNodes = new HashSet<>(getHiddenNodes()); + for (Figure fig : f) { + newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet()); + } + setHiddenNodes(newHiddenNodes); + } + + public Set<Figure> getSelectedFigures() { + Set<Figure> result = new HashSet<>(); + for (Figure f : diagram.getFigures()) { + for (InputNode node : f.getSource().getSourceNodes()) { + if (getSelectedNodes().contains(node.getId())) { + result.add(f); + } + } + } + return result; + } + + public void showAll(final Collection<Figure> f) { + showFigures(f); + } + + public void showOnly(final Set<Integer> nodes) { + final HashSet<Integer> allNodes = new HashSet<>(getGraphToView().getGroup().getAllNodes()); + allNodes.removeAll(nodes); + setHiddenNodes(allNodes); + } + + public void setHiddenNodes(Set<Integer> nodes) { + this.hiddenNodes = nodes; + hiddenNodesChangedEvent.fire(); + } + + public void setOnScreenNodes(Set<Integer> onScreenNodes) { + this.onScreenNodes = onScreenNodes; + viewChangedEvent.fire(); + } + + public FilterChain getSequenceFilterChain() { + return filterChain; + } + + public void setSequenceFilterChain(FilterChain chain) { + assert chain != null : "sequenceFilterChain must never be null"; + sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener); + sequenceFilterChain = chain; + sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener); + diagramChanged(); + } + + private void diagramChanged() { + // clear diagram + diagram = null; + getDiagramChangedEvent().fire(); + + } + + public FilterChain getFilterChain() { + return filterChain; + } + + public void setFilterChain(FilterChain chain) { + assert chain != null : "filterChain must never be null"; + filterChain.getChangedEvent().removeListener(filterChainChangedListener); + filterChain = chain; + filterChain.getChangedEvent().addListener(filterChainChangedListener); + diagramChanged(); + } + + private static List<String> calculateStringList(Group g) { + List<String> result = new ArrayList<>(); + for (InputGraph graph : g.getGraphs()) { + result.add(graph.getName()); + } + return result; + } + + public InputGraph getFirstGraph() { + return firstGraph; + } + + public InputGraph getSecondGraph() { + return secondGraph; + } + + public Diagram getDiagramToView() { + + if (diagram == null) { + diagram = Diagram.createDiagram(getGraphToView(), Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT)); + getFilterChain().apply(diagram, getSequenceFilterChain()); + if (getFirstGraph() != getSecondGraph()) { + CustomFilter f = new CustomFilter( + "difference", "colorize('state', 'same', white);" + + "colorize('state', 'changed', orange);" + + "colorize('state', 'new', green);" + + "colorize('state', 'deleted', red);"); + f.apply(diagram); + } + } + + return diagram; + } + + public InputGraph getGraphToView() { + if (inputGraph == null) { + if (getFirstGraph() != getSecondGraph()) { + inputGraph = Difference.createDiffGraph(getFirstGraph(), getSecondGraph()); + } else { + inputGraph = getFirstGraph(); + } + } + + return inputGraph; + } + + void setSelectedFigures(List<Figure> list) { + Set<Integer> newSelectedNodes = new HashSet<>(); + for (Figure f : list) { + newSelectedNodes.addAll(f.getSource().getSourceNodesAsSet()); + } + this.setSelectedNodes(newSelectedNodes); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.form Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <NonVisualComponents> + <Component class="javax.swing.JCheckBox" name="jCheckBox1"> + <Properties> + <Property name="text" type="java.lang.String" value="jCheckBox1"/> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo"> + <EmptyBorder bottom="0" left="0" right="0" top="0"/> + </Border> + </Property> + <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor"> + <Insets value="[0, 0, 0, 0]"/> + </Property> + </Properties> + </Component> + </NonVisualComponents> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> +</Form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,291 @@ +/* + * 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.editor; + +import com.oracle.graal.visualizer.util.LookupUtils; +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.data.Group; +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.util.RangeSliderModel; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.*; +import java.util.prefs.Preferences; +import javax.swing.*; +import org.openide.awt.Toolbar; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; +import org.openide.util.NbPreferences; +import org.openide.util.Utilities; +import org.openide.util.actions.Presenter; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; +import org.openide.windows.Mode; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; + +public final class EditorTopComponent extends TopComponent { + + private InstanceContent content; + private static final String PREFERRED_ID = "EditorTopComponent"; + private RangeSliderModel rangeSliderModel; + private CompilationViewer activeViewer; + private CompilationViewerFactory activeFactory; + private Group group; + private final JToolBar viewerToolBar; + private final JPanel viewerPanel; + private final CardLayout viewerPanelCardLayout; + private final Map<String, CompilationViewer> createdComponents = new HashMap<>(); + private final Lookup proxyLookup; + private Lookup currentLookup = Lookups.fixed(); + private final Lookup.Provider currentViewLookupProvider = new Lookup.Provider() { + + @Override + public Lookup getLookup() { + return currentLookup; + } + }; + private static final String PREFERENCE_FACTORY = "factory"; + + public static Preferences getPreferences() { + return NbPreferences.forModule(EditorTopComponent.class); + } + + private InputGraph getFirstGraph() { + return group.getGraphs().get(getModel().getFirstPosition()); + } + + private InputGraph getSecondGraph() { + return group.getGraphs().get(getModel().getSecondPosition()); + } + + private void updateDisplayName() { + int first = getModel().getFirstPosition(); + int second = getModel().getSecondPosition(); + if (first == second) { + setDisplayName(getModel().getPositions().get(first)); + } else { + setDisplayName(String.format("%s: %s - %s", activeFactory.getName(), getModel().getPositions().get(first), getModel().getPositions().get(second))); + } + } + + private void activateFactory(CompilationViewerFactory factory) { + this.activeFactory = factory; + getPreferences().put(PREFERENCE_FACTORY, activeFactory.getName()); + updateView(); + } + + public EditorTopComponent(InputGraph graph) { + setName(NbBundle.getMessage(EditorTopComponent.class, "CTL_EditorTopComponent")); + setToolTipText(NbBundle.getMessage(EditorTopComponent.class, "HINT_EditorTopComponent")); + + initComponents(); + + Toolbar toolBar = new Toolbar(); + this.add(BorderLayout.NORTH, toolBar); + + this.group = graph.getGroup(); + rangeSliderModel = new RangeSliderModel(calculateStringList(group)); + content = new InstanceContent(); + content.add(rangeSliderModel); + int graphPos = group.getGraphs().indexOf(graph); + rangeSliderModel.setPositions(graphPos, graphPos); + + Collection<? extends CompilationViewerFactory> factories = Lookup.getDefault().lookupAll(CompilationViewerFactory.class); + proxyLookup = Lookups.proxy(currentViewLookupProvider); + this.associateLookup(new ProxyLookup(new Lookup[]{proxyLookup, new AbstractLookup(content)})); + + rangeSliderModel.getChangedEvent().addListener(rangeSliderListener); + + ButtonGroup factoryButtonGroup = new ButtonGroup(); + for (CompilationViewerFactory factory : factories) { + AbstractButton button = createFactoryChangeButton(factory); + factoryButtonGroup.add(button); + toolBar.add(button); + } + toolBar.addSeparator(); + + viewerToolBar = new JToolBar(); + viewerToolBar.setFloatable(false); + toolBar.add(viewerToolBar); + toolBar.add(Box.createHorizontalGlue()); + + Action action = Utilities.actionsForPath("QuickSearchShadow").get(0); + Component quicksearch = ((Presenter.Toolbar) action).getToolbarPresenter(); + quicksearch.setMinimumSize(quicksearch.getPreferredSize()); // necessary for GTK LAF + toolBar.add(quicksearch); + + viewerPanel = new JPanel(); + viewerPanelCardLayout = new CardLayout(); + viewerPanel.setLayout(viewerPanelCardLayout); + this.add(viewerPanel, BorderLayout.CENTER); + + if (factories.size() > 0) { + String activeFactoryName = getPreferences().get(PREFERENCE_FACTORY, factories.iterator().next().getName()); + Enumeration<AbstractButton> buttons = factoryButtonGroup.getElements(); + for (CompilationViewerFactory factory : factories) { + JToggleButton curButton = (JToggleButton) buttons.nextElement(); + if (factory.getName().equals(activeFactoryName)) { + activeFactory = factory; + curButton.setSelected(true); + } + } + } + updateView(); + } + + private static List<String> calculateStringList(Group g) { + List<String> result = new ArrayList<>(); + for (InputGraph graph : g.getGraphs()) { + result.add(graph.getName()); + } + return result; + } + + private RangeSliderModel getModel() { + return rangeSliderModel; + } + + public static EditorTopComponent getActive() { + Set<? extends Mode> modes = WindowManager.getDefault().getModes(); + for (Mode m : modes) { + TopComponent tc = m.getSelectedTopComponent(); + if (tc instanceof EditorTopComponent) { + return (EditorTopComponent) tc; + } + } + return null; + } + + /** + * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jCheckBox1 = new javax.swing.JCheckBox(); + + org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, "jCheckBox1"); + jCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); + jCheckBox1.setMargin(new java.awt.Insets(0, 0, 0, 0)); + + setLayout(new java.awt.BorderLayout()); + }// </editor-fold>//GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox jCheckBox1; + // End of variables declaration//GEN-END:variables + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER; + } + + @Override + public void componentOpened() { + } + + @Override + public void componentClosed() { + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + private ChangedListener<RangeSliderModel> rangeSliderListener = new ChangedListener<RangeSliderModel>() { + + @Override + public void changed(RangeSliderModel source) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + updateView(); + } + }); + } + }; + + private void updateView() { + updateDisplayName(); + String id = getViewStringIdentifier(); + if (!createdComponents.containsKey(id)) { + CompilationViewer newViewer = createViewer(activeFactory); + createdComponents.put(id, newViewer); + viewerPanel.add(newViewer.getComponent(), id); + } + + CompilationViewer newViewer = createdComponents.get(id); + if (newViewer != activeViewer) { + activeViewer = newViewer; + viewerPanelCardLayout.show(viewerPanel, id); + + currentLookup = new ProxyLookup(activeViewer.getLookup(), Lookups.fixed(getFirstGraph(), getSecondGraph())); + initializeToolBar(activeFactory.getName()); + + // Make sure that lookup is updated. + proxyLookup.lookup(Object.class); + } + } + + private String getViewStringIdentifier() { + return String.format("%s/%d/%d", activeFactory.getName(), getModel().getFirstPosition(), getModel().getSecondPosition()); + } + + private AbstractButton createFactoryChangeButton(final CompilationViewerFactory factory) { + JToggleButton toggleButton = new JToggleButton(factory.getName()); + toggleButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + activateFactory(factory); + } + }); + return toggleButton; + } + + private CompilationViewer createViewer(CompilationViewerFactory activeFactory) { + InputGraph firstSnapshot = getFirstGraph(); + InputGraph secondSnapshot = getSecondGraph(); + return activeFactory.createViewer(firstSnapshot, secondSnapshot); + } + + private void initializeToolBar(String id) { + viewerToolBar.removeAll(); + for (Action a : LookupUtils.lookupActions(String.format("CompilationViewer/%s/Actions", id), activeViewer.getLookup())) { + if (a instanceof Presenter.Toolbar) { + viewerToolBar.add(((Presenter.Toolbar) a).getToolbarPresenter()); + } else { + viewerToolBar.add(a); + } + } + viewerToolBar.updateUI(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/GraphViewerImplementation.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008, 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.editor; + +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.data.services.GraphViewer; + +/** + * + * @author Thomas Wuerthinger + */ +public class GraphViewerImplementation implements GraphViewer { + + @Override + public void view(InputGraph graph) { + EditorTopComponent tc = new EditorTopComponent(graph); + tc.open(); + tc.requestActive(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/NodeQuickSearch.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2008, 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.editor; + +import com.sun.hotspot.igv.data.InputNode; +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher; +import com.sun.hotspot.igv.data.services.InputGraphProvider; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import org.netbeans.spi.quicksearch.SearchProvider; +import org.netbeans.spi.quicksearch.SearchRequest; +import org.netbeans.spi.quicksearch.SearchResponse; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.NotifyDescriptor.Message; + +/** + * + * @author Thomas Wuerthinger + */ +public class NodeQuickSearch implements SearchProvider { + + private static final String DEFAULT_PROPERTY = "name"; + + /** + * Method is called by infrastructure when search operation was requested. + * Implementors should evaluate given request and fill response object with + * apropriate results + * + * @param request Search request object that contains information what to search for + * @param response Search response object that stores search results. Note that it's important to react to return value of SearchResponse.addResult(...) method and stop computation if false value is returned. + */ + @Override + public void evaluate(SearchRequest request, SearchResponse response) { + String query = request.getText(); + if (query.trim().isEmpty()) { + return; + } + + final String[] parts = query.split("=", 2); + + String name; + String value; + + if (parts.length == 1) { + name = DEFAULT_PROPERTY; + value = ".*" + Pattern.quote(parts[0]) + ".*"; + } else { + name = parts[0]; + value = parts[1]; + } + + if (value.isEmpty()) { + value = ".*"; + } + + final InputGraphProvider p = null;// TODO: FIXME LookupHistory.getLast(InputGraphProvider.class); + if (p != null && p.getGraph() != null) { + List<InputNode> matches = null; + try { + RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(name, value, Pattern.CASE_INSENSITIVE); + Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(p.getGraph().getNodes()); + + matches = selector.selectMultiple(matcher); + } catch (Exception e) { + final String msg = e.getMessage(); + response.addResult(new Runnable() { + @Override + public void run() { + Message desc = new NotifyDescriptor.Message("An exception occurred during the search, " + + "perhaps due to a malformed query string:\n" + msg, + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(desc); + } + }, + "(Error during search)" + ); + } + + if (matches != null) { + final Set<InputNode> set = new HashSet<>(matches); + response.addResult(new Runnable() { + @Override + public void run() { + final EditorTopComponent comp = EditorTopComponent.getActive(); + if (comp != null) { + // TODO: find connection again! + //comp.setSelectedNodes(set); + comp.requestActive(); + } + } + }, + "All " + matches.size() + " matching nodes (" + name + "=" + value + ")" + ); + + // Single matches + for (final InputNode n : matches) { + response.addResult(new Runnable() { + @Override + public void run() { + final EditorTopComponent comp = EditorTopComponent.getActive(); + if (comp != null) { + final Set<InputNode> tmpSet = new HashSet<>(); + tmpSet.add(n); + // TODO: find connection again! + //comp.setSelectedNodes(tmpSet); + comp.requestActive(); + } + } + }, + n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")" + ); + } + } + } else { + System.out.println("no input graph provider!"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,95 @@ +/* + * 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.editor; + +import com.sun.hotspot.igv.graph.Figure; +import java.awt.BorderLayout; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Collection; +import java.util.prefs.Preferences; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import org.openide.util.Lookup; +import org.openide.util.NbPreferences; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; + +class SplitCompilationViewer implements CompilationViewer { + + private JSplitPane splitPane; + private Component firstPanel; + private Component secondPanel; + private Lookup combinedLookup; + private static final String DIVIDER_LOCATION = "dividerLocation"; + private final PropertyChangeListener splitChanged = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent changeEvent) { + String propertyName = changeEvent.getPropertyName(); + if (propertyName.equals(JSplitPane.DIVIDER_LOCATION_PROPERTY)) { + setLastDividerLocation((Integer) changeEvent.getNewValue()); + } + } + }; + + private static void setLastDividerLocation(int pos) { + NbPreferences.forModule(SplitCompilationViewer.class).put(DIVIDER_LOCATION, Integer.toString(pos)); + } + + private static int getLastDividerLocation() { + try { + return Integer.parseInt(NbPreferences.forModule(SplitCompilationViewer.class).get(DIVIDER_LOCATION, "400")); + } catch (NumberFormatException e) { + return 400; + } + } + + public SplitCompilationViewer(CompilationViewer firstViewer, CompilationViewer secondViewer) { + splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + firstPanel = createComponent(firstViewer); + secondPanel = createComponent(secondViewer); + splitPane.add(firstPanel); + splitPane.add(secondPanel); + splitPane.addPropertyChangeListener(splitChanged); + splitPane.setDividerLocation(getLastDividerLocation()); + combinedLookup = new ProxyLookup(firstViewer.getLookup(), secondViewer.getLookup()); + } + + @Override + public Lookup getLookup() { + return combinedLookup; + } + + @Override + public Component getComponent() { + return splitPane; + } + + private Component createComponent(CompilationViewer viewer) { + return viewer.getComponent(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewerFactory.java Wed Feb 08 21:15:00 2012 -0800 @@ -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.editor; + +import com.sun.hotspot.igv.data.InputGraph; + +public abstract class SplitCompilationViewerFactory implements CompilationViewerFactory { + + @Override + public CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph) { + if (firstGraph == secondGraph) { + return createViewer(firstGraph); + } else { + CompilationViewer firstViewer = createViewer(firstGraph); + CompilationViewer secondViewer = createViewer(secondGraph); + return new SplitCompilationViewer(firstViewer, secondViewer); + } + } + + protected abstract CompilationViewer createViewer(InputGraph graph); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Editor/src/com/oracle/graal/visualizer/editor/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <folder name="QuickSearch"> + <folder name="Nodes"> + <attr name="command" stringvalue="n"/> + <attr name="position" intvalue="0"/> + <file name="com-oracle-graal-visualizer-editor-NodeQuickSearch.instance"/> + </folder> + </folder> + + <folder name="QuickSearchShadow"> + <file name="org-netbeans-modules-quicksearch-QuickSearchAction.shadow"> + <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-quicksearch-QuickSearchAction.instance"/> + </file> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.filter" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.filter.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.filter +OpenIDE-Module-Layer: com/sun/hotspot/igv/filter/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filter/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.filter-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=7c032ebf +build.xml.script.CRC32=3b022a25 +build.xml.stylesheet.CRC32=79c3b980 +# 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=7c032ebf +nbproject/build-impl.xml.script.CRC32=26513f91 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.filter</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.graph</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.jdesktop.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.16.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.30.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.dialogs</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.18.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.filesystems</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.46.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.nodes</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.14.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.39.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.sun.hotspot.igv.filter</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.data.ChangedEvent; +import com.sun.hotspot.igv.data.Properties; +import org.openide.cookies.OpenCookie; + +/** + * + * @author Thomas Wuerthinger + */ +public abstract class AbstractFilter implements Filter { + + private ChangedEvent<Filter> changedEvent; + private Properties properties; + + public AbstractFilter() { + changedEvent = new ChangedEvent<Filter>(this); + properties = new Properties(); + } + + @Override + public Properties getProperties() { + return properties; + } + + @Override + public OpenCookie getEditor() { + return null; + } + + @Override + public ChangedEvent<Filter> getChangedEvent() { + return changedEvent; + } + + protected void fireChangedEvent() { + changedEvent.fire(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,11 @@ +OpenIDE-Module-Name=Filter + +jLabel1.text=Name\: +jLabel2.text=Source\: + +nameTextField.text= + +jButton1.text=OK +jButton2.text=Cancel + +title=Edit Filter Dialog
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.graph.Connection.ConnectionStyle; +import com.sun.hotspot.igv.graph.*; +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class ColorFilter extends AbstractFilter { + + private List<ColorRule> colorRules; + private String name; + + public ColorFilter(String name) { + this.name = name; + colorRules = new ArrayList<>(); + } + + @Override + public String getName() { + return name; + } + + @Override + public void apply(Diagram diagram) { + + Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures()); + for (ColorRule rule : colorRules) { + if (rule.getSelector() != null) { + List<Figure> figures = rule.getSelector().selected(diagram); + for (Figure f : figures) { + applyRule(rule, f); + if (rule.getColor() != null) { + f.setColor(rule.getColor()); + } + } + } else { + for (Figure f : diagram.getFigures()) { + applyRule(rule, f); + } + } + } + } + + private void applyRule(ColorRule rule, Figure f) { + if (rule.getColor() != null) { + f.setColor(rule.getColor()); + } + Color color = rule.getLineColor(); + ConnectionStyle style = rule.getLineStyle(); + + for (OutputSlot s : f.getOutputSlots()) { + for (Connection c : s.getConnections()) { + if (color != null) { + c.setColor(color); + } + + if (style != null) { + c.setStyle(style); + } + } + } + } + + public void addRule(ColorRule r) { + colorRules.add(r); + } + + public static class ColorRule { + + private Color color; + private Color lineColor; + private Connection.ConnectionStyle lineStyle; + private Selector selector; + + public ColorRule(Selector selector, Color c) { + this(selector, c, null, null); + } + + public ColorRule(Selector selector, Color c, Color lineColor, Connection.ConnectionStyle lineStyle) { + this.selector = selector; + this.color = c; + this.lineColor = lineColor; + this.lineStyle = lineStyle; + + } + + public ColorRule(Color c) { + this(null, c); + } + + public Color getColor() { + return color; + } + + public Selector getSelector() { + return selector; + } + + public Color getLineColor() { + return lineColor; + } + + public Connection.ConnectionStyle getLineStyle() { + return lineStyle; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Properties.PropertyMatcher; +import com.sun.hotspot.igv.graph.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * + * @author Thomas Wuerthinger + */ +public class CombineFilter extends AbstractFilter { + + private List<CombineRule> rules; + private String name; + + public CombineFilter(String name) { + this.name = name; + rules = new ArrayList<>(); + } + + @Override + public String getName() { + return name; + } + + @Override + public void apply(Diagram diagram) { + + Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures()); + for (CombineRule r : rules) { + + List<Figure> list = selector.selectMultiple(r.getFirstMatcher()); + Set<Figure> figuresToRemove = new HashSet<>(); + for (Figure f : list) { + + List<Figure> successors = new ArrayList<>(f.getSuccessors()); + if (r.isReversed()) { + if (successors.size() == 1) { + Figure succ = successors.get(0); + InputSlot slot = null; + + for (InputSlot s : succ.getInputSlots()) { + for (Connection c : s.getConnections()) { + if (c.getOutputSlot().getFigure() == f) { + slot = s; + } + } + } + + slot.getSource().addSourceNodes(f.getSource()); + if (r.getShortProperty() != null) { + String s = f.getProperties().get(r.getShortProperty()); + if (s != null && s.length() > 0) { + slot.setShortName(s); + slot.setText(s); + slot.setColor(f.getColor()); + } + } else { + assert slot != null; + slot.setText(f.getProperties().get("dump_spec")); + if (f.getProperties().get("short_name") != null) { + slot.setShortName(f.getProperties().get("short_name")); + } else { + String s = f.getProperties().get("dump_spec"); + if (s != null && s.length() <= 5) { + slot.setShortName(s); + } + } + } + + for (InputSlot s : f.getInputSlots()) { + for (Connection c : s.getConnections()) { + Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel()); + newConn.setColor(c.getColor()); + newConn.setStyle(c.getStyle()); + } + } + + figuresToRemove.add(f); + } + } else { + + for (Figure succ : successors) { + if (succ.getPredecessors().size() == 1 && succ.getInputSlots().size() == 1) { + if (succ.getProperties().selectSingle(r.getSecondMatcher()) != null && succ.getOutputSlots().size() == 1) { + + + OutputSlot oldSlot = null; + for (OutputSlot s : f.getOutputSlots()) { + for (Connection c : s.getConnections()) { + if (c.getInputSlot().getFigure() == succ) { + oldSlot = s; + } + } + } + + assert oldSlot != null; + + OutputSlot nextSlot = succ.getOutputSlots().get(0); + int pos = 0; + if (succ.getProperties().get("con") != null) { + pos = Integer.parseInt(succ.getProperties().get("con")); + } + OutputSlot slot = f.createOutputSlot(pos); + slot.getSource().addSourceNodes(succ.getSource()); + if (r.getShortProperty() != null) { + String s = succ.getProperties().get(r.getShortProperty()); + if (s != null && s.length() > 0) { + slot.setShortName(s); + slot.setText(s); + slot.setColor(succ.getColor()); + } + } else { + slot.setText(succ.getProperties().get("dump_spec")); + if (succ.getProperties().get("short_name") != null) { + slot.setShortName(succ.getProperties().get("short_name")); + } else { + String s = succ.getProperties().get("dump_spec"); + if (s != null && s.length() <= 2) { + slot.setShortName(s); + } else { + String tmpName = succ.getProperties().get("name"); + if (tmpName != null && tmpName.length() > 0) { + slot.setShortName(tmpName.substring(0, 1)); + } + } + } + } + for (Connection c : nextSlot.getConnections()) { + Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel()); + newConn.setColor(c.getColor()); + newConn.setStyle(c.getStyle()); + } + + + figuresToRemove.add(succ); + + if (oldSlot.getConnections().size() == 0) { + f.removeSlot(oldSlot); + } + } + } + } + } + } + + diagram.removeAllFigures(figuresToRemove); + } + } + + public void addRule(CombineRule combineRule) { + rules.add(combineRule); + } + + public static class CombineRule { + + private PropertyMatcher first; + private PropertyMatcher second; + private boolean reversed; + private String shortProperty; + + public CombineRule(PropertyMatcher first, PropertyMatcher second) { + this(first, second, false); + + } + + public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed) { + this(first, second, reversed, null); + } + + public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed, String shortProperty) { + this.first = first; + this.second = second; + this.reversed = reversed; + this.shortProperty = shortProperty; + } + + public boolean isReversed() { + return reversed; + } + + public PropertyMatcher getFirstMatcher() { + return first; + } + + public PropertyMatcher getSecondMatcher() { + return second; + } + + public String getShortProperty() { + return shortProperty; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.graph.*; +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class ConnectionFilter extends AbstractFilter { + + private List<ConnectionStyleRule> connectionStyleRules; + private String name; + + public ConnectionFilter(String name) { + this.name = name; + connectionStyleRules = new ArrayList<>(); + } + + @Override + public String getName() { + return name; + } + + @Override + public void apply(Diagram diagram) { + + Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures()); + for (ConnectionStyleRule rule : connectionStyleRules) { + List<Figure> figures = null; + if (rule.getSelector() != null) { + figures = rule.getSelector().selected(diagram); + } else { + figures = diagram.getFigures(); + } + + for (Figure f : figures) { + for (OutputSlot os : f.getOutputSlots()) { + for (Connection c : os.getConnections()) { + if (figures.contains(c.getInputSlot().getFigure())) { + c.setStyle(rule.getLineStyle()); + c.setColor(rule.getLineColor()); + } + } + } + } + } + } + + public void addRule(ConnectionStyleRule r) { + connectionStyleRules.add(r); + } + + public static class ConnectionStyleRule { + + private Color lineColor; + private Connection.ConnectionStyle lineStyle; + private Selector selector; + + public ConnectionStyleRule(Selector selector, Color lineColor, Connection.ConnectionStyle lineStyle) { + this.selector = selector; + this.lineColor = lineColor; + this.lineStyle = lineStyle; + } + + public Selector getSelector() { + return selector; + } + + public Color getLineColor() { + return lineColor; + } + + public Connection.ConnectionStyle getLineStyle() { + return lineStyle; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1998, 2008, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.Diagram; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.script.*; +import org.openide.cookies.OpenCookie; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; + +/** + * + * @author Thomas Wuerthinger + */ +public class CustomFilter extends AbstractFilter { + + public static final String JAVASCRIPT_HELPER_ID = "JavaScriptHelper"; + private String code; + private String name; + + public CustomFilter(String name, String code) { + this.name = name; + this.code = code; + getProperties().setProperty("name", name); + } + + @Override + public String getName() { + return name; + } + + public String getCode() { + return code; + } + + public void setName(String s) { + name = s; + fireChangedEvent(); + } + + public void setCode(String s) { + code = s; + fireChangedEvent(); + } + + @Override + public OpenCookie getEditor() { + return new OpenCookie() { + + @Override + public void open() { + openInEditor(); + } + }; + } + + public boolean openInEditor() { + EditFilterDialog dialog = new EditFilterDialog(CustomFilter.this); + dialog.setVisible(true); + boolean result = dialog.wasAccepted(); + this.getChangedEvent().fire(); + return result; + } + + @Override + public String toString() { + return getName(); + } + + private static String getJsHelperText() { + InputStream is = null; + StringBuilder sb = new StringBuilder("importPackage(Packages.com.sun.hotspot.igv.filter);importPackage(Packages.com.sun.hotspot.igv.graph);importPackage(Packages.com.sun.hotspot.igv.data);importPackage(Packages.com.sun.hotspot.igv.util);importPackage(java.awt);"); + try { + FileObject fo = FileUtil.getConfigRoot().getFileObject(JAVASCRIPT_HELPER_ID); + is = fo.getInputStream(); + BufferedReader r = new BufferedReader(new InputStreamReader(is)); + String s; + while ((s = r.readLine()) != null) { + sb.append(s); + sb.append("\n"); + } + + } catch (IOException ex) { + Logger.getLogger("global").log(Level.SEVERE, null, ex); + } finally { + try { + is.close(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + return sb.toString(); + } + + @Override + public void apply(Diagram d) { + try { + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine e = sem.getEngineByName("ECMAScript"); + e.eval(getJsHelperText()); + Bindings b = e.getContext().getBindings(ScriptContext.ENGINE_SCOPE); + b.put("graph", d); + b.put("IO", System.out); + e.eval(code, b); + } catch (ScriptException ex) { + Exceptions.printStackTrace(ex); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/EdgeColorIndexFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,77 @@ +/* + * 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.*; +import java.awt.Color; +import java.util.List; + +public class EdgeColorIndexFilter extends AbstractFilter { + + public static final String INPUTS = "INPUTS"; + public static final String OUTPUTS = "OUTPUTS"; + private final String applyTo; + private final Color[] colors; + + public EdgeColorIndexFilter(String applyTo, Color... color) { + if (!applyTo.equals(INPUTS) && !applyTo.equals(OUTPUTS)) { + throw new IllegalArgumentException("applyTo"); + } + + this.applyTo = applyTo; + this.colors = color; + } + + @Override + public String getName() { + return "Edge Color Index Filter"; + } + + @Override + public void apply(Diagram d) { + List<Figure> figures = d.getFigures(); + for (Figure f : figures) { + Slot[] slots; + if (applyTo.equals(INPUTS)) { + List<InputSlot> inputSlots = f.getInputSlots(); + slots = inputSlots.toArray(new Slot[inputSlots.size()]); + } else { + List<OutputSlot> outputSlots = f.getOutputSlots(); + slots = outputSlots.toArray(new Slot[outputSlots.size()]); + } + int index = 0; + for (Slot slot : slots) { + if (index < colors.length && colors[index] != null) { + slot.setColor(colors[index]); + for (Connection c : slot.getConnections()) { + + c.setColor(colors[index]); + } + } + index++; + } + + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.form Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JDialogFormInfo"> + <Properties> + <Property name="defaultCloseOperation" type="int" value="2"/> + <Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="resizable" type="boolean" value="false"/> + </Properties> + <SyntheticProperties> + <SyntheticProperty name="formSizePolicy" type="int" value="1"/> + </SyntheticProperties> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="sourceLabel" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="nameLabel" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="25" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane1" pref="695" max="32767" attributes="1"/> + <Component id="nameTextField" alignment="0" pref="695" max="32767" attributes="1"/> + </Group> + </Group> + <Group type="102" alignment="1" attributes="0"> + <Component id="okButton" min="-2" pref="76" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="cancelButton" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="nameLabel" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="nameTextField" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="sourceLabel" min="-2" max="-2" attributes="0"/> + <Component id="jScrollPane1" min="-2" pref="337" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="16" max="32767" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="jScrollPane1"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTextArea" name="sourceTextArea"> + <Properties> + <Property name="columns" type="int" value="20"/> + <Property name="rows" type="int" value="5"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JTextField" name="nameTextField"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/ssw/graphanalyzer/coordinator/Bundle.properties" key="nameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="nameLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="sourceLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="okButton"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonClicked,okButtonClicked"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="cancelButton"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/ssw/graphanalyzer/filter/Bundle.properties" key="jButton2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonClicked"/> + </Events> + </Component> + </SubComponents> +</Form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.filter; + +import org.openide.windows.WindowManager; + +/** + * + * @author Thomas Wuerthinger + */ +public class EditFilterDialog extends javax.swing.JDialog { + + private CustomFilter customFilter; + private boolean accepted; + + /** Creates new form EditFilterDialog */ + public EditFilterDialog(CustomFilter customFilter) { + super(WindowManager.getDefault().getMainWindow(), true); + this.customFilter = customFilter; + initComponents(); + + sourceTextArea.setText(customFilter.getCode()); + nameTextField.setText(customFilter.getName()); + } + + public boolean wasAccepted() { + return accepted; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + sourceTextArea = new javax.swing.JTextArea(); + nameTextField = new javax.swing.JTextField(); + nameLabel = new javax.swing.JLabel(); + sourceLabel = new javax.swing.JLabel(); + okButton = new javax.swing.JButton(); + cancelButton = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "title")); // NOI18N + setResizable(false); + + sourceTextArea.setColumns(20); + sourceTextArea.setRows(5); + jScrollPane1.setViewportView(sourceTextArea); + + nameTextField.setText("null"); + + nameLabel.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jLabel1.text")); // NOI18N + + sourceLabel.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jLabel2.text")); // NOI18N + + okButton.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jButton1.text")); // NOI18N + okButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonClicked(evt); + okButtonClicked(evt); + } + }); + + cancelButton.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jButton2.text")); // NOI18N + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonClicked(evt); + } + }); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(sourceLabel) + .add(nameLabel)) + .add(25, 25, 25) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 695, Short.MAX_VALUE) + .add(nameTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 695, Short.MAX_VALUE))) + .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() + .add(okButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 76, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(cancelButton))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(nameLabel) + .add(nameTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(sourceLabel) + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 337, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 16, Short.MAX_VALUE) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(cancelButton) + .add(okButton)) + .addContainerGap()) + ); + + pack(); + }// </editor-fold>//GEN-END:initComponents + +private void okButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonClicked + this.customFilter.setName(this.nameTextField.getText()); + this.customFilter.setCode(this.sourceTextArea.getText()); + accepted = true; + setVisible(false); +}//GEN-LAST:event_okButtonClicked + +private void cancelButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonClicked + setVisible(false); +}//GEN-LAST:event_cancelButtonClicked + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton cancelButton; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JLabel nameLabel; + private javax.swing.JTextField nameTextField; + private javax.swing.JButton okButton; + private javax.swing.JLabel sourceLabel; + private javax.swing.JTextArea sourceTextArea; + // End of variables declaration//GEN-END:variables + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.data.ChangedEvent; +import com.sun.hotspot.igv.data.ChangedEventProvider; +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.graph.Diagram; +import org.openide.cookies.OpenCookie; + +/** + * + * @author Thomas Wuerthinger + */ +public interface Filter extends Properties.Provider, ChangedEventProvider<Filter> { + + public String getName(); + + public void apply(Diagram d); + + OpenCookie getEditor(); + + @Override + ChangedEvent<Filter> getChangedEvent(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.data.ChangedEvent; +import com.sun.hotspot.igv.data.ChangedEventProvider; +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.graph.Diagram; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class FilterChain implements ChangedEventProvider<FilterChain> { + + private List<Filter> filters; + private transient ChangedEvent<FilterChain> changedEvent; + + private ChangedListener<Filter> changedListener = new ChangedListener<Filter>() { + @Override + public void changed(Filter source) { + changedEvent.fire(); + } + }; + + public FilterChain() { + filters = new ArrayList<>(); + changedEvent = new ChangedEvent<>(this); + } + + public FilterChain(FilterChain f) { + this.filters = new ArrayList<>(f.filters); + changedEvent = new ChangedEvent<>(this); + } + + @Override + public ChangedEvent<FilterChain> getChangedEvent() { + return changedEvent; + } + + public Filter getFilterAt(int index) { + assert index >= 0 && index < filters.size(); + return filters.get(index); + } + + public void apply(Diagram d) { + for (Filter f : filters) { + f.apply(d); + } + } + + public void apply(Diagram d, FilterChain sequence) { + List<Filter> applied = new ArrayList<>(); + for (Filter f : sequence.getFilters()) { + if (filters.contains(f)) { + f.apply(d); + applied.add(f); + } + } + + + for (Filter f : filters) { + if (!applied.contains(f)) { + f.apply(d); + } + } + } + + + public void addFilter(Filter filter) { + assert filter != null; + filters.add(filter); + filter.getChangedEvent().addListener(changedListener); + changedEvent.fire(); + } + + public boolean containsFilter(Filter filter) { + return filters.contains(filter); + } + + public void removeFilter(Filter filter) { + assert filters.contains(filter); + filters.remove(filter); + filter.getChangedEvent().removeListener(changedListener); + changedEvent.fire(); + } + + public void moveFilterUp(Filter filter) { + assert filters.contains(filter); + int index = filters.indexOf(filter); + if (index != 0) { + filters.remove(index); + filters.add(index - 1, filter); + } + changedEvent.fire(); + } + + public void moveFilterDown(Filter filter) { + assert filters.contains(filter); + int index = filters.indexOf(filter); + if (index != filters.size() - 1) { + filters.remove(index); + filters.add(index + 1, filter); + } + changedEvent.fire(); + } + + public List<Filter> getFilters() { + return Collections.unmodifiableList(filters); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +/** + * + * @author Thomas Wuerthinger + */ +public interface FilterChainProvider { + + public FilterChain getFilterChain(); + + public FilterChain getSequence(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author Thomas Wuerthinger + */ +public class FilterSetting { + + private Set<Filter> filters; + private String name; + + public FilterSetting() { + this(null); + } + + public FilterSetting(String name) { + this.name = name; + filters = new HashSet<>(); + } + + public Set<Filter> getFilters() { + return Collections.unmodifiableSet(filters); + } + + public void addFilter(Filter f) { + assert !filters.contains(f); + filters.add(f); + } + + public void removeFilter(Filter f) { + assert filters.contains(f); + filters.remove(f); + } + + public boolean containsFilter(Filter f) { + return filters.contains(f); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getFilterCount() { + return filters.size(); + } + + @Override + public String toString() { + return getName(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/GradientColorFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,161 @@ +/* + * 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.Diagram; +import com.sun.hotspot.igv.graph.Figure; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.Raster; +import java.util.List; + +/** + * Filter that colors nodes using a customizable color gradient, based on how + * a numeric property is located in a specified interval. + * + * @author Peter Hofer + */ +public class GradientColorFilter extends AbstractFilter { + + public static final String LINEAR = "LINEAR"; + public static final String LOGARITHMIC = "LOGARITHMIC"; + + private String propertyName = "probability"; + private float minValue = 0; + private float maxValue = 500; + private float[] fractions = {0, 0.5f, 1}; + private Color[] colors = {Color.BLUE, Color.YELLOW, Color.RED}; + private int shadeCount = 8; + private String mode = LINEAR; + + @Override + public String getName() { + return "Gradient Color Filter"; + } + + @Override + public void apply(Diagram d) { + boolean logarithmic = mode.equalsIgnoreCase(LOGARITHMIC); + if (!logarithmic && !mode.equalsIgnoreCase(LINEAR)) { + throw new RuntimeException("Unknown mode: " + mode); + } + + Rectangle bounds = new Rectangle(shadeCount, 1); + LinearGradientPaint lgp = new LinearGradientPaint(bounds.x, bounds.y, bounds.width, bounds.y, fractions, colors); + PaintContext context = lgp.createContext(null, bounds, bounds.getBounds2D(), AffineTransform.getTranslateInstance(0, 0), new RenderingHints(null)); + Raster raster = context.getRaster(bounds.x, bounds.y, bounds.width, bounds.height); + int[] rgb = raster.getPixels(bounds.x, bounds.y, bounds.width, bounds.height, (int[]) null); + Color[] shades = new Color[rgb.length / 3]; + for (int i = 0; i < shades.length; ++i) { + shades[i] = new Color(rgb[i * 3], rgb[i * 3 + 1], rgb[i * 3 + 2]); + } + + List<Figure> figures = d.getFigures(); + for (Figure f : figures) { + String property = f.getProperties().get(propertyName); + if (property != null) { + try { + float value = Float.parseFloat(property); + + Color nodeColor; + if (value <= minValue) { + nodeColor = colors[0]; + } else if (value >= maxValue) { + nodeColor = colors[colors.length - 1]; + } else { + double normalized = value - minValue; + double interval = maxValue - minValue; + int index; + // Use Math.ceil() to make values above zero distinguishable from zero + if (logarithmic) { + index = (int) Math.ceil(shades.length * Math.log(1 + normalized) / Math.log(1 + interval)); + } else { + index = (int) Math.ceil(shades.length * normalized / interval); + } + nodeColor = shades[index]; + } + f.setColor(nodeColor); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + public String getPropertyName() { + return propertyName; + } + + public void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + public float getMinValue() { + return minValue; + } + + public void setMinValue(float minValue) { + this.minValue = minValue; + } + + public float getMaxValue() { + return maxValue; + } + + public void setMaxValue(float maxValue) { + this.maxValue = maxValue; + } + + public float[] getFractions() { + return fractions; + } + + public void setFractions(float[] fractions) { + this.fractions = fractions; + } + + public Color[] getColors() { + return colors; + } + + public void setColors(Color[] colors) { + this.colors = colors; + } + + public int getShadeCount() { + return shadeCount; + } + + public void setShadeCount(int shadeCount) { + this.shadeCount = shadeCount; + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.Diagram; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.Selector; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * + * @author Thomas Wuerthinger + */ +public class RemoveFilter extends AbstractFilter { + + private List<RemoveRule> rules; + private String name; + + public RemoveFilter(String name) { + this.name = name; + rules = new ArrayList<>(); + } + + @Override + public String getName() { + return name; + } + + @Override + public void apply(Diagram diagram) { + for (RemoveRule r : rules) { + List<Figure> selected = r.getSelector().selected(diagram); + Set<Figure> toRemove = new HashSet<>(selected); + + if (r.getRemoveOrphans()) { + boolean changed; + do { + changed = false; + for (Figure f : diagram.getFigures()) { + if (!toRemove.contains(f)) { + if (toRemove.containsAll(f.getPredecessors()) && toRemove.containsAll(f.getSuccessors())) { + toRemove.add(f); + changed = true; + } + } + } + } while (changed); + } + + diagram.removeAllFigures(toRemove); + } + } + + public void addRule(RemoveRule rule) { + rules.add(rule); + } + + public static class RemoveRule { + + private Selector selector; + private boolean removeOrphans; + + public RemoveRule(Selector selector) { + this(selector, false); + } + + public RemoveRule(Selector selector, boolean removeOrphans) { + this.selector = selector; + this.removeOrphans = removeOrphans; + } + + public Selector getSelector() { + return selector; + } + + public boolean getRemoveOrphans() { + return removeOrphans; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.*; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class RemoveInputsFilter extends AbstractFilter { + + private List<RemoveInputsRule> rules; + private String name; + + public RemoveInputsFilter(String name) { + this.name = name; + rules = new ArrayList<>(); + } + + @Override + public String getName() { + return name; + } + + @Override + public void apply(Diagram diagram) { + + for (RemoveInputsRule r : rules) { + + List<Figure> list = r.getSelector().selected(diagram); + for (Figure f : list) { + int z = 0; + List<InputSlot> last = new ArrayList<>(); + for (InputSlot is : f.getInputSlots()) { + if (z >= r.getStartingIndex() && z <= r.getEndIndex() && is.getConnections().size() > 0) { + StringBuilder sb = new StringBuilder(); + List<Connection> conns = is.getConnections(); + for (int i = 0; i < conns.size(); i++) { + Connection c = conns.get(i); + OutputSlot os = c.getOutputSlot(); + Figure pred = os.getFigure(); + if (i != 0) { + sb.append("<BR>"); + } + sb.append(pred.getLines()[0]); + } + is.removeAllConnections(); + is.setShortName("X"); + is.setText(sb.toString()); + last.add(is); + } else { + last.clear(); + } + z++; + } + + if (last.size() > 3) { + InputSlot first = last.get(0); + first.setShortName("XX"); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < last.size(); i++) { + InputSlot is2 = last.get(i); + if (i != 0) { + sb.append("<BR>"); + } + sb.append(is2.getText()); + } + + first.setText(sb.toString()); + + for (int i = 1; i < last.size(); i++) { + f.removeSlot(last.get(i)); + } + } + } + } + } + + public void addRule(RemoveInputsRule rule) { + rules.add(rule); + } + + public static class RemoveInputsRule { + + private Selector selector; + private int startingIndex; + private int endIndex; + + public RemoveInputsRule(Selector selector) { + this(selector, 0); + } + + public RemoveInputsRule(Selector selector, int startIndex) { + this(selector, startIndex, Integer.MAX_VALUE); + } + + public RemoveInputsRule(Selector selector, int startIndex, int endIndex) { + this.startingIndex = startIndex; + this.endIndex = endIndex; + this.selector = selector; + } + + public int getStartingIndex() { + return startingIndex; + } + + public int getEndIndex() { + return endIndex; + } + + public Selector getSelector() { + return selector; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.*; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class RemoveSelfLoopsFilter extends AbstractFilter { + + private String name; + + /** Creates a new instance of RemoveSelfLoops */ + public RemoveSelfLoopsFilter(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public void apply(Diagram d) { + + for (Figure f : d.getFigures()) { + + for (InputSlot is : f.getInputSlots()) { + + List<Connection> toRemove = new ArrayList<>(); + for (Connection c : is.getConnections()) { + + if (c.getOutputSlot().getFigure() == f) { + toRemove.add(c); + } + } + + for (Connection c : toRemove) { + + c.remove(); + + OutputSlot os = c.getOutputSlot(); + if (os.getConnections().size() == 0) { + f.removeSlot(os); + } + + c.getInputSlot().setShortName("O"); + c.getInputSlot().setText("Self Loop"); + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.*; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class SplitFilter extends AbstractFilter { + + private String name; + private Selector selector; + private String propertyName; + + public SplitFilter(String name, Selector selector, String propertyName) { + this.name = name; + this.selector = selector; + this.propertyName = propertyName; + } + + @Override + public String getName() { + return name; + } + + @Override + public void apply(Diagram d) { + List<Figure> list = selector.selected(d); + + for (Figure f : list) { + + for (InputSlot is : f.getInputSlots()) { + for (Connection c : is.getConnections()) { + OutputSlot os = c.getOutputSlot(); + if (f.getSource().getSourceNodes().size() > 0) { + os.getSource().addSourceNodes(f.getSource()); + os.setAssociatedNode(f.getSource().getSourceNodes().get(0)); + os.setColor(f.getColor()); + } + + + String s = Figure.resolveString(propertyName, f.getProperties()); + if (s != null) { + os.setShortName(s); + } + + } + } + for (OutputSlot os : f.getOutputSlots()) { + for (Connection c : os.getConnections()) { + InputSlot is = c.getInputSlot(); + if (f.getSource().getSourceNodes().size() > 0) { + is.getSource().addSourceNodes(f.getSource()); + is.setAssociatedNode(f.getSource().getSourceNodes().get(0)); + is.setColor(f.getColor()); + } + + String s = Figure.resolveString(propertyName, f.getProperties()); + if (s != null) { + is.setShortName(s); + } + } + } + + d.removeFigure(f); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/UnconnectedSlotFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,76 @@ +/* + * 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.sun.hotspot.igv.filter; + +import com.sun.hotspot.igv.graph.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Filter that hides slots with no connections. + */ +public class UnconnectedSlotFilter extends AbstractFilter { + + private final boolean removeInputs; + private final boolean removeOutputs; + + public UnconnectedSlotFilter(boolean inputs, boolean outputs) { + this.removeInputs = inputs; + this.removeOutputs = outputs; + } + + @Override + public String getName() { + return "Unconnected Slot Filter"; + } + + @Override + public void apply(Diagram d) { + if (!removeInputs && !removeOutputs) { + return; + } + + List<Figure> figures = d.getFigures(); + for (Figure f : figures) { + List<Slot> remove = new ArrayList<>(); + if (removeInputs) { + for (InputSlot is : f.getInputSlots()) { + if (is.getConnections().isEmpty()) { + remove.add(is); + } + } + } + if (removeOutputs) { + for (OutputSlot os : f.getOutputSlots()) { + if (os.getConnections().isEmpty()) { + remove.add(os); + } + } + } + for (Slot s : remove) { + f.removeSlot(s); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2008, 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. + * + */ + + /** + * + * @author Thomas Wuerthinger + */ + +function colorize(property, regexp, color) { + var f = new ColorFilter(""); + f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), color)); + f.apply(graph); +} + +function remove(property, regexp) { + var f = new RemoveFilter(""); + f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)))); + f.apply(graph); +} + +function removeIncludingOrphans(property, regexp) { + var f = new RemoveFilter(""); + f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), true)); + f.apply(graph); +} + +function split(property, regexp, propertyName) { + if (propertyName == undefined) { + propertyName = graph.getNodeText(); + } + var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), propertyName); + f.apply(graph); +} + +function removeInputs(property, regexp, from, to) { + var f = new RemoveInputsFilter(""); + if(from == undefined && to == undefined) { + f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)))); + } else if(to == undefined) { + f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from)); + } else { + f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from, to)); + } + f.apply(graph); +} + +function removeUnconnectedSlots(inputs, outputs) { + var f = new UnconnectedSlotFilter(inputs, outputs); + f.apply(graph); +} + +function colorizeGradient(property, min, max) { + var f = new GradientColorFilter(); + f.setPropertyName(property); + f.setMinValue(min); + f.setMaxValue(max); + f.apply(graph); +} + +function colorizeGradientWithMode(property, min, max, mode) { + var f = new GradientColorFilter(); + f.setPropertyName(property); + f.setMinValue(min); + f.setMaxValue(max); + f.setMode(mode); + f.apply(graph); +} + +function colorizeGradientCustom(property, min, max, mode, colors, fractions, nshades) { + var f = new GradientColorFilter(); + f.setPropertyName(property); + f.setMinValue(min); + f.setMaxValue(max); + f.setMode(mode); + f.setColors(colors); + f.setFractions(fractions); + f.setShadeCount(nshades); + f.apply(graph); +} + +var black = Color.black; +var blue = Color.blue; +var cyan = Color.cyan; +var darkGray = Color.darkGray; +var gray = Color.gray; +var green = Color.green; +var lightGray = Color.lightGray; +var magenta = Color.magenta; +var orange = Color.orange; +var pink = Color.pink +var red = Color.red; +var yellow = Color.yellow; +var white = Color.white; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Filter/src/com/sun/hotspot/igv/filter/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <file name="JavaScriptHelper" url="helper.js"/> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.filterwindow" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.filterwindow.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.filterwindow +OpenIDE-Module-Layer: com/sun/hotspot/igv/filterwindow/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filterwindow/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.filterwindow-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +# 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=09ba2a87 +nbproject/build-impl.xml.script.CRC32=e4293f0e +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.filterwindow</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.filter</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.graph</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.actions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.21.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.dialogs</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.18.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.explorer</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.34.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.filesystems</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.46.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.loaders</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.nodes</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.14.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.39.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages/> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/META-INF/services/com.sun.hotspot.igv.filter.FilterChainProvider Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +com.sun.hotspot.igv.filterwindow.FilterChainProviderImplementation
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,3 @@ +OpenIDE-Module-Name=FilterWindow +CTL_FilterTopComponent=Filters +HINT_FilterTopComponent=Allows to choose active filters and modify them.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow; + +import javax.swing.JList; +import org.openide.explorer.view.ListView; +import org.openide.explorer.view.NodeListModel; + +/** + * + * @author Thomas Wuerthinger + */ +public class CheckListView extends ListView { + + @Override + public void showSelection(int[] indices) { + super.showSelection(indices); + } + + @Override + protected NodeListModel createModel() { + return new CheckNodeListModel(); + } + + @Override + protected JList<Object> createList() { + JList<Object> tmpList = super.createList(); + tmpList.setCellRenderer(new CheckRenderer(tmpList)); + return tmpList; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow; + +import com.sun.hotspot.igv.data.ChangedEvent; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.util.Lookup; + +/** + * + * @author Thomas Wuerthinger + */ +public class CheckNode extends AbstractNode { + + private ChangedEvent<CheckNode> selectionChangedEvent; + public boolean selected; + public boolean enabled; + + public CheckNode(Children c, Lookup lookup) { + super(c, lookup); + selectionChangedEvent = new ChangedEvent<>(this); + selected = false; + enabled = true; + } + + public ChangedEvent<CheckNode> getSelectionChangedEvent() { + return selectionChangedEvent; + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(boolean b) { + if (b != selected) { + selected = b; + selectionChangedEvent.fire(); + } + } + + public void setEnabled(boolean b) { + enabled = b; + } + + public boolean isEnabled() { + return enabled; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow; + +import org.openide.explorer.view.NodeListModel; +import org.openide.explorer.view.Visualizer; + +/** + * + * @author Thomas Wuerthinger + */ +public class CheckNodeListModel extends NodeListModel { + + public CheckNode getCheckNodeAt(int index) { + Object item = getElementAt(index); + if (item != null) { + return (CheckNode) Visualizer.findNode(item); + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow; + +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JCheckBox; +import javax.swing.JList; +import javax.swing.ListCellRenderer; + +/** + * @author Thomas Wuerthinger + */ +public class CheckRenderer extends JCheckBox implements ListCellRenderer<Object> { + + private JList<Object> list; + private Color startBackground; + + public CheckRenderer(final JList<Object> list) { + this.list = list; + list.addMouseListener( + new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + int index = list.locationToIndex(e.getPoint()); + Point p2 = list.indexToLocation(index); + Rectangle r = new Rectangle(p2.x, p2.y, getPreferredSize().height, getPreferredSize().height); + if (r.contains(e.getPoint())) { + CheckNode node = ((CheckNodeListModel) list.getModel()).getCheckNodeAt(index); + node.setSelected(!node.isSelected()); + list.repaint(); + e.consume(); + } + } + }); + + this.setPreferredSize(new Dimension(getPreferredSize().width, getPreferredSize().height - 5)); + startBackground = this.getBackground(); + } + + @Override + public Component getListCellRendererComponent(final JList<? extends Object> list, Object value, final int index, boolean isSelected, boolean cellHasFocus) { + setText(value.toString()); + CheckNode node = ((CheckNodeListModel) list.getModel()).getCheckNodeAt(index); + this.setSelected(node.isSelected()); + this.setEnabled(list.isEnabled()); + + if (isSelected && list.hasFocus()) { + this.setBackground(list.getSelectionBackground()); + this.setForeground(list.getSelectionForeground()); + } else if (isSelected) { + assert !list.hasFocus(); + this.setBackground(startBackground); + this.setForeground(list.getForeground()); + + } else { + this.setBackground(list.getBackground()); + this.setForeground(list.getForeground()); + } + return this; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow; + +import com.sun.hotspot.igv.filter.FilterChain; +import com.sun.hotspot.igv.filter.FilterChainProvider; + +/** + * + * @author Thomas Wuerthinger + */ +public class FilterChainProviderImplementation implements FilterChainProvider { + + @Override + public FilterChain getFilterChain() { + return FilterTopComponent.findInstance().getFilterChain(); + } + + @Override + public FilterChain getSequence() { + return FilterTopComponent.findInstance().getSequence(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow; + +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.filter.Filter; +import com.sun.hotspot.igv.filter.FilterChain; +import com.sun.hotspot.igv.filterwindow.actions.MoveFilterDownAction; +import com.sun.hotspot.igv.filterwindow.actions.MoveFilterUpAction; +import com.sun.hotspot.igv.filterwindow.actions.RemoveFilterAction; +import com.sun.hotspot.igv.util.PropertiesSheet; +import javax.swing.Action; +import org.openide.actions.OpenAction; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.Lookup; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.Utilities; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; + +/** + * + * @author Thomas Wuerthinger + */ +public class FilterNode extends CheckNode implements LookupListener, ChangedListener<FilterTopComponent> { + + private Filter filter; + private Lookup.Result<FilterChain> result; + + public FilterNode(Filter filter) { + this(filter, new InstanceContent()); + } + + private FilterNode(Filter filter, InstanceContent content) { + super(Children.LEAF, new AbstractLookup(content)); + content.add(filter); + + content.add(filter.getEditor()); + this.filter = filter; + filter.getChangedEvent().addListener(new ChangedListener<Filter>() { + + @Override + public void changed(Filter source) { + update(); + } + }); + + update(); + + Lookup.Template<FilterChain> tpl = new Lookup.Template<>(FilterChain.class); + result = Utilities.actionsGlobalContext().lookup(tpl); + result.addLookupListener(this); + + FilterTopComponent.findInstance().getFilterSettingsChangedEvent().addListener(this); + resultChanged(null); + + setShortDescription("Double-click to open filter"); + } + + private void update() { + this.setDisplayName(filter.getName()); + } + + public Filter getFilter() { + return filter; + } + + @Override + protected Sheet createSheet() { + Sheet s = super.createSheet(); + PropertiesSheet.initializeSheet(getFilter().getProperties(), s); + return s; + } + + @Override + public Action[] getActions(boolean b) { + return new Action[]{(Action) OpenAction.findObject(OpenAction.class, true), (Action) MoveFilterUpAction.findObject(MoveFilterUpAction.class, true), (Action) MoveFilterDownAction.findObject(MoveFilterDownAction.class, true), (Action) RemoveFilterAction.findObject(RemoveFilterAction.class, true)}; + } + + @Override + public Action getPreferredAction() { + return OpenAction.get(OpenAction.class).createContextAwareInstance(Utilities.actionsGlobalContext()); + } + + @Override + public void resultChanged(LookupEvent lookupEvent) { + changed(FilterTopComponent.findInstance()); + } + + @Override + public void changed(FilterTopComponent source) { + setSelected(source.getFilterChain().containsFilter(filter)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> +</Form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow; + +import com.sun.hotspot.igv.data.ChangedEvent; +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.filter.CustomFilter; +import com.sun.hotspot.igv.filter.Filter; +import com.sun.hotspot.igv.filter.FilterChain; +import com.sun.hotspot.igv.filter.FilterSetting; +import com.sun.hotspot.igv.filterwindow.actions.*; +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import java.util.*; +import javax.swing.JComboBox; +import javax.swing.UIManager; +import javax.swing.border.Border; +import org.openide.DialogDisplayer; +import org.openide.ErrorManager; +import org.openide.NotifyDescriptor; +import org.openide.awt.Toolbar; +import org.openide.awt.ToolbarPool; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; +import org.openide.filesystems.FileLock; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.*; +import org.openide.util.actions.SystemAction; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; + +/** + * + * @author Thomas Wuerthinger + */ +public final class FilterTopComponent extends TopComponent implements LookupListener, ExplorerManager.Provider { + + private static FilterTopComponent instance; + public static final String FOLDER_ID = "Filters"; + public static final String AFTER_ID = "after"; + public static final String ENABLED_ID = "enabled"; + public static final String PREFERRED_ID = "FilterTopComponent"; + private CheckListView view; + private ExplorerManager manager; + private FilterChain filterChain; + private FilterChain sequence; + private Lookup.Result<FilterChain> result; + private JComboBox comboBox; + private List<FilterSetting> filterSettings; + private FilterSetting customFilterSetting = new FilterSetting("-- Custom --"); + private ChangedEvent<FilterTopComponent> filterSettingsChangedEvent; + private ActionListener comboBoxActionListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + comboBoxSelectionChanged(); + } + }; + + public ChangedEvent<FilterTopComponent> getFilterSettingsChangedEvent() { + return filterSettingsChangedEvent; + } + + public FilterChain getSequence() { + return sequence; + } + + public void updateSelection() { + Node[] nodes = this.getExplorerManager().getSelectedNodes(); + int[] arr = new int[nodes.length]; + for (int i = 0; i < nodes.length; i++) { + int index = sequence.getFilters().indexOf(((FilterNode) nodes[i]).getFilter()); + arr[i] = index; + } + view.showSelection(arr); + } + + private void comboBoxSelectionChanged() { + + Object o = comboBox.getSelectedItem(); + if (o == null) { + return; + } + assert o instanceof FilterSetting; + FilterSetting s = (FilterSetting) o; + + if (s != customFilterSetting) { + FilterChain chain = getFilterChain(); + chain.getChangedEvent().beginAtomic(); + List<Filter> toRemove = new ArrayList<>(); + for (Filter f : chain.getFilters()) { + if (!s.containsFilter(f)) { + toRemove.add(f); + } + } + for (Filter f : toRemove) { + chain.removeFilter(f); + } + + for (Filter f : s.getFilters()) { + if (!chain.containsFilter(f)) { + chain.addFilter(f); + } + } + + chain.getChangedEvent().endAtomic(); + filterSettingsChangedEvent.fire(); + } else { + this.updateComboBoxSelection(); + } + + SystemAction.get(RemoveFilterSettingsAction.class).setEnabled(comboBox.getSelectedItem() != this.customFilterSetting); + SystemAction.get(SaveFilterSettingsAction.class).setEnabled(comboBox.getSelectedItem() == this.customFilterSetting); + } + + private void updateComboBox() { + comboBox.removeAllItems(); + comboBox.addItem(customFilterSetting); + for (FilterSetting s : filterSettings) { + comboBox.addItem(s); + } + + this.updateComboBoxSelection(); + } + + public void addFilterSetting() { + NotifyDescriptor.InputLine l = new NotifyDescriptor.InputLine("Name of the new profile:", "Filter Profile"); + if (DialogDisplayer.getDefault().notify(l) == NotifyDescriptor.OK_OPTION) { + String name = l.getInputText(); + + FilterSetting toRemove = null; + for (FilterSetting s : filterSettings) { + if (s.getName().equals(name)) { + NotifyDescriptor.Confirmation conf = new NotifyDescriptor.Confirmation("Filter profile \"" + name + "\" already exists, do you want to replace it?", "Filter"); + if (DialogDisplayer.getDefault().notify(conf) == NotifyDescriptor.YES_OPTION) { + toRemove = s; + break; + } else { + return; + } + } + } + + if (toRemove != null) { + filterSettings.remove(toRemove); + } + FilterSetting setting = createFilterSetting(name); + filterSettings.add(setting); + + // Sort alphabetically + Collections.sort(filterSettings, new Comparator<FilterSetting>() { + + @Override + public int compare(FilterSetting o1, FilterSetting o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + updateComboBox(); + } + } + + public boolean canRemoveFilterSetting() { + return comboBox.getSelectedItem() != customFilterSetting; + } + + public void removeFilterSetting() { + if (canRemoveFilterSetting()) { + Object o = comboBox.getSelectedItem(); + assert o instanceof FilterSetting; + FilterSetting f = (FilterSetting) o; + assert f != customFilterSetting; + assert filterSettings.contains(f); + NotifyDescriptor.Confirmation l = new NotifyDescriptor.Confirmation("Do you really want to remove filter profile \"" + f + "\"?", "Filter Profile"); + if (DialogDisplayer.getDefault().notify(l) == NotifyDescriptor.YES_OPTION) { + filterSettings.remove(f); + updateComboBox(); + } + } + } + + private FilterSetting createFilterSetting(String name) { + FilterSetting s = new FilterSetting(name); + FilterChain chain = this.getFilterChain(); + for (Filter f : chain.getFilters()) { + s.addFilter(f); + } + return s; + } + + private void updateComboBoxSelection() { + List<Filter> filters = this.getFilterChain().getFilters(); + boolean found = false; + for (FilterSetting s : filterSettings) { + if (s.getFilterCount() == filters.size()) { + boolean ok = true; + for (Filter f : filters) { + if (!s.containsFilter(f)) { + ok = false; + } + } + + if (ok) { + if (comboBox.getSelectedItem() != s) { + comboBox.setSelectedItem(s); + } + found = true; + break; + } + } + } + + if (!found && comboBox.getSelectedItem() != customFilterSetting) { + comboBox.setSelectedItem(customFilterSetting); + } + } + + private class FilterChildren extends Children.Keys<Filter> implements ChangedListener<CheckNode> { + + private HashMap<Filter, Node> nodeHash = new HashMap<>(); + + @Override + protected Node[] createNodes(Filter filter) { + if (nodeHash.containsKey(filter)) { + return new Node[]{nodeHash.get(filter)}; + } + + FilterNode node = new FilterNode(filter); + node.getSelectionChangedEvent().addListener(this); + nodeHash.put(filter, node); + return new Node[]{node}; + } + + public FilterChildren() { + sequence.getChangedEvent().addListener(new ChangedListener<FilterChain>() { + + @Override + public void changed(FilterChain source) { + addNotify(); + } + }); + + setBefore(false); + } + + @Override + protected void addNotify() { + setKeys(sequence.getFilters()); + updateSelection(); + } + + @Override + public void changed(CheckNode source) { + FilterNode node = (FilterNode) source; + Filter f = node.getFilter(); + FilterChain chain = getFilterChain(); + if (node.isSelected()) { + if (!chain.containsFilter(f)) { + chain.addFilter(f); + } + } else { + if (chain.containsFilter(f)) { + chain.removeFilter(f); + } + } + view.revalidate(); + view.repaint(); + updateComboBoxSelection(); + } + } + + public FilterChain getFilterChain() { + return filterChain; + } + + private FilterTopComponent() { + filterSettingsChangedEvent = new ChangedEvent<>(this); + initComponents(); + setName(NbBundle.getMessage(FilterTopComponent.class, "CTL_FilterTopComponent")); + setToolTipText(NbBundle.getMessage(FilterTopComponent.class, "HINT_FilterTopComponent")); + // setIcon(Utilities.loadImage(ICON_PATH, true)); + + sequence = new FilterChain(); + filterChain = new FilterChain(); + initFilters(); + manager = new ExplorerManager(); + manager.setRootContext(new AbstractNode(new FilterChildren())); + associateLookup(ExplorerUtils.createLookup(manager, getActionMap())); + view = new CheckListView(); + + ToolbarPool.getDefault().setPreferredIconSize(16); + Toolbar toolBar = new Toolbar(); + Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N + toolBar.setBorder(b); + comboBox = new JComboBox(); + toolBar.add(comboBox); + this.add(toolBar, BorderLayout.NORTH); + toolBar.add(SaveFilterSettingsAction.get(SaveFilterSettingsAction.class)); + toolBar.add(RemoveFilterSettingsAction.get(RemoveFilterSettingsAction.class)); + toolBar.addSeparator(); + toolBar.add(NewFilterAction.get(NewFilterAction.class)); + toolBar.add(RemoveFilterAction.get(RemoveFilterAction.class).createContextAwareInstance(this.getLookup())); + toolBar.add(MoveFilterUpAction.get(MoveFilterUpAction.class).createContextAwareInstance(this.getLookup())); + toolBar.add(MoveFilterDownAction.get(MoveFilterDownAction.class).createContextAwareInstance(this.getLookup())); + this.add(view, BorderLayout.CENTER); + + filterSettings = new ArrayList<>(); + updateComboBox(); + + comboBox.addActionListener(comboBoxActionListener); + setChain(filterChain); + } + + public void newFilter() { + CustomFilter cf = new CustomFilter("My custom filter", ""); + if (cf.openInEditor()) { + sequence.addFilter(cf); + FileObject fo = getFileObject(cf); + FilterChangedListener listener = new FilterChangedListener(fo, cf); + listener.changed(cf); + cf.getChangedEvent().addListener(listener); + } + } + + public void removeFilter(Filter f) { + com.sun.hotspot.igv.filter.CustomFilter cf = (com.sun.hotspot.igv.filter.CustomFilter) f; + + sequence.removeFilter(cf); + try { + getFileObject(cf).delete(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + + } + + private static class FilterChangedListener implements ChangedListener<Filter> { + + private FileObject fileObject; + private CustomFilter filter; + + public FilterChangedListener(FileObject fo, CustomFilter cf) { + fileObject = fo; + filter = cf; + } + + @Override + public void changed(Filter source) { + try { + if (!fileObject.getName().equals(filter.getName())) { + FileLock lock = fileObject.lock(); + fileObject.move(lock, fileObject.getParent(), filter.getName(), ""); + lock.releaseLock(); + FileObject newFileObject = fileObject.getParent().getFileObject(filter.getName()); + fileObject = newFileObject; + } + + FileLock lock = fileObject.lock(); + OutputStream os = fileObject.getOutputStream(lock); + try (Writer w = new OutputStreamWriter(os)) { + String s = filter.getCode(); + w.write(s); + } + lock.releaseLock(); + + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } + + public void initFilters() { + FileObject folder = FileUtil.getConfigRoot().getFileObject(FOLDER_ID); + FileObject[] children = folder.getChildren(); + + List<CustomFilter> customFilters = new ArrayList<>(); + HashMap<CustomFilter, String> afterMap = new HashMap<>(); + Set<CustomFilter> enabledSet = new HashSet<>(); + HashMap<String, CustomFilter> map = new HashMap<>(); + + for (final FileObject fo : children) { + InputStream is = null; + + String code = ""; + FileLock lock = null; + try { + lock = fo.lock(); + is = fo.getInputStream(); + BufferedReader r = new BufferedReader(new InputStreamReader(is)); + String s; + StringBuilder sb = new StringBuilder(); + while ((s = r.readLine()) != null) { + sb.append(s); + sb.append("\n"); + } + code = sb.toString(); + } catch (FileNotFoundException ex) { + Exceptions.printStackTrace(ex); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } finally { + try { + is.close(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + lock.releaseLock(); + } + + String displayName = fo.getName(); + + + final CustomFilter cf = new CustomFilter(displayName, code); + map.put(displayName, cf); + + String after = (String) fo.getAttribute(AFTER_ID); + afterMap.put(cf, after); + + Boolean enabled = (Boolean) fo.getAttribute(ENABLED_ID); + if (enabled != null && (boolean) enabled) { + enabledSet.add(cf); + } + + cf.getChangedEvent().addListener(new FilterChangedListener(fo, cf)); + + customFilters.add(cf); + } + + for (int j = 0; j < customFilters.size(); j++) { + for (int i = 0; i < customFilters.size(); i++) { + List<CustomFilter> copiedList = new ArrayList<>(customFilters); + for (CustomFilter cf : copiedList) { + + String after = afterMap.get(cf); + + if (map.containsKey(after)) { + CustomFilter afterCf = map.get(after); + int index = customFilters.indexOf(afterCf); + int currentIndex = customFilters.indexOf(cf); + + if (currentIndex < index) { + customFilters.remove(currentIndex); + customFilters.add(index, cf); + } + } + } + } + } + + for (CustomFilter cf : customFilters) { + sequence.addFilter(cf); + if (enabledSet.contains(cf)) { + filterChain.addFilter(cf); + } + } + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents + private void initComponents() { + + setLayout(new java.awt.BorderLayout()); + + }// </editor-fold>//GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + /** + * Gets default instance. Do not use directly: reserved for *.settings files only, + * i.e. deserialization routines; otherwise you could get a non-deserialized instance. + * To obtain the singleton instance, use {@link findInstance}. + */ + public static synchronized FilterTopComponent getDefault() { + if (instance == null) { + instance = new FilterTopComponent(); + } + return instance; + } + + /** + * Obtain the FilterTopComponent instance. Never call {@link #getDefault} directly! + */ + public static synchronized FilterTopComponent findInstance() { + TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); + if (win == null) { + ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find Filter component. It will not be located properly in the window system."); + return getDefault(); + } + if (win instanceof FilterTopComponent) { + return (FilterTopComponent) win; + } + ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior."); + return getDefault(); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_ALWAYS; + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + @Override + public ExplorerManager getExplorerManager() { + return manager; + } + + @Override + public void componentOpened() { + Lookup.Template<FilterChain> tpl = new Lookup.Template<>(FilterChain.class); + result = Utilities.actionsGlobalContext().lookup(tpl); + result.addLookupListener(this); + } + + @Override + public void componentClosed() { + result.removeLookupListener(this); + result = null; + } + + @Override + public void resultChanged(LookupEvent lookupEvent) { + setChain(Utilities.actionsGlobalContext().lookup(FilterChain.class)); + } + + public void setChain(FilterChain chain) { + updateComboBoxSelection(); + } + + private FileObject getFileObject(CustomFilter cf) { + FileObject fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID + "/" + cf.getName()); + if (fo == null) { + try { + fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID).createData(cf.getName()); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + return fo; + } + + @Override + public boolean requestFocus(boolean temporary) { + view.requestFocus(); + return super.requestFocus(temporary); + } + + @Override + protected boolean requestFocusInWindow(boolean temporary) { + view.requestFocus(); + return super.requestFocusInWindow(temporary); + } + + @Override + public void requestActive() { + super.requestActive(); + view.requestFocus(); + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + + out.writeInt(filterSettings.size()); + for (FilterSetting f : filterSettings) { + out.writeUTF(f.getName()); + + out.writeInt(f.getFilterCount()); + for (Filter filter : f.getFilters()) { + CustomFilter cf = (CustomFilter) filter; + out.writeUTF(cf.getName()); + } + } + + CustomFilter prev = null; + for (Filter f : this.sequence.getFilters()) { + CustomFilter cf = (CustomFilter) f; + FileObject fo = getFileObject(cf); + if (getFilterChain().containsFilter(cf)) { + fo.setAttribute(ENABLED_ID, true); + } else { + fo.setAttribute(ENABLED_ID, false); + } + + if (prev == null) { + fo.setAttribute(AFTER_ID, null); + } else { + fo.setAttribute(AFTER_ID, prev.getName()); + } + + prev = cf; + } + } + + public CustomFilter findFilter(String name) { + for (Filter f : sequence.getFilters()) { + + CustomFilter cf = (CustomFilter) f; + if (cf.getName().equals(name)) { + return cf; + } + } + + return null; + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + + int filterSettingsCount = in.readInt(); + for (int i = 0; i < filterSettingsCount; i++) { + String name = in.readUTF(); + FilterSetting s = new FilterSetting(name); + int filterCount = in.readInt(); + for (int j = 0; j < filterCount; j++) { + String filterName = in.readUTF(); + CustomFilter filter = findFilter(filterName); + if (filter != null) { + s.addFilter(filter); + } + } + + filterSettings.add(s); + } + updateComboBox(); + } + + final static class ResolvableHelper implements Serializable { + + private static final long serialVersionUID = 1L; + + public Object readResolve() { + return FilterTopComponent.getDefault(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd"> +<settings version="1.0"> + <module name="com.sun.hotspot.igv.filterwindow" spec="1.0"/> + <instanceof class="org.openide.windows.TopComponent"/> + <instanceof class="com.sun.hotspot.igv.filterwindow.FilterTopComponent"/> + <instance class="com.sun.hotspot.igv.filterwindow.FilterTopComponent" method="getDefault"/> +</settings>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-ref2_0.dtd"> +<tc-ref version="2.0" > + <module name="com.sun.hotspot.igv.filterwindow" spec="1.0"/> + <tc-id id="FilterTopComponent"/> + <state opened="true"/> +</tc-ref>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,7 @@ +CTL_FilterAction=Filters +CTL_MoveFilterUpAction=Move upwards +CTL_MoveFilterDownAction=Move downwards +CTL_RemoveFilterAction=Remove +CTL_RemoveFilterSettingsAction=Remove filter setting +CTL_SaveFilterSettingsAction=Create filter profile... +CTL_NewFilterAction=New filter...
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow.actions; + +import com.sun.hotspot.igv.filterwindow.FilterTopComponent; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; + +/** + * + * @author Thomas Wuerthinger + */ +public class FilterAction extends AbstractAction { + + public FilterAction() { + super(NbBundle.getMessage(FilterAction.class, "CTL_FilterAction")); + } + + @Override + public void actionPerformed(ActionEvent evt) { + TopComponent win = FilterTopComponent.findInstance(); + win.open(); + win.requestActive(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow.actions; + +import com.sun.hotspot.igv.filter.Filter; +import com.sun.hotspot.igv.filterwindow.FilterTopComponent; +import javax.swing.Action; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CookieAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class MoveFilterDownAction extends CookieAction { + + @Override + protected void performAction(Node[] activatedNodes) { + for (Node n : activatedNodes) { + Filter c = n.getLookup().lookup(Filter.class); + FilterTopComponent.findInstance().getSequence().moveFilterDown(c); + } + } + + @Override + protected int mode() { + return CookieAction.MODE_EXACTLY_ONE; + } + + public MoveFilterDownAction() { + + putValue(Action.SHORT_DESCRIPTION, "Move selected filter downwards"); + } + + @Override + public String getName() { + return NbBundle.getMessage(MoveFilterUpAction.class, "CTL_MoveFilterDownAction"); + } + + @Override + protected Class[] cookieClasses() { + return new Class[]{ + Filter.class + }; + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/filterwindow/images/down.png"; + } + + @Override + protected void initialize() { + super.initialize(); + putValue("noIconInMenu", Boolean.TRUE); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow.actions; + +import com.sun.hotspot.igv.filter.Filter; +import com.sun.hotspot.igv.filterwindow.FilterTopComponent; +import javax.swing.Action; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CookieAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class MoveFilterUpAction extends CookieAction { + + @Override + protected void performAction(Node[] activatedNodes) { + for (Node n : activatedNodes) { + Filter c = n.getLookup().lookup(Filter.class); + FilterTopComponent.findInstance().getSequence().moveFilterUp(c); + } + } + + @Override + protected int mode() { + return CookieAction.MODE_EXACTLY_ONE; + } + + public MoveFilterUpAction() { + putValue(Action.SHORT_DESCRIPTION, "Move selected filter upwards"); + } + + @Override + public String getName() { + return NbBundle.getMessage(MoveFilterUpAction.class, "CTL_MoveFilterUpAction"); + } + + @Override + protected Class[] cookieClasses() { + return new Class[]{ + Filter.class + }; + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/filterwindow/images/up.png"; + } + + @Override + protected void initialize() { + super.initialize(); + putValue("noIconInMenu", Boolean.TRUE); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow.actions; + +import com.sun.hotspot.igv.filterwindow.FilterTopComponent; +import javax.swing.Action; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallableSystemAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class NewFilterAction extends CallableSystemAction { + + public NewFilterAction() { + putValue(Action.SHORT_DESCRIPTION, "Create new filter"); + } + + @Override + public void performAction() { + FilterTopComponent.findInstance().newFilter(); + } + + @Override + public String getName() { + return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_NewFilterAction"); + } + + @Override + protected void initialize() { + super.initialize(); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/filterwindow/images/plus.png"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow.actions; + +import com.sun.hotspot.igv.filter.Filter; +import com.sun.hotspot.igv.filterwindow.FilterTopComponent; +import javax.swing.Action; +import javax.swing.JOptionPane; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CookieAction; +import org.openide.windows.WindowManager; + +/** + * + * @author Thomas Wuerthinger + */ +public final class RemoveFilterAction extends CookieAction { + + @Override + protected void performAction(Node[] activatedNodes) { + Object[] options = {"Yes", + "No", + "Cancel" + }; + int n = JOptionPane.showOptionDialog(WindowManager.getDefault().getMainWindow(), + "Do you really want to delete " + activatedNodes.length + " filter(s)?", "Delete Filters", + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[2]); + + if (n == JOptionPane.YES_OPTION) { + for (int i = 0; i < activatedNodes.length; i++) { + FilterTopComponent.findInstance().removeFilter(activatedNodes[i].getLookup().lookup(Filter.class)); + } + } + } + + @Override + protected int mode() { + return CookieAction.MODE_ALL; + } + + @Override + public String getName() { + return NbBundle.getMessage(RemoveFilterAction.class, "CTL_RemoveFilterAction"); + } + + public RemoveFilterAction() { + putValue(Action.SHORT_DESCRIPTION, "Remove selected filter"); + } + + @Override + protected Class[] cookieClasses() { + return new Class[]{ + Filter.class + }; + } + + @Override + protected void initialize() { + super.initialize(); + putValue("noIconInMenu", Boolean.TRUE); + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/filterwindow/images/minus.png"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow.actions; + +import com.sun.hotspot.igv.filterwindow.FilterTopComponent; +import javax.swing.Action; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallableSystemAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class RemoveFilterSettingsAction extends CallableSystemAction { + + @Override + public void performAction() { + FilterTopComponent.findInstance().removeFilterSetting(); + } + + @Override + public String getName() { + return NbBundle.getMessage(RemoveFilterSettingsAction.class, "CTL_RemoveFilterSettingsAction"); + } + + public RemoveFilterSettingsAction() { + putValue(Action.SHORT_DESCRIPTION, "Delete current filter profile"); + } + + @Override + protected void initialize() { + super.initialize(); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/filterwindow/images/delete.png"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.filterwindow.actions; + +import com.sun.hotspot.igv.filterwindow.FilterTopComponent; +import javax.swing.Action; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.actions.CallableSystemAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class SaveFilterSettingsAction extends CallableSystemAction { + + @Override + public void performAction() { + FilterTopComponent.findInstance().addFilterSetting(); + } + + @Override + public String getName() { + return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_SaveFilterSettingsAction"); + } + + @Override + protected void initialize() { + super.initialize(); + } + + public SaveFilterSettingsAction() { + putValue(Action.SHORT_DESCRIPTION, "Save filter configuration as profile..."); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/filterwindow/images/add.png"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mode version="2.1"> + <name unique="customRightTopMode" /> + <kind type="view" /> + <state type="joined" /> + <constraints> + <path orientation="horizontal" number="90" weight="0.2"/> + <path orientation="vertical" number="0" weight="0.75"/> + </constraints> + <bounds x="0" y="0" width="0" height="0" /> + <frame state="0"/> + <active-tc id="FilterTopComponent"/> + <empty-behavior permanent="false"/> +</mode>
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.png has changed
Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <folder name="Edit"> + <file name="com-sun-hotspot-igv-filterwindow-actions-MoveFilterDownAction.instance"> + <attr name="position" intvalue="300"/> + </file> + <file name="com-sun-hotspot-igv-filterwindow-actions-MoveFilterUpAction.instance"> + <attr name="position" intvalue="400"/> + </file> + <file name="com-sun-hotspot-igv-filterwindow-actions-RemoveFilterAction.instance"> + <attr name="position" intvalue="500"/> + </file> + <file name="com-sun-hotspot-igv-filterwindow-actions-RemoveFilterSettingsAction.instance"> + <attr name="position" intvalue="600"/> + </file> + <file name="com-sun-hotspot-igv-filterwindow-actions-SaveFilterSettingsAction.instance"> + <attr name="position" intvalue="900"/> + </file> + </folder> + + <folder name="Actions"> + <folder name="Window"> + <file name="com-sun-hotspot-igv-filterwindow-actions-FilterAction.instance"/> + </folder> + </folder> + <folder name="Menu"> + <folder name="Window"> + <file name="FilterAction.shadow"> + <attr name="originalFile" stringvalue="Actions/Window/com-sun-hotspot-igv-filterwindow-actions-FilterAction.instance"/> + </file> + </folder> + </folder> + <folder name="Windows2"> + <folder name="Components"> + <file name="FilterTopComponent.settings" url="FilterTopComponentSettings.xml"/> + </folder> + <folder name="Modes"> + <file name="customRightTopMode.wsmode" url="customRightTopWsmode.xml"/> + <folder name="customRightTopMode"> + <file name="FilterTopComponent.wstcref" url="FilterTopComponentWstcref.xml"/> + </folder> + </folder> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.graal" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.graal.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.graal +OpenIDE-Module-Layer: com/sun/hotspot/igv/graal/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graal/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.graal-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=79002a09 +build.xml.script.CRC32=3534d355 +build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 +# 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=79002a09 +nbproject/build-impl.xml.script.CRC32=2867f2d5 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.graal</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.filter</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.graph</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages/> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=GraalCompilerSupport
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,74 @@ +/* + * 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.sun.hotspot.igv.graal.filters; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.filter.AbstractFilter; +import com.sun.hotspot.igv.graph.Connection; +import com.sun.hotspot.igv.graph.Diagram; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.InputSlot; +import java.util.HashSet; +import java.util.Set; + +public class GraalCFGFilter extends AbstractFilter { + + @Override + public String getName() { + return "Graal CFG Filter"; + } + + @Override + public void apply(Diagram d) { + Set<Figure> figuresToRemove = new HashSet<>(); + Set<Connection> connectionsToRemove = new HashSet<>(); + for (Figure f : d.getFigures()) { + final String prop = f.getProperties().get("probability"); + + if (prop == null) { + figuresToRemove.add(f); + } + } + d.removeAllFigures(figuresToRemove); + + for (Figure f : d.getFigures()) { + Properties p = f.getProperties(); + int predCount = Integer.parseInt(p.get("predecessorCount")); + for (InputSlot is : f.getInputSlots()) { + if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) { + for (Connection c : is.getConnections()) { + if (!"EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) { + connectionsToRemove.add(c); + } + } + } + } + } + + for (Connection c : connectionsToRemove) { + c.remove(); + System.out.println("rm " + c); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,81 @@ +/* + * 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.sun.hotspot.igv.graal.filters; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.filter.AbstractFilter; +import com.sun.hotspot.igv.graph.Diagram; +import com.sun.hotspot.igv.graph.Figure; +import java.awt.Color; +import java.util.List; + +public class GraalColoringFilter extends AbstractFilter { + + private String colorName; + + public GraalColoringFilter(String colorName) { + this.colorName = colorName; + } + + @Override + public String getName() { + return "Graal Coloring Filter (" + colorName + ")"; + } + + @Override + public void apply(Diagram d) { + List<Figure> figures = d.getFigures(); + int colors = 0; + for (Figure f : figures) { + Properties p = f.getProperties(); + final String prop = p.get(colorName + "Color"); + if (prop == null) { + continue; + } + try { + int color = Integer.parseInt(prop); + if (color > colors) { + colors = color; + } + } catch (NumberFormatException nfe) { + // nothing to do + } + } + colors++; + for (Figure f : figures) { + Properties p = f.getProperties(); + final String prop = p.get(colorName + "Color"); + if (prop == null) { + continue; + } + try { + int color = Integer.parseInt(prop); + Color c = Color.getHSBColor((float) color / colors, 1.0f, 0.7f); + f.setColor(c); + } catch (NumberFormatException nfe) { + // nothing to do + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,114 @@ +/* + * 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.sun.hotspot.igv.graal.filters; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.filter.AbstractFilter; +import com.sun.hotspot.igv.graph.Connection; +import com.sun.hotspot.igv.graph.Connection.ConnectionStyle; +import com.sun.hotspot.igv.graph.Diagram; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.InputSlot; +import java.awt.Color; +import java.util.List; + +/** + * Filter that colors usage and successor edges differently. + * + * @author Peter Hofer + */ +public class GraalEdgeColorFilter extends AbstractFilter { + + private Color successorColor = Color.BLUE; + private Color usageColor = Color.RED; + private Color memoryColor = Color.GREEN; + + public GraalEdgeColorFilter() { + } + + @Override + public String getName() { + return "Graal Edge Color Filter"; + } + + @Override + public void apply(Diagram d) { + List<Figure> figures = d.getFigures(); + for (Figure f : figures) { + Properties p = f.getProperties(); + int predCount; + if (p.get("predecessorCount") != null) { + predCount = Integer.parseInt(p.get("predecessorCount")); + } else { + predCount = 0; + } + for (InputSlot is : f.getInputSlots()) { + Color color; + ConnectionStyle style = ConnectionStyle.NORMAL; + if (is.getPosition() < predCount) { + color = successorColor; + style = ConnectionStyle.BOLD; + } else { + color = usageColor; + } + + is.setColor(color); + for (Connection c : is.getConnections()) { + if (c.getLabel() == null || !c.getLabel().endsWith("#NDF")) { + c.setColor(color); + c.setStyle(style); + } else if ("EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class")) + || "EndNode".equals(c.getOutputSlot().getProperties().get("class"))) { + c.setColor(successorColor); + c.setStyle(ConnectionStyle.BOLD); + } + } + } + } + } + + public Color getUsageColor() { + return usageColor; + } + + public void setUsageColor(Color usageColor) { + this.usageColor = usageColor; + } + + public void setMemoryColor(Color memoryColor) { + this.memoryColor = memoryColor; + } + + public Color getMemoryColor() { + return memoryColor; + } + + public Color getSuccessorColor() { + return successorColor; + } + + public void setSuccessorColor(Color successorColor) { + this.successorColor = successorColor; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/beginend.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,4 @@ +var f = new CombineFilter("Combine Filter"); +f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("class", ".*"), new Properties.RegexpPropertyMatcher("class", "BeginNode"), false, "shortName")); +f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("class", "EndNode"), new Properties.RegexpPropertyMatcher("class", ".*"), true, "shortName")); +f.apply(graph);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,4 @@ +colorize("name", "<init>.*", yellow); +colorize("name", "<clinit>.*", pink); +colorize("leaf", "1", lightGray); +colorize("cutoff", "1", red);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/cfg.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +var f = new com.sun.hotspot.igv.graal.filters.GraalCFGFilter(); +f.apply(graph);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,11 @@ +colorize("name", ".*", white); +colorize("name", "StartNode|EndNode|LoopBegin|LoopEnd|Return", orange); +colorize("name", "Phi:.*", magenta); +colorize("name", "FrameState@.*", new java.awt.Color(0.5, 0.8, 1.0)); +colorize("name", "If", pink); +colorize("name", "const.*", new java.awt.Color(0.7, 0.7, 0.7)); +colorize("name", "Local", new java.awt.Color(0.85, 0.85, 0.85)); +colorize("name", "\\+|-|\\*|/", cyan); +colorize("name", "Comp .*", yellow); + +colorize("notInOwnBlock", "true", red); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,4 @@ +var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter(); +f.setUsageColor(blue); +f.setSuccessorColor(red); +f.apply(graph);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/framestatelocks.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +colorize("class", "FrameState", red); +colorize("locks", "", gray); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +remove("class", "FrameState"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/probability.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,3 @@ +colorizeGradientWithMode("probability", 0, 500, "logarithmic"); + +// more parameters: colorizeGradientCustom("probability", 0, 500, "logarithmic", [blue, yellow, red], [0, 0.5, 1], 16);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/slots.filter Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +removeUnconnectedSlots(true, true);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <folder name="Filters"> + <file name="Graal Coloring" url="filters/color.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal Edge Coloring" url="filters/edgeColor.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal Remove Unconnected Slots" url="filters/slots.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal Probability" url="filters/probability.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal Reduce Begin-End" url="filters/beginend.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal Remove FrameState" url="filters/noframestate.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal Mark FrameState With Lock" url="filters/framestatelocks.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal Call Analysis" url="filters/callgraph.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + + <file name="Graal CFG-only" url="filters/cfg.filter"> + <attr name="enabled" boolvalue="false"/> + </file> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.graph" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.graph.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.graph +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graph/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.graph-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=b2bc2f02 +build.xml.script.CRC32=486d5dab +build.xml.stylesheet.CRC32=79c3b980 +# 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=b2bc2f02 +nbproject/build-impl.xml.script.CRC32=17fa0f49 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.graph</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.sun.hotspot.igv.graph</package> + <package>com.sun.hotspot.igv.graph.services</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class AndSelector implements Selector { + + private Selector selector1; + private Selector selector2; + + public AndSelector(Selector s1, Selector s2) { + this.selector1 = s1; + this.selector2 = s2; + } + + @Override + public List<Figure> selected(Diagram d) { + List<Figure> l1 = selector1.selected(d); + List<Figure> l2 = selector2.selected(d); + List<Figure> result = new ArrayList<>(); + for (Figure f : l2) { + if (l1.contains(f)) { + result.add(f); + } + } + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Graph
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import com.sun.hotspot.igv.data.Source; +import com.sun.hotspot.igv.layout.Link; +import com.sun.hotspot.igv.layout.Port; +import java.awt.Color; +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class Connection implements Source.Provider, Link { + + @Override + public boolean isVIP() { + return style == ConnectionStyle.BOLD; + } + + public enum ConnectionStyle { + + NORMAL, + DASHED, + BOLD + } + private InputSlot inputSlot; + private OutputSlot outputSlot; + private Source source; + private Color color; + private ConnectionStyle style; + private List<Point> controlPoints; + private String label; + + protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label) { + this.inputSlot = inputSlot; + this.outputSlot = outputSlot; + this.label = label; + this.inputSlot.connections.add(this); + this.outputSlot.connections.add(this); + controlPoints = new ArrayList<>(); + Figure sourceFigure = this.outputSlot.getFigure(); + Figure destFigure = this.inputSlot.getFigure(); + sourceFigure.addSuccessor(destFigure); + destFigure.addPredecessor(sourceFigure); + source = new Source(); + + this.color = Color.BLACK; + this.style = ConnectionStyle.NORMAL; + } + + public InputSlot getInputSlot() { + return inputSlot; + } + + public OutputSlot getOutputSlot() { + return outputSlot; + } + + public Color getColor() { + return color; + } + + public ConnectionStyle getStyle() { + return style; + } + + public void setColor(Color c) { + color = c; + } + + public void setStyle(ConnectionStyle s) { + style = s; + } + + @Override + public Source getSource() { + return source; + } + + public String getLabel() { + return label; + } + + public void remove() { + inputSlot.getFigure().removePredecessor(outputSlot.getFigure()); + inputSlot.connections.remove(this); + outputSlot.getFigure().removeSuccessor(inputSlot.getFigure()); + outputSlot.connections.remove(this); + } + + public String getToolTipText() { + StringBuilder builder = new StringBuilder(); + if (label != null) { + builder.append(label).append(": from "); + } else { + builder.append("From "); + } + builder.append(getOutputSlot().getFigure()); + builder.append(" to "); + builder.append(getInputSlot().getFigure()); + return builder.toString(); + } + + @Override + public String toString() { + return "Connection('" + label + "', " + getFrom().getVertex() + " to " + getTo().getVertex() + ")"; + } + + @Override + public Port getFrom() { + return outputSlot; + } + + @Override + public Port getTo() { + return inputSlot; + } + + @Override + public List<Point> getControlPoints() { + return controlPoints; + } + + @Override + public void setControlPoints(List<Point> list) { + controlPoints = list; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import com.sun.hotspot.igv.data.InputEdge; +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.data.InputNode; +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher; +import java.awt.Font; +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class Diagram { + + private List<Figure> figures; + private InputGraph graph; + private int curId; + private String nodeText; + private Font font; + private Font slotFont; + + public Font getFont() { + return font; + } + + public Font getSlotFont() { + return slotFont; + } + + private Diagram() { + figures = new ArrayList<>(); + this.nodeText = ""; + this.font = new Font("Arial", Font.PLAIN, 13); + this.slotFont = new Font("Arial", Font.PLAIN, 10); + } + + public String getNodeText() { + return nodeText; + } + + public Diagram getNext() { + return Diagram.createDiagram(graph.getNext(), nodeText); + } + + public Diagram getPrev() { + return Diagram.createDiagram(graph.getPrev(), nodeText); + } + + public List<Figure> getFigures() { + return Collections.unmodifiableList(figures); + } + + public Figure createFigure() { + Figure f = new Figure(this, curId); + curId++; + this.figures.add(f); + return f; + } + + public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label) { + assert inputSlot.getFigure().getDiagram() == this; + assert outputSlot.getFigure().getDiagram() == this; + return new Connection(inputSlot, outputSlot, label); + } + + public Map<InputNode, Set<Figure>> calcSourceToFigureRelation() { + Map<InputNode, Set<Figure>> map = new HashMap<>(); + + for(InputNode node : this.getGraph().getNodes()) { + map.put(node, new HashSet<Figure>()); + } + + for(Figure f : this.getFigures()) { + for(InputNode node : f.getSource().getSourceNodes()) { + map.get(node).add(f); + } + } + + return map; + } + + public static Diagram createDiagram(InputGraph graph, String nodeText) { + if (graph == null) { + return null; + } + + Diagram d = new Diagram(); + d.graph = graph; + d.nodeText = nodeText; + + Collection<InputNode> nodes = graph.getNodes(); + Hashtable<Integer, Figure> figureHash = new Hashtable<>(); + for (InputNode n : nodes) { + Figure f = d.createFigure(); + f.getSource().addSourceNode(n); + f.getProperties().add(n.getProperties()); + figureHash.put(n.getId(), f); + } + + for (InputEdge e : graph.getEdges()) { + + int from = e.getFrom(); + int to = e.getTo(); + Figure fromFigure = figureHash.get(from); + Figure toFigure = figureHash.get(to); + assert fromFigure != null && toFigure != null; + + if(fromFigure == null || toFigure == null) continue; + + int fromIndex = e.getFromIndex(); + while (fromFigure.getOutputSlots().size() <= fromIndex) { + fromFigure.createOutputSlot(); + } + OutputSlot outputSlot = fromFigure.getOutputSlots().get(fromIndex); + + int toIndex = e.getToIndex(); + while (toFigure.getInputSlots().size() <= toIndex) { + toFigure.createInputSlot(); + } + InputSlot inputSlot = toFigure.getInputSlots().get(toIndex); + + Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel()); + + if (e.getState() == InputEdge.State.NEW) { + c.setStyle(Connection.ConnectionStyle.BOLD); + } else if (e.getState() == InputEdge.State.DELETED) { + c.setStyle(Connection.ConnectionStyle.DASHED); + } + } + + + return d; + } + + public void removeAllFigures(Set<Figure> figuresToRemove) { + for (Figure f : figuresToRemove) { + freeFigure(f); + } + + ArrayList<Figure> newFigures = new ArrayList<>(); + for (Figure f : this.figures) { + if (!figuresToRemove.contains(f)) { + newFigures.add(f); + } + } + figures = newFigures; + } + + private void freeFigure(Figure succ) { + + List<InputSlot> inputSlots = new ArrayList<>(succ.getInputSlots()); + for (InputSlot s : inputSlots) { + succ.removeInputSlot(s); + } + + List<OutputSlot> outputSlots = new ArrayList<>(succ.getOutputSlots()); + for (OutputSlot s : outputSlots) { + succ.removeOutputSlot(s); + } + + assert succ.getInputSlots().size() == 0; + assert succ.getOutputSlots().size() == 0; + assert succ.getPredecessors().size() == 0; + assert succ.getSuccessors().size() == 0; + + } + + public void removeFigure(Figure succ) { + + assert this.figures.contains(succ); + freeFigure(succ); + this.figures.remove(succ); + } + + public String getName() { + return graph.getName(); + } + + public InputGraph getGraph() { + return graph; + } + + public Set<Connection> getConnections() { + + Set<Connection> connections = new HashSet<>(); + for (Figure f : figures) { + + for (InputSlot s : f.getInputSlots()) { + connections.addAll(s.getConnections()); + } + } + + return connections; + } + + public Figure getRootFigure() { + Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(figures); + Figure root = selector.selectSingle(new StringPropertyMatcher("name", "Root")); + if (root == null) { + root = selector.selectSingle(new StringPropertyMatcher("name", "Start")); + } + if (root == null) { + List<Figure> rootFigures = getRootFigures(); + if (rootFigures.size() > 0) { + root = rootFigures.get(0); + } else if (figures.size() > 0) { + root = figures.get(0); + } + } + + return root; + } + + public void printStatistics() { + System.out.println("============================================================="); + System.out.println("Diagram statistics"); + + List<Figure> tmpFigures = getFigures(); + Set<Connection> connections = getConnections(); + + System.out.println("Number of figures: " + tmpFigures.size()); + System.out.println("Number of connections: " + connections.size()); + + List<Figure> figuresSorted = new ArrayList<>(tmpFigures); + Collections.sort(figuresSorted, new Comparator<Figure>() { + + @Override + public int compare(Figure a, Figure b) { + return b.getPredecessors().size() + b.getSuccessors().size() - a.getPredecessors().size() - a.getSuccessors().size(); + } + }); + + final int COUNT = 10; + int z = 0; + for (Figure f : figuresSorted) { + + z++; + int sum = f.getPredecessors().size() + f.getSuccessors().size(); + System.out.println("#" + z + ": " + f + ", predCount=" + f.getPredecessors().size() + " succCount=" + f.getSuccessors().size()); + if (sum < COUNT) { + break; + } + + } + + System.out.println("============================================================="); + } + + public List<Figure> getRootFigures() { + ArrayList<Figure> rootFigures = new ArrayList<>(); + for (Figure f : figures) { + if (f.getPredecessors().size() == 0) { + rootFigures.add(f); + } + } + return rootFigures; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import com.sun.hotspot.igv.data.InputNode; +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Source; +import com.sun.hotspot.igv.layout.Vertex; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.List; +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class Figure extends Properties.Entity implements Source.Provider, Vertex { + + public static final int INSET = 12; + public static int SLOT_WIDTH = 12; + public static final int OVERLAPPING = 6; + public static final int SLOT_START = 4; + public static final int SLOT_OFFSET = 8; + public static final boolean VERTICAL_LAYOUT = true; + protected List<InputSlot> inputSlots; + protected List<OutputSlot> outputSlots; + private Source source; + private Diagram diagram; + private Point position; + private List<Figure> predecessors; + private List<Figure> successors; + private Color color; + private int id; + private String idString; + private String[] lines; + private int heightCash = -1; + private int widthCash = -1; + + public int getHeight() { + if (heightCash == -1) { + BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + Graphics g = image.getGraphics(); + g.setFont(diagram.getFont().deriveFont(Font.BOLD)); + FontMetrics metrics = g.getFontMetrics(); + String nodeText = diagram.getNodeText(); + heightCash = nodeText.split("\n").length * metrics.getHeight() + INSET; + } + return heightCash; + } + + public static <T> List<T> getAllBefore(List<T> inputList, T tIn) { + List<T> result = new ArrayList<>(); + for(T t : inputList) { + if(t.equals(tIn)) { + break; + } + result.add(t); + } + return result; + } + + public static int getSlotsWidth(Collection<? extends Slot> slots) { + int result = Figure.SLOT_OFFSET; + for(Slot s : slots) { + result += s.getWidth() + Figure.SLOT_OFFSET; + } + return result; + } + + public int getWidth() { + if (widthCash == -1) { + int max = 0; + BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + Graphics g = image.getGraphics(); + g.setFont(diagram.getFont().deriveFont(Font.BOLD)); + FontMetrics metrics = g.getFontMetrics(); + for (String s : getLines()) { + int cur = metrics.stringWidth(s); + if (cur > max) { + max = cur; + } + } + widthCash = max + INSET; + widthCash = Math.max(widthCash, Figure.getSlotsWidth(inputSlots)); + widthCash = Math.max(widthCash, Figure.getSlotsWidth(outputSlots)); + } + return widthCash; + } + + protected Figure(Diagram diagram, int id) { + this.diagram = diagram; + this.source = new Source(); + inputSlots = new ArrayList<>(5); + outputSlots = new ArrayList<>(1); + predecessors = new ArrayList<>(6); + successors = new ArrayList<>(6); + this.id = id; + idString = Integer.toString(id); + + this.position = new Point(0, 0); + this.color = Color.WHITE; + } + + public int getId() { + return id; + } + + public void setColor(Color color) { + this.color = color; + } + + public Color getColor() { + return color; + } + + public List<Figure> getPredecessors() { + return Collections.unmodifiableList(predecessors); + } + + public Set<Figure> getPredecessorSet() { + Set<Figure> result = new HashSet<>(); + for (Figure f : getPredecessors()) { + result.add(f); + } + return Collections.unmodifiableSet(result); + } + + public Set<Figure> getSuccessorSet() { + Set<Figure> result = new HashSet<>(); + for (Figure f : getSuccessors()) { + result.add(f); + } + return Collections.unmodifiableSet(result); + } + + public List<Figure> getSuccessors() { + return Collections.unmodifiableList(successors); + } + + protected void addPredecessor(Figure f) { + this.predecessors.add(f); + } + + protected void addSuccessor(Figure f) { + this.successors.add(f); + } + + protected void removePredecessor(Figure f) { + assert predecessors.contains(f); + predecessors.remove(f); + } + + protected void removeSuccessor(Figure f) { + assert successors.contains(f); + successors.remove(f); + } + + @Override + public void setPosition(Point p) { + this.position = p; + } + + @Override + public Point getPosition() { + return position; + } + + public Diagram getDiagram() { + return diagram; + } + + @Override + public Source getSource() { + return source; + } + + public InputSlot createInputSlot() { + InputSlot slot = new InputSlot(this, -1); + inputSlots.add(slot); + return slot; + } + + public InputSlot createInputSlot(int index) { + InputSlot slot = new InputSlot(this, index); + inputSlots.add(slot); + Collections.sort(inputSlots, Slot.slotIndexComparator); + return slot; + } + + public void removeSlot(Slot s) { + + assert inputSlots.contains(s) || outputSlots.contains(s); + + List<Connection> connections = new ArrayList<>(s.getConnections()); + for (Connection c : connections) { + c.remove(); + } + + if (inputSlots.contains(s)) { + inputSlots.remove(s); + } else if (outputSlots.contains(s)) { + outputSlots.remove(s); + } + } + + public OutputSlot createOutputSlot() { + OutputSlot slot = new OutputSlot(this, -1); + outputSlots.add(slot); + return slot; + } + + public OutputSlot createOutputSlot(int index) { + OutputSlot slot = new OutputSlot(this, index); + outputSlots.add(slot); + Collections.sort(outputSlots, Slot.slotIndexComparator); + return slot; + } + + public List<InputSlot> getInputSlots() { + return Collections.unmodifiableList(inputSlots); + } + + public Set<Slot> getSlots() { + Set<Slot> result = new HashSet<>(); + result.addAll(getInputSlots()); + result.addAll(getOutputSlots()); + return result; + } + + public List<OutputSlot> getOutputSlots() { + return Collections.unmodifiableList(outputSlots); + } + + void removeInputSlot(InputSlot s) { + s.removeAllConnections(); + inputSlots.remove(s); + } + + void removeOutputSlot(OutputSlot s) { + s.removeAllConnections(); + outputSlots.remove(s); + } + + public String[] getLines() { + if (lines == null) { + updateLines(); + } + return lines; + } + + public void updateLines() { + String[] strings = diagram.getNodeText().split("\n"); + String[] result = new String[strings.length]; + + for (int i = 0; i < strings.length; i++) { + result[i] = resolveString(strings[i], getProperties()); + } + + lines = result; + } + + public static final String resolveString(String string, Properties properties) { + + StringBuilder sb = new StringBuilder(); + boolean inBrackets = false; + StringBuilder curIdent = new StringBuilder(); + + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (inBrackets) { + if (c == ']') { + String value = properties.get(curIdent.toString()); + if (value == null) { + value = ""; + } + sb.append(value); + inBrackets = false; + } else { + curIdent.append(c); + } + } else { + if (c == '[') { + inBrackets = true; + curIdent = new StringBuilder(); + } else { + sb.append(c); + } + } + } + + return sb.toString(); + } + + @Override + public Dimension getSize() { + if (VERTICAL_LAYOUT) { + int width = Math.max(getWidth(), Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1)); + int height = getHeight() + 2 * Figure.SLOT_WIDTH - 2 * Figure.OVERLAPPING; + + + return new Dimension(width, height); + } else { + int width = getWidth() + 2 * Figure.SLOT_WIDTH - 2*Figure.OVERLAPPING; + int height = Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1); + return new Dimension(width, height); + } + } + + @Override + public String toString() { + return idString; + } + + @Override + public boolean isRoot() { + + List<InputNode> sourceNodes = source.getSourceNodes(); + if (sourceNodes.size() > 0 && sourceNodes.get(0).getProperties().get("name") != null) { + return source.getSourceNodes().get(0).getProperties().get("name").equals("Root"); + } else { + return false; + } + } + + @Override + public int compareTo(Vertex f) { + return toString().compareTo(f.toString()); + } + + public Rectangle getBounds() { + return new Rectangle(this.getPosition(), new Dimension(this.getWidth(), this.getHeight())); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.awt.Point; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputSlot extends Slot { + + protected InputSlot(Figure figure, int wantedIndex) { + super(figure, wantedIndex); + } + + @Override + public int getPosition() { + return getFigure().getInputSlots().indexOf(this); + } + + @Override + public void setPosition(int position) { + List<InputSlot> inputSlots = getFigure().inputSlots; + InputSlot s = inputSlots.remove(position); + inputSlots.add(position, s); + } + @Override + public Point getRelativePosition() { + int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getInputSlots()); + double gapRatio = (double)gap / (double)(getFigure().getInputSlots().size() + 1); + int gapAmount = (int)((getPosition() + 1)*gapRatio); + return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getInputSlots(), this)) + getWidth()/2, -Figure.SLOT_START); + //return new Point((getFigure().getWidth() / (getFigure().getInputSlots().size() * 2)) * (getPosition() * 2 + 1), -Figure.SLOT_START); + } + + @Override + public String toString() { + return "InputSlot[figure=" + this.getFigure().toString() + ", position=" + getPosition() + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class InvertSelector implements Selector { + + private Selector selector; + + public InvertSelector(Selector selector) { + this.selector = selector; + } + + @Override + public List<Figure> selected(Diagram d) { + + List<Figure> result = new ArrayList<>(); + List<Figure> otherResult = selector.selected(d); + for (Figure f : d.getFigures()) { + if (!otherResult.contains(f)) { + result.add(f); + } + } + + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Properties.PropertyMatcher; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class MatcherSelector implements Selector { + + private PropertyMatcher matcher; + + public MatcherSelector(PropertyMatcher matcher) { + this.matcher = matcher; + } + + @Override + public List<Figure> selected(Diagram d) { + Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(d.getFigures()); + List<Figure> list = selector.selectMultiple(matcher); + return list; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class OrSelector implements Selector { + + private Selector selector1; + private Selector selector2; + + /** Creates a new instance of OrSelector */ + public OrSelector(Selector s1, Selector s2) { + this.selector1 = s1; + this.selector2 = s2; + } + + @Override + public List<Figure> selected(Diagram d) { + + List<Figure> l1 = selector1.selected(d); + List<Figure> l2 = selector2.selected(d); + + for (Figure f : l2) { + if (!l1.contains(f)) { + l1.add(f); + } + } + + return l1; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.awt.Point; + +/** + * + * @author Thomas Wuerthinger + */ +public class OutputSlot extends Slot { + + protected OutputSlot(Figure figure, int wantedIndex) { + super(figure, wantedIndex); + } + + @Override + public int getPosition() { + return getFigure().getOutputSlots().indexOf(this); + } + + @Override + public void setPosition(int position) { + OutputSlot s = getFigure().outputSlots.remove(position); + getFigure().outputSlots.add(position, s); + } + + @Override + public Point getRelativePosition() { + int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getOutputSlots()); + if(gap < 0) { + gap = 0; + } + double gapRatio = (double)gap / (double)(getFigure().getOutputSlots().size() + 1); + int gapAmount = (int)((getPosition() + 1)*gapRatio); + return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getOutputSlots(), this)) + getWidth()/2, Figure.SLOT_START); + } + + @Override + public String toString() { + return "OutputSlot[figure=" + this.getFigure().toString() + ", position=" + getPosition() + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class PredecessorSelector implements Selector { + + private Selector innerSelector; + + public PredecessorSelector(Selector innerSelector) { + this.innerSelector = innerSelector; + } + + @Override + public List<Figure> selected(Diagram d) { + List<Figure> inner = innerSelector.selected(d); + List<Figure> result = new ArrayList<>(); + for (Figure f : d.getFigures()) { + boolean saved = false; + for (Figure f2 : f.getSuccessors()) { + if (inner.contains(f2)) { + saved = true; + } + } + + if (saved) { + result.add(f); + } + } + + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public interface Selector { + + List<Figure> selected(Diagram d); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import com.sun.hotspot.igv.data.InputNode; +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Source; +import com.sun.hotspot.igv.layout.Port; +import com.sun.hotspot.igv.layout.Vertex; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public abstract class Slot implements Port, Source.Provider, Properties.Provider { + + private int wantedIndex; + private Source source; + protected List<Connection> connections; + private InputNode associatedNode; + private Color color; + private String text; + private String shortName; + private Figure figure; + + protected Slot(Figure figure, int wantedIndex) { + this.figure = figure; + connections = new ArrayList<>(2); + source = new Source(); + this.wantedIndex = wantedIndex; + text = ""; + shortName = ""; + assert figure != null; + } + + @Override + public Properties getProperties() { + Properties p = new Properties(); + if (source.getSourceNodes().size() > 0) { + for (InputNode n : source.getSourceNodes()) { + p.add(n.getProperties()); + } + } else { + p.setProperty("name", "Slot"); + p.setProperty("figure", figure.getProperties().get("name")); + p.setProperty("connectionCount", Integer.toString(connections.size())); + } + return p; + } + public static final Comparator<Slot> slotIndexComparator = new Comparator<Slot>() { + + @Override + public int compare(Slot o1, Slot o2) { + return o1.wantedIndex - o2.wantedIndex; + } + }; + public static final Comparator<Slot> slotFigureComparator = new Comparator<Slot>() { + + @Override + public int compare(Slot o1, Slot o2) { + return o1.figure.getId() - o2.figure.getId(); + } + }; + + public InputNode getAssociatedNode() { + return associatedNode; + } + + public void setAssociatedNode(InputNode node) { + associatedNode = node; + } + + public int getWidth() { + if (shortName == null || shortName.length() <= 1) { + return Figure.SLOT_WIDTH; + } else { + BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + Graphics g = image.getGraphics(); + g.setFont(figure.getDiagram().getSlotFont().deriveFont(Font.BOLD)); + FontMetrics metrics = g.getFontMetrics(); + return Math.max(Figure.SLOT_WIDTH, metrics.stringWidth(shortName) + 6); + } + } + + public int getWantedIndex() { + return wantedIndex; + } + + @Override + public Source getSource() { + return source; + } + + public String getText() { + return text; + } + + public void setShortName(String s) { + assert s != null; +// assert s.length() <= 2; + this.shortName = s; + + } + + public String getShortName() { + return shortName; + } + + public String getToolTipText() { + StringBuilder sb = new StringBuilder(); + sb.append(text); + + for (InputNode n : getSource().getSourceNodes()) { + sb.append("Node (ID=" + n.getId() + "): " + n.getProperties().get("name")); + sb.append("<br>"); + } + + return sb.toString(); + } + + public boolean shouldShowName() { + return getShortName() != null && getShortName().length() > 0; + } + + public void setText(String s) { + if (s == null) { + s = ""; + } + this.text = s; + } + + public Figure getFigure() { + assert figure != null; + return figure; + } + + public Color getColor() { + return this.color; + } + + public void setColor(Color c) { + color = c; + } + + public List<Connection> getConnections() { + return Collections.unmodifiableList(connections); + } + + public void removeAllConnections() { + List<Connection> connectionsCopy = new ArrayList<>(this.connections); + for (Connection c : connectionsCopy) { + c.remove(); + } + } + + @Override + public Vertex getVertex() { + return figure; + } + + public abstract int getPosition(); + + public abstract void setPosition(int position); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class SuccessorSelector implements Selector { + + private Selector innerSelector; + + public SuccessorSelector(Selector innerSelector) { + this.innerSelector = innerSelector; + } + + @Override + public List<Figure> selected(Diagram d) { + List<Figure> inner = innerSelector.selected(d); + List<Figure> result = new ArrayList<>(); + for (Figure f : d.getFigures()) { + boolean saved = false; + for (Figure f2 : f.getPredecessors()) { + if (inner.contains(f2)) { + saved = true; + } + } + + if (saved) { + result.add(f); + } + } + + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Graph/src/com/sun/hotspot/igv/graph/services/DiagramProvider.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.graph.services; + +import com.sun.hotspot.igv.data.ChangedEvent; +import com.sun.hotspot.igv.graph.Diagram; + +/** + * + * @author Thomas Wuerthinger + */ +public interface DiagramProvider { + Diagram getDiagram(); + ChangedEvent<DiagramProvider> getChangedEvent(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.hierarchicallayout" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.hierarchicallayout.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.hierarchicallayout +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/hierarchicallayout/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.hierarchicallayout-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=de087df9 +build.xml.script.CRC32=98977c36 +build.xml.stylesheet.CRC32=79c3b980 +# 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=de087df9 +nbproject/build-impl.xml.script.CRC32=0d734625 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.hierarchicallayout</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.sun.hotspot.igv.hierarchicallayout</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=HierarchicalLayout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.hierarchicallayout; + +/** + * + * @author Thomas Wuerthinger + */ +public class Edge<N, E> { + + private E data; + private Node<N, E> source; + private Node<N, E> dest; + + protected Edge(Graph<N, E> graph, Node<N, E> source, Node<N, E> dest, E data) { + setData(data); + this.source = source; + this.dest = dest; + assert source != null; + assert dest != null; + assert source.getGraph() == dest.getGraph(); + assert source.getGraph() != null; + assert dest.getGraph() != null; + } + + public Node<N, E> getSource() { + return source; + } + + public Node<N, E> getDest() { + return dest; + } + + public E getData() { + return data; + } + + public void setData(E e) { + data = e; + } + + public void remove() { + source.getGraph().removeEdge(this, null); + } + + public boolean isSelfLoop() { + return source == dest; + } + + public void reverse() { + + // Remove from current source / dest + source.removeOutEdge(this); + dest.removeInEdge(this); + + Node<N, E> tmp = source; + source = dest; + dest = tmp; + + // Add to new source / dest + source.addOutEdge(this); + dest.addInEdge(this); + } + + @Override + public String toString() { + return "Edge (" + source + " -- " + dest + "): " + data; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.hierarchicallayout; + +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class Graph<N, E> { + + private HashMap<Object, Node<N, E>> nodes; + private HashMap<Object, Edge<N, E>> edges; + private List<Node<N, E>> nodeList; + + public Graph() { + nodes = new HashMap<>(); + edges = new HashMap<>(); + nodeList = new ArrayList<>(); + } + + public Node<N, E> createNode(N data, Object key) { + Node<N, E> n = new Node<>(this, data); + assert key == null || !nodes.containsKey(key); + if (key != null) { + nodes.put(key, n); + } + nodeList.add(n); + return n; + } + + public Edge<N, E> createEdge(Node<N, E> source, Node<N, E> dest, E data, Object key) { + Edge<N, E> e = new Edge<>(this, source, dest, data); + source.addOutEdge(e); + dest.addInEdge(e); + if (key != null) { + edges.put(key, e); + } + return e; + } + + public Node<N, E> getNode(Object key) { + return nodes.get(key); + } + + public Edge<N, E> getEdge(Object key) { + return edges.get(key); + } + + public Collection<Edge<N, E>> getEdges() { + return Collections.unmodifiableCollection(edges.values()); + } + + public Collection<Node<N, E>> getNodes() { + return Collections.unmodifiableList(nodeList); + } + + public void removeEdge(Edge<N, E> e, Object key) { + assert key == null || edges.containsKey(key); + if (key != null) { + edges.remove(key); + } + e.getSource().removeOutEdge(e); + e.getDest().removeInEdge(e); + } + + public class DFSTraversalVisitor { + + public void visitNode(Node<N, E> n) { + } + + public boolean visitEdge(Edge<N, E> e, boolean backEdge) { + return true; + } + } + + public class BFSTraversalVisitor { + + public void visitNode(Node<N, E> n, int depth) { + } + } + + public List<Node<N, E>> getNodesWithInDegree(int x) { + return getNodesWithInDegree(x, true); + } + + public List<Node<N, E>> getNodesWithInDegree(int x, boolean countSelfLoops) { + + List<Node<N, E>> result = new ArrayList<>(); + for (Node<N, E> n : getNodes()) { + if (n.getInDegree(countSelfLoops) == x) { + result.add(n); + } + } + + return result; + + } + + private void markReachable(Node<N, E> startingNode) { + ArrayList<Node<N, E>> arr = new ArrayList<>(); + arr.add(startingNode); + for (Node<N, E> n : getNodes()) { + n.setReachable(false); + } + traverseDFS(arr, new DFSTraversalVisitor() { + + @Override + public void visitNode(Node<N, E> n) { + n.setReachable(true); + } + }); + } + + public void traverseBFS(Node<N, E> startingNode, BFSTraversalVisitor tv, boolean longestPath) { + + if (longestPath) { + markReachable(startingNode); + } + + for (Node<N, E> n : getNodes()) { + n.setVisited(false); + n.setActive(false); + } + + Queue<Node<N, E>> queue = new LinkedList<>(); + queue.add(startingNode); + startingNode.setVisited(true); + int layer = 0; + Node<N, E> lastOfLayer = startingNode; + Node<N, E> lastAdded = null; + + while (!queue.isEmpty()) { + + Node<N, E> current = queue.poll(); + tv.visitNode(current, layer); + current.setActive(false); + + + for (Edge<N, E> e : current.getOutEdges()) { + if (!e.getDest().isVisited()) { + + boolean allow = true; + if (longestPath) { + for (Node<N, E> pred : e.getDest().getPredecessors()) { + if ((!pred.isVisited() || pred.isActive()) && pred.isReachable()) { + allow = false; + break; + } + } + } + + if (allow) { + queue.offer(e.getDest()); + lastAdded = e.getDest(); + e.getDest().setVisited(true); + e.getDest().setActive(true); + } + } + } + + if (current == lastOfLayer && !queue.isEmpty()) { + lastOfLayer = lastAdded; + layer++; + } + } + } + + public void traverseDFS(DFSTraversalVisitor tv) { + traverseDFS(getNodes(), tv); + } + + public void traverseDFS(Collection<Node<N, E>> startingNodes, DFSTraversalVisitor tv) { + + for (Node<N, E> n : getNodes()) { + n.setVisited(false); + n.setActive(false); + } + + boolean result = false; + for (Node<N, E> n : startingNodes) { + traverse(tv, n); + } + } + + private void traverse(DFSTraversalVisitor tv, Node<N, E> n) { + + if (!n.isVisited()) { + n.setVisited(true); + n.setActive(true); + tv.visitNode(n); + + for (Edge<N, E> e : n.getOutEdges()) { + + Node<N, E> next = e.getDest(); + if (next.isActive()) { + tv.visitEdge(e, true); + } else { + if (tv.visitEdge(e, false)) { + traverse(tv, next); + } + } + } + + n.setActive(false); + } + + } + + public boolean hasCycles() { + + for (Node<N, E> n : getNodes()) { + n.setVisited(false); + n.setActive(false); + } + + boolean result = false; + for (Node<N, E> n : getNodes()) { + result |= checkCycles(n); + if (result) { + break; + } + } + return result; + } + + private boolean checkCycles(Node<N, E> n) { + + if (n.isActive()) { + return true; + } + + if (!n.isVisited()) { + + n.setVisited(true); + n.setActive(true); + + for (Node<N, E> succ : n.getSuccessors()) { + if (checkCycles(succ)) { + return true; + } + } + + n.setActive(false); + + } + + return false; + } + + @Override + public String toString() { + + StringBuilder s = new StringBuilder(); + s.append("Nodes: "); + for (Node<N, E> n : getNodes()) { + s.append(n.toString()); + s.append("\n"); + } + + s.append("Edges: "); + + for (Edge<N, E> e : getEdges()) { + s.append(e.toString()); + s.append("\n"); + } + + return s.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1749 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.hierarchicallayout; + +import com.sun.hotspot.igv.layout.LayoutGraph; +import com.sun.hotspot.igv.layout.LayoutManager; +import com.sun.hotspot.igv.layout.Link; +import com.sun.hotspot.igv.layout.Vertex; +import java.awt.Dimension; +import java.awt.Point; +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class HierarchicalLayoutManager implements LayoutManager { + + public static final boolean TRACE = false; + public static final boolean CHECK = false; + public static final int SWEEP_ITERATIONS = 1; + public static final int CROSSING_ITERATIONS = 2; + public static final int DUMMY_HEIGHT = 1; + public static final int DUMMY_WIDTH = 1; + public static final int X_OFFSET = 9; + public static final int LAYER_OFFSET = 30; + public static final int MAX_LAYER_LENGTH = -1; + public static final int MIN_LAYER_DIFFERENCE = 1; + public static final int VIP_BONUS = 10; + + public enum Combine { + + NONE, + SAME_INPUTS, + SAME_OUTPUTS + } + // Options + private Combine combine; + private int dummyWidth; + private int dummyHeight; + private int xOffset; + private int layerOffset; + private int maxLayerLength; + private int minLayerDifference; + // Algorithm global datastructures + private Set<Link> reversedLinks; + private List<LayoutNode> nodes; + private HashMap<Vertex, LayoutNode> vertexToLayoutNode; + private HashMap<Link, List<Point>> reversedLinkStartPoints; + private HashMap<Link, List<Point>> reversedLinkEndPoints; + private HashMap<LayoutEdge, LayoutEdge> bottomEdgeHash; + private HashMap<Link, List<Point>> splitStartPoints; + private HashMap<Link, List<Point>> splitEndPoints; + private LayoutGraph graph; + private List<LayoutNode>[] layers; + private int layerCount; + private Set<? extends Vertex> firstLayerHint; + private Set<? extends Vertex> lastLayerHint; + private Set<? extends Link> importantLinks; + private Set<Link> linksToFollow; + + private class LayoutNode { + + public int x; + public int y; + public int width; + public int height; + public int layer = -1; + public int xOffset; + public int yOffset; + public int bottomYOffset; + public Vertex vertex; // Only used for non-dummy nodes, otherwise null + + public List<LayoutEdge> preds = new ArrayList<>(); + public List<LayoutEdge> succs = new ArrayList<>(); + public HashMap<Integer, Integer> outOffsets = new HashMap<>(); + public HashMap<Integer, Integer> inOffsets = new HashMap<>(); + public int pos = -1; // Position within layer + + public int crossingNumber; + + @Override + public String toString() { + return "Node " + vertex; + } + } + + private class LayoutEdge { + + public LayoutNode from; + public LayoutNode to; + public int relativeFrom; + public int relativeTo; + public Link link; + public boolean vip; + } + + private abstract class AlgorithmPart { + + public void start() { + if (CHECK) { + preCheck(); + } + + long start = 0; + if (TRACE) { + System.out.println("##################################################"); + System.out.println("Starting part " + this.getClass().getName()); + start = System.currentTimeMillis(); + } + run(); + if (TRACE) { + System.out.println("Timing for " + this.getClass().getName() + " is " + (System.currentTimeMillis() - start)); + printStatistics(); + } + + if (CHECK) { + postCheck(); + } + } + + protected abstract void run(); + + protected void printStatistics() { + } + + protected void postCheck() { + } + + protected void preCheck() { + } + } + + public HierarchicalLayoutManager() { + this(Combine.NONE); + } + + public HierarchicalLayoutManager(Combine b) { + this.combine = b; + this.dummyWidth = DUMMY_WIDTH; + this.dummyHeight = DUMMY_HEIGHT; + this.xOffset = X_OFFSET; + this.layerOffset = LAYER_OFFSET; + this.maxLayerLength = MAX_LAYER_LENGTH; + this.minLayerDifference = MIN_LAYER_DIFFERENCE; + this.linksToFollow = new HashSet<>(); + } + + public int getMaxLayerLength() { + return maxLayerLength; + } + + public void setMaxLayerLength(int v) { + maxLayerLength = v; + } + + public void setMinLayerDifference(int v) { + minLayerDifference = v; + } + + @Override + public void doLayout(LayoutGraph graph) { + doLayout(graph, new HashSet<Vertex>(), new HashSet<Vertex>(), new HashSet<Link>()); + + } + + @Override + public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks) { + + this.importantLinks = importantLinks; + this.graph = graph; + this.firstLayerHint = firstLayerHint; + this.lastLayerHint = lastLayerHint; + + vertexToLayoutNode = new HashMap<>(); + reversedLinks = new HashSet<>(); + reversedLinkStartPoints = new HashMap<>(); + reversedLinkEndPoints = new HashMap<>(); + bottomEdgeHash = new HashMap<>(); + nodes = new ArrayList<>(); + splitStartPoints = new HashMap<>(); + splitEndPoints = new HashMap<>(); + + // ############################################################# + // Step 1: Build up data structure + new BuildDatastructure().start(); + + // ############################################################# + // STEP 2: Reverse edges, handle backedges + new ReverseEdges().start(); + + for (LayoutNode n : nodes) { + ArrayList<LayoutEdge> tmpArr = new ArrayList<>(); + for (LayoutEdge e : n.succs) { + if (importantLinks.contains(e.link)) { + tmpArr.add(e); + } + } + + for (LayoutEdge e : tmpArr) { + //System.out.println("Removed " + e); + e.from.succs.remove(e); + e.to.preds.remove(e); + } + } + + // ############################################################# + // STEP 3: Assign layers + new AssignLayers().start(); + + // ############################################################# + // STEP 4: Create dummy nodes + new CreateDummyNodes().start(); + + // ############################################################# + // STEP 5: Crossing Reduction + new CrossingReduction().start(); + + // ############################################################# + // STEP 7: Assign X coordinates + new AssignXCoordinates().start(); + + // ############################################################# + // STEP 6: Assign Y coordinates + new AssignYCoordinates().start(); + + // ############################################################# + // STEP 8: Write back to interface + new WriteResult().start(); + } + + private class WriteResult extends AlgorithmPart { + + private int pointCount; + + @Override + protected void run() { + + HashMap<Vertex, Point> vertexPositions = new HashMap<>(); + HashMap<Link, List<Point>> linkPositions = new HashMap<>(); + for (Vertex v : graph.getVertices()) { + LayoutNode n = vertexToLayoutNode.get(v); + assert !vertexPositions.containsKey(v); + vertexPositions.put(v, new Point(n.x + n.xOffset, n.y + n.yOffset)); + } + + for (LayoutNode n : nodes) { + + for (LayoutEdge e : n.preds) { + if (e.link != null) { + ArrayList<Point> points = new ArrayList<>(); + + Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset + e.link.getTo().getRelativePosition().y); + points.add(p); + if (e.to.inOffsets.containsKey(e.relativeTo)) { + points.add(new Point(p.x, p.y + e.to.inOffsets.get(e.relativeTo) + e.link.getTo().getRelativePosition().y)); + } + + LayoutNode cur = e.from; + LayoutNode other = e.to; + LayoutEdge curEdge = e; + while (cur.vertex == null && cur.preds.size() != 0) { + if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { + points.remove(points.size() - 1); + } + points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height)); + if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { + points.remove(points.size() - 1); + } + points.add(new Point(cur.x + cur.width / 2, cur.y)); + assert cur.preds.size() == 1; + curEdge = cur.preds.get(0); + cur = curEdge.from; + } + + p = new Point(cur.x + curEdge.relativeFrom, cur.y + cur.height - cur.bottomYOffset + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y)); + if (curEdge.from.outOffsets.containsKey(curEdge.relativeFrom)) { + points.add(new Point(p.x, p.y + curEdge.from.outOffsets.get(curEdge.relativeFrom) + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y))); + } + points.add(p); + + Collections.reverse(points); + + + + if (cur.vertex == null && cur.preds.size() == 0) { + + if (reversedLinkEndPoints.containsKey(e.link)) { + for (Point p1 : reversedLinkEndPoints.get(e.link)) { + points.add(new Point(p1.x + e.to.x, p1.y + e.to.y)); + } + } + + if (splitStartPoints.containsKey(e.link)) { + points.add(0, null); + points.addAll(0, splitStartPoints.get(e.link)); + + //checkPoints(points); + if (reversedLinks.contains(e.link)) { + Collections.reverse(points); + } + assert !linkPositions.containsKey(e.link); + linkPositions.put(e.link, points); + } else { + splitEndPoints.put(e.link, points); + } + + } else { + if (reversedLinks.contains(e.link)) { + Collections.reverse(points); + } + if (reversedLinkStartPoints.containsKey(e.link)) { + for (Point p1 : reversedLinkStartPoints.get(e.link)) { + points.add(new Point(p1.x + cur.x, p1.y + cur.y)); + } + } + + if (reversedLinkEndPoints.containsKey(e.link)) { + for (Point p1 : reversedLinkEndPoints.get(e.link)) { + points.add(0, new Point(p1.x + other.x, p1.y + other.y)); + } + } + + assert !linkPositions.containsKey(e.link); + linkPositions.put(e.link, points); + } + pointCount += points.size(); + + // No longer needed! + e.link = null; + } + } + + for (LayoutEdge e : n.succs) { + if (e.link != null) { + ArrayList<Point> points = new ArrayList<>(); + Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset + e.link.getFrom().getRelativePosition().y); + points.add(p); + if (e.from.outOffsets.containsKey(e.relativeFrom)) { + points.add(new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom) + e.link.getFrom().getRelativePosition().y)); + } + + LayoutNode cur = e.to; + LayoutNode other = e.from; + LayoutEdge curEdge = e; + while (cur.vertex == null && cur.succs.size() != 0) { + if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { + points.remove(points.size() - 1); + } + points.add(new Point(cur.x + cur.width / 2, cur.y)); + if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { + points.remove(points.size() - 1); + } + points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height)); + if (cur.succs.size() == 0) { + break; + } + assert cur.succs.size() == 1; + curEdge = cur.succs.get(0); + cur = curEdge.to; + } + + + p = new Point(cur.x + curEdge.relativeTo, cur.y + cur.yOffset + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y)); + points.add(p); + if (curEdge.to.inOffsets.containsKey(curEdge.relativeTo)) { + points.add(new Point(p.x, p.y + curEdge.to.inOffsets.get(curEdge.relativeTo) + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y))); + } + + + if (cur.succs.size() == 0 && cur.vertex == null) { + if (reversedLinkStartPoints.containsKey(e.link)) { + for (Point p1 : reversedLinkStartPoints.get(e.link)) { + points.add(0, new Point(p1.x + other.x, p1.y + other.y)); + } + } + + if (splitEndPoints.containsKey(e.link)) { + points.add(null); + points.addAll(splitEndPoints.get(e.link)); + + //checkPoints(points); + if (reversedLinks.contains(e.link)) { + Collections.reverse(points); + } + assert !linkPositions.containsKey(e.link); + linkPositions.put(e.link, points); + } else { + splitStartPoints.put(e.link, points); + } + } else { + + if (reversedLinkStartPoints.containsKey(e.link)) { + for (Point p1 : reversedLinkStartPoints.get(e.link)) { + points.add(0, new Point(p1.x + other.x, p1.y + other.y)); + } + } + if (reversedLinkEndPoints.containsKey(e.link)) { + for (Point p1 : reversedLinkEndPoints.get(e.link)) { + points.add(new Point(p1.x + cur.x, p1.y + cur.y)); + } + } + if (reversedLinks.contains(e.link)) { + Collections.reverse(points); + } + //checkPoints(points); + assert !linkPositions.containsKey(e.link); + linkPositions.put(e.link, points); + } + + pointCount += points.size(); + e.link = null; + } + } + } + + int minX = Integer.MAX_VALUE; + int minY = Integer.MAX_VALUE; + for (Vertex v : vertexPositions.keySet()) { + Point p = vertexPositions.get(v); + minX = Math.min(minX, p.x); + minY = Math.min(minY, p.y); + } + + for (Link l : linkPositions.keySet()) { + List<Point> points = linkPositions.get(l); + for (Point p : points) { + if (p != null) { + minX = Math.min(minX, p.x); + minY = Math.min(minY, p.y); + } + } + + } + + for (Vertex v : vertexPositions.keySet()) { + Point p = vertexPositions.get(v); + p.x -= minX; + p.y -= minY; + v.setPosition(p); + } + + for (Link l : linkPositions.keySet()) { + List<Point> points = linkPositions.get(l); + for (Point p : points) { + if (p != null) { + p.x -= minX; + p.y -= minY; + } + } + l.setControlPoints(points); + + } + } + + @Override + protected void printStatistics() { + System.out.println("Number of nodes: " + nodes.size()); + int edgeCount = 0; + for (LayoutNode n : nodes) { + edgeCount += n.succs.size(); + } + System.out.println("Number of edges: " + edgeCount); + System.out.println("Number of points: " + pointCount); + } + } + + private static class Segment { + + public float d; + public int orderNumber = -1; + public ArrayList<LayoutNode> nodes = new ArrayList<>(); + public HashSet<Segment> succs = new HashSet<>(); + public HashSet<Segment> preds = new HashSet<>(); + public Region region; + } + private static final Comparator<Segment> segmentComparator = new Comparator<Segment>() { + + @Override + public int compare(Segment s1, Segment s2) { + return s1.orderNumber - s2.orderNumber; + } + }; + + private static class Region { + + public float d; + public int minOrderNumber; + public SortedSet<Segment> segments = new TreeSet<>(segmentComparator); + public HashSet<Region> succs = new HashSet<>(4); + public HashSet<Region> preds = new HashSet<>(4); + } + private static final Comparator<Region> regionComparator = new Comparator<Region>() { + + @Override + public int compare(Region r1, Region r2) { + return r1.minOrderNumber - r2.minOrderNumber; + } + }; + private static final Comparator<LayoutNode> nodePositionComparator = new Comparator<LayoutNode>() { + + @Override + public int compare(LayoutNode n1, LayoutNode n2) { + return n1.pos - n2.pos; + } + }; + private static final Comparator<LayoutNode> nodeProcessingDownComparator = new Comparator<LayoutNode>() { + @Override + public int compare(LayoutNode n1, LayoutNode n2) { + if (n1.vertex == null) { + if (n2.vertex == null) { + return 0; + } + return -1; + } + if (n2.vertex == null) { + return 1; + } + return n1.preds.size() - n2.preds.size(); + } + }; + private static final Comparator<LayoutNode> nodeProcessingUpComparator = new Comparator<LayoutNode>() { + + @Override + public int compare(LayoutNode n1, LayoutNode n2) { + if (n1.vertex == null) { + if (n2.vertex == null) { + return 0; + } + return -1; + } + if (n2.vertex == null) { + return 1; + } + return n1.succs.size() - n2.succs.size(); + } + }; + + private class AssignXCoordinates extends AlgorithmPart { + + private ArrayList<Integer>[] space; + private ArrayList<LayoutNode>[] downProcessingOrder; + private ArrayList<LayoutNode>[] upProcessingOrder; + + private void initialPositions() { + for (LayoutNode n : nodes) { + n.x = space[n.layer].get(n.pos); + } + } + + @SuppressWarnings("unchecked") + private void createArrays() { + space = new ArrayList[layers.length]; + downProcessingOrder = new ArrayList[layers.length]; + upProcessingOrder = new ArrayList[layers.length]; + } + + @Override + protected void run() { + createArrays(); + + for (int i = 0; i < layers.length; i++) { + space[i] = new ArrayList<>(); + downProcessingOrder[i] = new ArrayList<>(); + upProcessingOrder[i] = new ArrayList<>(); + + int curX = 0; + for (LayoutNode n : layers[i]) { + space[i].add(curX); + curX += n.width + xOffset; + downProcessingOrder[i].add(n); + upProcessingOrder[i].add(n); + } + + Collections.sort(downProcessingOrder[i], nodeProcessingDownComparator); + Collections.sort(upProcessingOrder[i], nodeProcessingUpComparator); + } + + initialPositions(); + for (int i = 0; i < SWEEP_ITERATIONS; i++) { + sweepDown(); + sweepUp(); + } + + sweepDown(); + //for (int i = 0; i < SWEEP_ITERATIONS; i++) { + // doubleSweep(); + //} + } + + private int calculateOptimalDown(LayoutNode n) { + int size = n.preds.size(); + if (size == 0) { + return n.x; + } + int[] values = new int[size]; + for (int i = 0; i < size; i++) { + LayoutEdge e = n.preds.get(i); + values[i] = e.from.x + e.relativeFrom - e.relativeTo; + if (e.vip) { + return values[i]; + } + } + return median(values); + } + + private int calculateOptimalBoth(LayoutNode n) { + if (n.preds.size() == n.succs.size()) { + return n.x; + } + + int[] values = new int[n.preds.size() + n.succs.size()]; + int i = 0; + + for (LayoutEdge e : n.preds) { + values[i] = e.from.x + e.relativeFrom - e.relativeTo; + i++; + } + + for (LayoutEdge e : n.succs) { + values[i] = e.to.x + e.relativeTo - e.relativeFrom; + i++; + } + + return median(values); + } + + private int calculateOptimalUp(LayoutNode n) { + int size = n.succs.size(); + if (size == 0) { + return n.x; + } + int[] values = new int[size]; + for (int i = 0; i < size; i++) { + LayoutEdge e = n.succs.get(i); + values[i] = e.to.x + e.relativeTo - e.relativeFrom; + if (e.vip) { + return values[i]; + } + } + return median(values); + } + + private int median(int[] values) { + Arrays.sort(values); + if (values.length % 2 == 0) { + return (values[values.length / 2 - 1] + values[values.length / 2]) / 2; + } else { + return values[values.length / 2]; + } + } + + private void sweepUp() { + for (int i = layers.length - 1; i >= 0; i--) { + NodeRow r = new NodeRow(space[i]); + for (LayoutNode n : upProcessingOrder[i]) { + int optimal = calculateOptimalUp(n); + r.insert(n, optimal); + } + } + } + + private void doubleSweep() { + for (int i = layers.length - 2; i >= 0; i--) { + NodeRow r = new NodeRow(space[i]); + for (LayoutNode n : upProcessingOrder[i]) { + int optimal = calculateOptimalBoth(n); + r.insert(n, optimal); + } + } + } + + private void sweepDown() { + for (int i = 1; i < layers.length; i++) { + NodeRow r = new NodeRow(space[i]); + for (LayoutNode n : downProcessingOrder[i]) { + int optimal = calculateOptimalDown(n); + r.insert(n, optimal); + } + } + } + } + + private static class NodeRow { + + private TreeSet<LayoutNode> treeSet; + private ArrayList<Integer> space; + + public NodeRow(ArrayList<Integer> space) { + treeSet = new TreeSet<>(nodePositionComparator); + this.space = space; + } + + public int offset(LayoutNode n1, LayoutNode n2) { + int v1 = space.get(n1.pos) + n1.width; + int v2 = space.get(n2.pos); + return v2 - v1; + } + + public void insert(LayoutNode n, int pos) { + + SortedSet<LayoutNode> headSet = treeSet.headSet(n); + + LayoutNode leftNeighbor = null; + int minX = Integer.MIN_VALUE; + if (!headSet.isEmpty()) { + leftNeighbor = headSet.last(); + minX = leftNeighbor.x + leftNeighbor.width + offset(leftNeighbor, n); + } + + if (pos < minX) { + n.x = minX; + } else { + + LayoutNode rightNeighbor = null; + SortedSet<LayoutNode> tailSet = treeSet.tailSet(n); + int maxX = Integer.MAX_VALUE; + if (!tailSet.isEmpty()) { + rightNeighbor = tailSet.first(); + maxX = rightNeighbor.x - offset(n, rightNeighbor) - n.width; + } + + if (pos > maxX) { + n.x = maxX; + } else { + n.x = pos; + } + + assert minX <= maxX; + } + + treeSet.add(n); + } + } + private static Comparator<LayoutNode> crossingNodeComparator = new Comparator<LayoutNode>() { + + @Override + public int compare(LayoutNode n1, LayoutNode n2) { + return n1.crossingNumber - n2.crossingNumber; + } + }; + + private class CrossingReduction extends AlgorithmPart { + + @Override + public void preCheck() { + for (LayoutNode n : nodes) { + assert n.layer < layerCount; + } + } + + @SuppressWarnings("unchecked") + private void createLayers() { + layers = new List[layerCount]; + + for (int i = 0; i < layerCount; i++) { + layers[i] = new ArrayList<>(); + } + } + + @Override + protected void run() { + createLayers(); + + // Generate initial ordering + HashSet<LayoutNode> visited = new HashSet<>(); + for (LayoutNode n : nodes) { + if (n.layer == 0) { + layers[0].add(n); + visited.add(n); + } else if (n.preds.size() == 0) { + layers[n.layer].add(n); + visited.add(n); + } + } + + for (int i = 0; i < layers.length - 1; i++) { + for (LayoutNode n : layers[i]) { + for (LayoutEdge e : n.succs) { + if (!visited.contains(e.to)) { + visited.add(e.to); + layers[i + 1].add(e.to); + } + } + } + } + + + updatePositions(); + + initX(); + + // Optimize + for (int i = 0; i < CROSSING_ITERATIONS; i++) { + downSweep(); + upSweep(); + } + if (reversedLinks.isEmpty()) { + // This graph seems to be a tree or forest. + // A final down-sweep will usually give us a better layout. + downSweep(); + } + } + + private void initX() { + + for (int i = 0; i < layers.length; i++) { + updateXOfLayer(i); + } + } + + private void updateXOfLayer(int index) { + int x = 0; + + for (LayoutNode n : layers[index]) { + n.x = x; + x += n.width + X_OFFSET; + } + } + + private void updatePositions() { + + for (int i = 0; i < layers.length; i++) { + int z = 0; + for (LayoutNode n : layers[i]) { + n.pos = z; + z++; + } + } + } + + private void downSweep() { + + // Downsweep + for (int i = 1; i < layerCount; i++) { + + for (LayoutNode n : layers[i]) { + n.crossingNumber = 0; + } + + for (LayoutNode n : layers[i]) { + + int sum = 0; + int count = 0; + for (LayoutEdge e : n.preds) { + int cur = e.from.x + e.relativeFrom; + int factor = 1; + if (e.vip) { + factor = VIP_BONUS; + } + sum += cur*factor; + count+=factor; + } + + if (count > 0) { + sum /= count; + n.crossingNumber = sum; + } + } + + + updateCrossingNumbers(i, true); + Collections.sort(layers[i], crossingNodeComparator); + updateXOfLayer(i); + + int z = 0; + for (LayoutNode n : layers[i]) { + n.pos = z; + z++; + } + } + } + + private void updateCrossingNumbers(int index, boolean down) { + for (int i = 0; i < layers[index].size(); i++) { + LayoutNode n = layers[index].get(i); + LayoutNode prev = null; + if (i > 0) { + prev = layers[index].get(i - 1); + } + LayoutNode next = null; + if (i < layers[index].size() - 1) { + next = layers[index].get(i + 1); + } + + boolean cond = n.succs.isEmpty(); + if (down) { + cond = n.preds.isEmpty(); + } + + if (cond) { + + if (prev != null && next != null) { + n.crossingNumber = (prev.crossingNumber + next.crossingNumber) / 2; + } else if (prev != null) { + n.crossingNumber = prev.crossingNumber; + } else if (next != null) { + n.crossingNumber = next.crossingNumber; + } + } + } + } + + private void upSweep() { + // Upsweep + for (int i = layerCount - 2; i >= 0; i--) { + + for (LayoutNode n : layers[i]) { + n.crossingNumber = 0; + } + + for (LayoutNode n : layers[i]) { + + int count = 0; + int sum = 0; + for (LayoutEdge e : n.succs) { + int cur = e.to.x + e.relativeTo; + int factor = 1; + if (e.vip) { + factor = VIP_BONUS; + } + sum += cur*factor; + count+=factor; + } + + if (count > 0) { + sum /= count; + n.crossingNumber = sum; + } + + } + + updateCrossingNumbers(i, false); + Collections.sort(layers[i], crossingNodeComparator); + updateXOfLayer(i); + + int z = 0; + for (LayoutNode n : layers[i]) { + n.pos = z; + z++; + } + } + } + + @Override + public void postCheck() { + + HashSet<LayoutNode> visited = new HashSet<>(); + for (int i = 0; i < layers.length; i++) { + for (LayoutNode n : layers[i]) { + assert !visited.contains(n); + assert n.layer == i; + visited.add(n); + } + } + + } + } + + private class AssignYCoordinates extends AlgorithmPart { + + @Override + protected void run() { + int curY = 0; + + for (int i = 0; i < layers.length; i++) { + int maxHeight = 0; + int baseLine = 0; + int bottomBaseLine = 0; + for (LayoutNode n : layers[i]) { + maxHeight = Math.max(maxHeight, n.height - n.yOffset - n.bottomYOffset); + baseLine = Math.max(baseLine, n.yOffset); + bottomBaseLine = Math.max(bottomBaseLine, n.bottomYOffset); + } + + int maxXOffset = 0; + for (LayoutNode n : layers[i]) { + if (n.vertex == null) { + // Dummy node + n.y = curY; + n.height = maxHeight + baseLine + bottomBaseLine; + + } else { + n.y = curY + baseLine + (maxHeight - (n.height - n.yOffset - n.bottomYOffset)) / 2 - n.yOffset; + } + + for (LayoutEdge e : n.succs) { + int curXOffset = Math.abs(n.x - e.to.x); + maxXOffset = Math.max(curXOffset, maxXOffset); + } + } + + curY += maxHeight + baseLine + bottomBaseLine; + curY += layerOffset + (int) Math.sqrt(maxXOffset); + } + } + } + + private class CreateDummyNodes extends AlgorithmPart { + + private int oldNodeCount; + + @Override + protected void preCheck() { + for (LayoutNode n : nodes) { + for (LayoutEdge e : n.succs) { + assert e.from != null; + assert e.from == n; + assert e.from.layer < e.to.layer; + } + + for (LayoutEdge e : n.preds) { + assert e.to != null; + assert e.to == n; + } + } + } + + @Override + protected void run() { + oldNodeCount = nodes.size(); + + + if (combine == Combine.SAME_OUTPUTS) { + + Comparator<LayoutEdge> comparator = new Comparator<LayoutEdge>() { + + @Override + public int compare(LayoutEdge e1, LayoutEdge e2) { + return e1.to.layer - e2.to.layer; + } + }; + HashMap<Integer, List<LayoutEdge>> portHash = new HashMap<>(); + ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes); + for (LayoutNode n : currentNodes) { + portHash.clear(); + + ArrayList<LayoutEdge> succs = new ArrayList<>(n.succs); + HashMap<Integer, LayoutNode> topNodeHash = new HashMap<>(); + HashMap<Integer, HashMap<Integer, LayoutNode>> bottomNodeHash = new HashMap<>(); + for (LayoutEdge e : succs) { + assert e.from.layer < e.to.layer; + if (e.from.layer != e.to.layer - 1) { + if (maxLayerLength != -1 && e.to.layer - e.from.layer > maxLayerLength/* && e.to.preds.size() > 1 && e.from.succs.size() > 1*/) { + assert maxLayerLength > 2; + e.to.preds.remove(e); + e.from.succs.remove(e); + + LayoutEdge topEdge = null; + + if (combine == Combine.SAME_OUTPUTS && topNodeHash.containsKey(e.relativeFrom)) { + LayoutNode topNode = topNodeHash.get(e.relativeFrom); + topEdge = new LayoutEdge(); + topEdge.relativeFrom = e.relativeFrom; + topEdge.from = e.from; + topEdge.relativeTo = topNode.width / 2; + topEdge.to = topNode; + topEdge.link = e.link; + topEdge.vip = e.vip; + e.from.succs.add(topEdge); + topNode.preds.add(topEdge); + } else { + + LayoutNode topNode = new LayoutNode(); + topNode.layer = e.from.layer + 1; + topNode.width = DUMMY_WIDTH; + topNode.height = DUMMY_HEIGHT; + nodes.add(topNode); + topEdge = new LayoutEdge(); + topEdge.relativeFrom = e.relativeFrom; + topEdge.from = e.from; + topEdge.relativeTo = topNode.width / 2; + topEdge.to = topNode; + topEdge.link = e.link; + topEdge.vip = e.vip; + e.from.succs.add(topEdge); + topNode.preds.add(topEdge); + topNodeHash.put(e.relativeFrom, topNode); + bottomNodeHash.put(e.relativeFrom, new HashMap<Integer, LayoutNode>()); + } + + HashMap<Integer, LayoutNode> hash = bottomNodeHash.get(e.relativeFrom); + + LayoutNode bottomNode = null; + if (hash.containsKey(e.to.layer)) { + bottomNode = hash.get(e.to.layer); + } else { + + bottomNode = new LayoutNode(); + bottomNode.layer = e.to.layer - 1; + bottomNode.width = DUMMY_WIDTH; + bottomNode.height = DUMMY_HEIGHT; + nodes.add(bottomNode); + hash.put(e.to.layer, bottomNode); + } + + LayoutEdge bottomEdge = new LayoutEdge(); + bottomEdge.relativeTo = e.relativeTo; + bottomEdge.to = e.to; + bottomEdge.relativeFrom = bottomNode.width / 2; + bottomEdge.from = bottomNode; + bottomEdge.link = e.link; + bottomEdge.vip = e.vip; + e.to.preds.add(bottomEdge); + bottomEdgeHash.put(topEdge, bottomEdge); + bottomNode.succs.add(bottomEdge); + + } else { + Integer i = e.relativeFrom; + if (!portHash.containsKey(i)) { + portHash.put(i, new ArrayList<LayoutEdge>()); + } + portHash.get(i).add(e); + } + } + } + + succs = new ArrayList<>(n.succs); + for (LayoutEdge e : succs) { + + Integer i = e.relativeFrom; + if (portHash.containsKey(i)) { + + List<LayoutEdge> list = portHash.get(i); + Collections.sort(list, comparator); + + if (list.size() == 1) { + processSingleEdge(list.get(0)); + } else { + + int maxLayer = list.get(0).to.layer; + for (LayoutEdge curEdge : list) { + maxLayer = Math.max(maxLayer, curEdge.to.layer); + } + + + int cnt = maxLayer - n.layer - 1; + LayoutEdge[] edges = new LayoutEdge[cnt]; + LayoutNode[] nodes = new LayoutNode[cnt]; + edges[0] = new LayoutEdge(); + edges[0].from = n; + edges[0].relativeFrom = i; + edges[0].vip = e.vip; + n.succs.add(edges[0]); + + nodes[0] = new LayoutNode(); + nodes[0].width = dummyWidth; + nodes[0].height = dummyHeight; + nodes[0].layer = n.layer + 1; + nodes[0].preds.add(edges[0]); + edges[0].to = nodes[0]; + edges[0].relativeTo = nodes[0].width / 2; + for (int j = 1; j < cnt; j++) { + edges[j] = new LayoutEdge(); + edges[j].vip = e.vip; + edges[j].from = nodes[j - 1]; + edges[j].relativeFrom = nodes[j - 1].width / 2; + nodes[j - 1].succs.add(edges[j]); + nodes[j] = new LayoutNode(); + nodes[j].width = dummyWidth; + nodes[j].height = dummyHeight; + nodes[j].layer = n.layer + j + 1; + nodes[j].preds.add(edges[j]); + edges[j].to = nodes[j]; + edges[j].relativeTo = nodes[j].width / 2; + } + + for (LayoutEdge curEdge : list) { + assert curEdge.to.layer - n.layer - 2 >= 0; + assert curEdge.to.layer - n.layer - 2 < cnt; + LayoutNode anchor = nodes[curEdge.to.layer - n.layer - 2]; + anchor.succs.add(curEdge); + curEdge.from = anchor; + curEdge.relativeFrom = anchor.width / 2; + n.succs.remove(curEdge); + } + + } + + portHash.remove(i); + } + } + } + } else if (combine == Combine.SAME_INPUTS) { + throw new UnsupportedOperationException("Currently not supported"); + } else { + ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes); + for (LayoutNode n : currentNodes) { + for (LayoutEdge e : n.succs) { + processSingleEdge(e); + } + } + } + } + + private void processSingleEdge(LayoutEdge e) { + LayoutNode n = e.from; + if (e.to.layer > n.layer + 1) { + LayoutEdge last = e; + for (int i = n.layer + 1; i < last.to.layer; i++) { + last = addBetween(last, i); + } + } + } + + private LayoutEdge addBetween(LayoutEdge e, int layer) { + LayoutNode n = new LayoutNode(); + n.width = dummyWidth; + n.height = dummyHeight; + n.layer = layer; + n.preds.add(e); + nodes.add(n); + LayoutEdge result = new LayoutEdge(); + result.vip = e.vip; + n.succs.add(result); + result.from = n; + result.relativeFrom = n.width / 2; + result.to = e.to; + result.relativeTo = e.relativeTo; + e.relativeTo = n.width / 2; + e.to.preds.remove(e); + e.to.preds.add(result); + e.to = n; + return result; + } + + @Override + public void printStatistics() { + System.out.println("Dummy nodes created: " + (nodes.size() - oldNodeCount)); + } + + @Override + public void postCheck() { + ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes); + for (LayoutNode n : currentNodes) { + for (LayoutEdge e : n.succs) { + assert e.from.layer == e.to.layer - 1; + } + } + + for (int i = 0; i < layers.length; i++) { + assert layers[i].size() > 0; + for (LayoutNode n : layers[i]) { + assert n.layer == i; + } + } + } + } + + private class AssignLayers extends AlgorithmPart { + + @Override + public void preCheck() { + for (LayoutNode n : nodes) { + assert n.layer == -1; + } + } + + @Override + protected void run() { + + List<LayoutNode> insertOrder = new ArrayList<>(); + + HashSet<LayoutNode> set = new HashSet<>(); + for (LayoutNode n : nodes) { + if (n.preds.size() == 0) { + set.add(n); + insertOrder.add(n); + n.layer = 0; + } + } + + int z = minLayerDifference; + HashSet<LayoutNode> newSet = new HashSet<>(); + HashSet<LayoutNode> failed = new HashSet<>(); + while (!set.isEmpty()) { + + newSet.clear(); + failed.clear(); + + for (LayoutNode n : set) { + + for (LayoutEdge se : n.succs) { + LayoutNode s = se.to; + if (!newSet.contains(s) && !failed.contains(s)) { + boolean ok = true; + for (LayoutEdge pe : s.preds) { + LayoutNode p = pe.from; + if (p.layer == -1) { + ok = false; + break; + } + } + + if (ok) { + newSet.add(s); + } else { + failed.add(s); + } + } + } + + } + + for (LayoutNode n : newSet) { + n.layer = z; + insertOrder.add(n); + } + + // Swap sets + HashSet<LayoutNode> tmp = set; + set = newSet; + newSet = tmp; + z += minLayerDifference; + } + + optimize(insertOrder); + + layerCount = z - minLayerDifference; + + for (Vertex v : lastLayerHint) { + + LayoutNode n = vertexToLayoutNode.get(v); + assert n.succs.size() == 0; + n.layer = layerCount - 1; + } + + for (Vertex v : firstLayerHint) { + LayoutNode n = vertexToLayoutNode.get(v); + assert n.preds.size() == 0; + n.layer = 0; + assert n.layer == 0; + } + } + + public void optimize(List<LayoutNode> insertOrder) { + for (int i = insertOrder.size() - 1; i >= 0; i--) { + LayoutNode cur = insertOrder.get(i); + if (cur.succs.size() > cur.preds.size()) { + int minLayer = cur.succs.get(0).to.layer; + for (LayoutEdge e : cur.succs) { + minLayer = Math.min(minLayer, e.to.layer); + } + cur.layer = minLayer - 1; + } + } + } + + @Override + public void postCheck() { + for (LayoutNode n : nodes) { + assert n.layer >= 0; + assert n.layer < layerCount; + for (LayoutEdge e : n.succs) { + assert e.from.layer < e.to.layer; + } + } + } + } + + private class ReverseEdges extends AlgorithmPart { + + private HashSet<LayoutNode> visited; + private HashSet<LayoutNode> active; + + @Override + protected void run() { + + // Remove self-edges + for (LayoutNode node : nodes) { + ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs); + for (LayoutEdge e : succs) { + assert e.from == node; + if (e.to == node) { + node.succs.remove(e); + node.preds.remove(e); + } + } + } + + // Reverse inputs of roots + for (LayoutNode node : nodes) { + if (node.vertex.isRoot()) { + boolean ok = true; + for (LayoutEdge e : node.preds) { + if (e.from.vertex.isRoot()) { + ok = false; + break; + } + } + if (ok) { + reverseAllInputs(node); + } + } + } + + + // Start DFS and reverse back edges + visited = new HashSet<>(); + active = new HashSet<>(); + for (LayoutNode node : nodes) { + DFS(node); + } + + + for (LayoutNode node : nodes) { + + SortedSet<Integer> reversedDown = new TreeSet<>(); + + for (LayoutEdge e : node.succs) { + if (reversedLinks.contains(e.link)) { + reversedDown.add(e.relativeFrom); + } + } + + + SortedSet<Integer> reversedUp = null; + if (reversedDown.size() == 0) { + reversedUp = new TreeSet<>(Collections.reverseOrder()); + } else { + reversedUp = new TreeSet<>(); + } + + for (LayoutEdge e : node.preds) { + if (reversedLinks.contains(e.link)) { + reversedUp.add(e.relativeTo); + } + } + + final int offset = X_OFFSET + DUMMY_WIDTH; + + int curX = 0; + int curWidth = node.width + reversedDown.size() * offset; + for (int pos : reversedDown) { + ArrayList<LayoutEdge> reversedSuccs = new ArrayList<>(); + for (LayoutEdge e : node.succs) { + if (e.relativeFrom == pos && reversedLinks.contains(e.link)) { + reversedSuccs.add(e); + e.relativeFrom = curWidth; + } + } + + ArrayList<Point> startPoints = new ArrayList<>(); + startPoints.add(new Point(curWidth, curX)); + startPoints.add(new Point(pos, curX)); + startPoints.add(new Point(pos, reversedDown.size() * offset)); + for (LayoutEdge e : reversedSuccs) { + reversedLinkStartPoints.put(e.link, startPoints); + } + + node.inOffsets.put(pos, -curX); + curX += offset; + node.height += offset; + node.yOffset += offset; + curWidth -= offset; + } + node.width += reversedDown.size() * offset; + + if (reversedDown.size() == 0) { + curX = offset; + } else { + curX = -offset; + } + + curX = 0; + int minX = 0; + if (reversedDown.size() != 0) { + minX = -offset * reversedUp.size(); + } + + int oldNodeHeight = node.height; + for (int pos : reversedUp) { + ArrayList<LayoutEdge> reversedPreds = new ArrayList<>(); + for (LayoutEdge e : node.preds) { + if (e.relativeTo == pos && reversedLinks.contains(e.link)) { + if (reversedDown.size() == 0) { + e.relativeTo = node.width + offset; + } else { + e.relativeTo = curX - offset; + } + + reversedPreds.add(e); + } + } + node.height += offset; + ArrayList<Point> endPoints = new ArrayList<>(); + + if (reversedDown.size() == 0) { + + curX += offset; + node.width += offset; + endPoints.add(new Point(node.width, node.height)); + + } else { + curX -= offset; + node.width += offset; + endPoints.add(new Point(curX, node.height)); + } + + node.outOffsets.put(pos - minX, curX); + curX += offset; + node.bottomYOffset += offset; + + + endPoints.add(new Point(pos, node.height)); + endPoints.add(new Point(pos, oldNodeHeight)); + for (LayoutEdge e : reversedPreds) { + reversedLinkEndPoints.put(e.link, endPoints); + } + } + + + if (minX < 0) { + for (LayoutEdge e : node.preds) { + e.relativeTo -= minX; + } + + for (LayoutEdge e : node.succs) { + e.relativeFrom -= minX; + } + + node.xOffset = -minX; + node.width += -minX; + } + } + + } + + private void DFS(LayoutNode startNode) { + if (visited.contains(startNode)) { + return; + } + + Stack<LayoutNode> stack = new Stack<>(); + stack.push(startNode); + + while (!stack.empty()) { + LayoutNode node = stack.pop(); + + if (visited.contains(node)) { + // Node no longer active + active.remove(node); + continue; + } + + // Repush immediately to know when no longer active + stack.push(node); + visited.add(node); + active.add(node); + + ArrayList<LayoutEdge> succs = new ArrayList<>(node.succs); + for (LayoutEdge e : succs) { + if (active.contains(e.to)) { + assert visited.contains(e.to); + // Encountered back edge + reverseEdge(e); + } else if (!visited.contains(e.to) && (linksToFollow.size() == 0 || linksToFollow.contains(e.link))) { + stack.push(e.to); + } + } + } + } + + private void reverseAllInputs(LayoutNode node) { + for (LayoutEdge e : node.preds) { + assert !reversedLinks.contains(e.link); + reversedLinks.add(e.link); + node.succs.add(e); + e.from.preds.add(e); + e.from.succs.remove(e); + int oldRelativeFrom = e.relativeFrom; + int oldRelativeTo = e.relativeTo; + e.to = e.from; + e.from = node; + e.relativeFrom = oldRelativeTo; + e.relativeTo = oldRelativeFrom; + } + node.preds.clear(); + } + + private void reverseEdge(LayoutEdge e) { + assert !reversedLinks.contains(e.link); + reversedLinks.add(e.link); + + LayoutNode oldFrom = e.from; + LayoutNode oldTo = e.to; + int oldRelativeFrom = e.relativeFrom; + int oldRelativeTo = e.relativeTo; + + e.from = oldTo; + e.to = oldFrom; + e.relativeFrom = oldRelativeTo; + e.relativeTo = oldRelativeFrom; + + oldFrom.succs.remove(e); + oldFrom.preds.add(e); + oldTo.preds.remove(e); + oldTo.succs.add(e); + } + + @Override + public void postCheck() { + + for (LayoutNode n : nodes) { + + HashSet<LayoutNode> curVisited = new HashSet<>(); + Queue<LayoutNode> queue = new LinkedList<>(); + for (LayoutEdge e : n.succs) { + LayoutNode s = e.to; + queue.add(s); + curVisited.add(s); + } + + while (!queue.isEmpty()) { + LayoutNode curNode = queue.remove(); + + for (LayoutEdge e : curNode.succs) { + assert e.to != n; + if (!curVisited.contains(e.to)) { + queue.add(e.to); + curVisited.add(e.to); + } + } + } + } + } + } + private Comparator<Link> linkComparator = new Comparator<Link>() { + + @Override + public int compare(Link l1, Link l2) { + + int result = l1.getFrom().getVertex().compareTo(l2.getFrom().getVertex()); + if (result != 0) { + return result; + } + result = l1.getTo().getVertex().compareTo(l2.getTo().getVertex()); + if (result != 0) { + return result; + } + result = l1.getFrom().getRelativePosition().x - l2.getFrom().getRelativePosition().x; + if (result != 0) { + return result; + } + result = l1.getTo().getRelativePosition().x - l2.getTo().getRelativePosition().x; + return result; + } + }; + + private class BuildDatastructure extends AlgorithmPart { + + @Override + protected void run() { + // Set up nodes + List<Vertex> vertices = new ArrayList<>(graph.getVertices()); + Collections.sort(vertices); + + for (Vertex v : vertices) { + LayoutNode node = new LayoutNode(); + Dimension size = v.getSize(); + node.width = (int) size.getWidth(); + node.height = (int) size.getHeight(); + node.vertex = v; + nodes.add(node); + vertexToLayoutNode.put(v, node); + } + + // Set up edges + List<Link> links = new ArrayList<>(graph.getLinks()); + Collections.sort(links, linkComparator); + for (Link l : links) { + LayoutEdge edge = new LayoutEdge(); + assert vertexToLayoutNode.containsKey(l.getFrom().getVertex()); + assert vertexToLayoutNode.containsKey(l.getTo().getVertex()); + edge.from = vertexToLayoutNode.get(l.getFrom().getVertex()); + edge.to = vertexToLayoutNode.get(l.getTo().getVertex()); + edge.relativeFrom = l.getFrom().getRelativePosition().x; + edge.relativeTo = l.getTo().getRelativePosition().x; + edge.link = l; + edge.from.succs.add(edge); + edge.to.preds.add(edge); + edge.vip = l.isVIP(); + //assert edge.from != edge.to; // No self-loops allowed + } + + for (Link l : importantLinks) { + if (!vertexToLayoutNode.containsKey(l.getFrom().getVertex()) || + vertexToLayoutNode.containsKey(l.getTo().getVertex())) { + continue; + } + LayoutNode from = vertexToLayoutNode.get(l.getFrom().getVertex()); + LayoutNode to = vertexToLayoutNode.get(l.getTo().getVertex()); + for (LayoutEdge e : from.succs) { + if (e.to == to) { + linksToFollow.add(e.link); + } + } + } + } + + @Override + public void postCheck() { + + assert vertexToLayoutNode.keySet().size() == nodes.size(); + assert nodes.size() == graph.getVertices().size(); + + for (Vertex v : graph.getVertices()) { + + LayoutNode node = vertexToLayoutNode.get(v); + assert node != null; + + for (LayoutEdge e : node.succs) { + assert e.from == node; + } + + for (LayoutEdge e : node.preds) { + assert e.to == node; + } + + } + } + } + + @Override + public void doRouting(LayoutGraph graph) { + // Do nothing for now + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.hierarchicallayout; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class Node<N, E> { + + private N data; + private List<Edge<N, E>> inEdges; + private List<Edge<N, E>> outEdges; + private boolean visited; + private boolean active; + private boolean reachable; + private Graph<N, E> graph; + + protected boolean isVisited() { + return visited; + } + + protected void setVisited(boolean b) { + visited = b; + } + + protected boolean isReachable() { + return reachable; + } + + protected void setReachable(boolean b) { + reachable = b; + } + + protected boolean isActive() { + return active; + } + + protected void setActive(boolean b) { + active = b; + } + + public int getInDegree() { + return getInDegree(true); + } + + public int getInDegree(boolean countSelfLoops) { + if (countSelfLoops) { + return inEdges.size(); + } else { + int cnt = 0; + for (Edge<N, E> e : inEdges) { + if (e.getSource() != this) { + cnt++; + } + } + return cnt; + } + } + + public int getOutDegree() { + return outEdges.size(); + } + + protected Node(Graph<N, E> graph, N data) { + setData(data); + this.graph = graph; + inEdges = new ArrayList<>(); + outEdges = new ArrayList<>(); + } + + protected void addInEdge(Edge<N, E> e) { + inEdges.add(e); + } + + public Graph<N, E> getGraph() { + return graph; + } + + protected void addOutEdge(Edge<N, E> e) { + outEdges.add(e); + } + + protected void removeInEdge(Edge<N, E> e) { + //assert inEdges.contains(e); + inEdges.remove(e); + } + + protected void removeOutEdge(Edge<N, E> e) { + //assert outEdges.contains(e); + outEdges.remove(e); + } + + public List<Edge<N, E>> getInEdges() { + return Collections.unmodifiableList(inEdges); + } + + public List<Edge<N, E>> getOutEdges() { + return Collections.unmodifiableList(outEdges); + } + + public List<Node<N, E>> getSuccessors() { + ArrayList<Node<N, E>> succ = new ArrayList<>(); + for (Edge<N, E> e : getOutEdges()) { + Node<N, E> n = e.getDest(); + if (!succ.contains(n)) { + succ.add(n); + } + } + return succ; + } + + public List<Node<N, E>> getPredecessors() { + ArrayList<Node<N, E>> pred = new ArrayList<>(); + for (Edge<N, E> e : getInEdges()) { + Node<N, E> n = e.getSource(); + if (!pred.contains(n)) { + pred.add(n); + } + } + return pred; + } + + public N getData() { + return data; + } + + public void setData(N d) { + data = d; + } + + @Override + public String toString() { + return "Node: " + data; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.hierarchicallayout; + +/** + * + * @author Thomas Wuerthinger + */ +public class Timing { + + private long lastValue; + private long sum; + private String name; + + public Timing(String name) { + this.name = name; + } + + @Override + public String toString() { + long val = sum; + if (lastValue != 0) { + // Timer running + long newValue = System.nanoTime(); + val += (newValue - lastValue); + } + return "Timing for " + name + " is: " + val / 1000000 + " ms"; + } + + public void print() { + System.out.println(toString()); + } + + public void start() { + lastValue = System.nanoTime(); + } + + public void stop() { + if (lastValue == 0) { + throw new IllegalStateException("You must call start before stop"); + } + long newValue = System.nanoTime(); + sum += newValue - lastValue; + lastValue = 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.layout" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.layout.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.layout +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/layout/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.layout-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=cb0889d9 +build.xml.script.CRC32=d65fccb9 +build.xml.stylesheet.CRC32=79c3b980 +# 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=cb0889d9 +nbproject/build-impl.xml.script.CRC32=7f82736d +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.layout</code-name-base> + <suite-component/> + <module-dependencies/> + <public-packages> + <package>com.sun.hotspot.igv.layout</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Layout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.layout; + +import java.util.*; + +/** + * + * @author Thomas Wuerthinger + */ +public class LayoutGraph { + + private Set<? extends Link> links; + private SortedSet<Vertex> vertices; + private HashMap<Vertex, Set<Port>> inputPorts; + private HashMap<Vertex, Set<Port>> outputPorts; + private HashMap<Port, Set<Link>> portLinks; + + public LayoutGraph(Set<? extends Link> links) { + this(links, new HashSet<Vertex>()); + } + + public LayoutGraph(Set<? extends Link> links, Set<? extends Vertex> additionalVertices) { + this.links = links; + assert verify(); + + vertices = new TreeSet<>(); + portLinks = new HashMap<>(links.size()); + inputPorts = new HashMap<>(links.size()); + outputPorts = new HashMap<>(links.size()); + + for (Link l : links) { + Port p = l.getFrom(); + Port p2 = l.getTo(); + Vertex v1 = p.getVertex(); + Vertex v2 = p2.getVertex(); + + if (!vertices.contains(v1)) { + + outputPorts.put(v1, new HashSet<Port>(1)); + inputPorts.put(v1, new HashSet<Port>(3)); + vertices.add(v1); + assert vertices.contains(v1); + } + + if (!vertices.contains(v2)) { + vertices.add(v2); + assert vertices.contains(v2); + outputPorts.put(v2, new HashSet<Port>(1)); + inputPorts.put(v2, new HashSet<Port>(3)); + } + + if (!portLinks.containsKey(p)) { + HashSet<Link> hashSet = new HashSet<>(3); + portLinks.put(p, hashSet); + } + + if (!portLinks.containsKey(p2)) { + portLinks.put(p2, new HashSet<Link>(3)); + } + + outputPorts.get(v1).add(p); + inputPorts.get(v2).add(p2); + + portLinks.get(p).add(l); + portLinks.get(p2).add(l); + } + + for (Vertex v : additionalVertices) { + if (!vertices.contains(v)) { + outputPorts.put(v, new HashSet<Port>(1)); + inputPorts.put(v, new HashSet<Port>(3)); + vertices.add(v); + vertices.contains(v); + } + } + } + + public Set<Port> getInputPorts(Vertex v) { + return this.inputPorts.get(v); + } + + public Set<Port> getOutputPorts(Vertex v) { + return this.outputPorts.get(v); + } + + public Set<Link> getPortLinks(Port p) { + return portLinks.get(p); + } + + public Set<? extends Link> getLinks() { + return links; + } + + public boolean verify() { + return true; + } + + public SortedSet<Vertex> getVertices() { + return vertices; + } + + private void markNotRoot(Set<Vertex> notRootSet, Vertex v, Vertex startingVertex) { + + if (notRootSet.contains(v)) { + return; + } + if (v != startingVertex) { + notRootSet.add(v); + } + Set<Port> outPorts = getOutputPorts(v); + for (Port p : outPorts) { + Set<Link> portLinks = getPortLinks(p); + for (Link l : portLinks) { + Port other = l.getTo(); + Vertex otherVertex = other.getVertex(); + if (otherVertex != startingVertex) { + markNotRoot(notRootSet, otherVertex, startingVertex); + } + } + } + } + + // Returns a set of vertices with the following properties: + // - All Vertices in the set startingRoots are elements of the set. + // - When starting a DFS at every vertex in the set, every vertex of the + // whole graph is visited. + public Set<Vertex> findRootVertices(Set<Vertex> startingRoots) { + + Set<Vertex> notRootSet = new HashSet<>(); + for (Vertex v : startingRoots) { + if (!notRootSet.contains(v)) { + markNotRoot(notRootSet, v, v); + } + } + + Set<Vertex> tmpVertices = getVertices(); + for (Vertex v : tmpVertices) { + if (!notRootSet.contains(v)) { + if (this.getInputPorts(v).size() == 0) { + markNotRoot(notRootSet, v, v); + } + } + } + + for (Vertex v : tmpVertices) { + if (!notRootSet.contains(v)) { + markNotRoot(notRootSet, v, v); + } + } + + Set<Vertex> result = new HashSet<>(); + for (Vertex v : tmpVertices) { + if (!notRootSet.contains(v)) { + result.add(v); + } + } + assert tmpVertices.size() == 0 || result.size() > 0; + return result; + } + + public Set<Vertex> findRootVertices() { + return findRootVertices(new HashSet<Vertex>()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.layout; + +import java.util.Set; + +/** + * + * @author Thomas Wuerthinger + */ +public interface LayoutManager { + + public void doLayout(LayoutGraph graph); + + public void doLayout(LayoutGraph graph, Set<? extends Vertex> firstLayerHint, Set<? extends Vertex> lastLayerHint, Set<? extends Link> importantLinks); + + public void doRouting(LayoutGraph graph); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.layout; + +import java.awt.Point; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public interface Link { + + public Port getFrom(); + + public Port getTo(); + + public boolean isVIP(); + + public List<Point> getControlPoints(); + + public void setControlPoints(List<Point> list); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.layout; + +import java.awt.Point; + +/** + * + * @author Thomas Wuerthinger + */ +public interface Port { + + public Vertex getVertex(); + + public Point getRelativePosition(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.layout; + +import java.awt.Dimension; +import java.awt.Point; + +/** + * + * @author Thomas Wuerthinger + */ +public interface Vertex extends Comparable<Vertex> { + + public Dimension getSize(); + + public Point getPosition(); + + public void setPosition(Point p); + + public boolean isRoot(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.coordinator" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.oracle.graal.visualizer.outline.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.oracle.graal.visualizer.outline +OpenIDE-Module-Layer: com/oracle/graal/visualizer/outline/layer.xml +OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/outline/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.coordinator-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=077de97c +build.xml.script.CRC32=d29d586c +build.xml.stylesheet.CRC32=79c3b980 +# 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=077de97c +nbproject/build-impl.xml.script.CRC32=03daa42d +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.oracle.graal.visualizer.outline</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>at.ssw.visualizer.cfg</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.difference</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.settings</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.api.progress</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.23.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.actions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.21.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.30.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.dialogs</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.18.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.explorer</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.34.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.filesystems</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.46.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.loaders</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.nodes</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.14.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.39.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.oracle.graal.visualizer.outline</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +AdvancedOption_DisplayName_Coordinator=Settings +AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings +CTL_OutlineTopComponent=Outline +HINT_OutlineTopComponent=Displays loaded compilations. +OpenIDE-Module-Name=OutlineView
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/CompilationNode.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,148 @@ +/* + * 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.outline; + +import com.sun.hotspot.igv.data.*; +import com.sun.hotspot.igv.data.services.GraphViewer; +import java.awt.Image; +import java.util.ArrayList; +import java.util.List; +import javax.swing.Action; +import javax.swing.JOptionPane; +import org.openide.actions.OpenAction; +import org.openide.cookies.OpenCookie; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; +import org.openide.util.Lookup; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; +import org.openide.util.lookup.Lookups; + +public class CompilationNode extends AbstractNode implements ChangedListener { + + private CompilationNode(final Folder folder, Children children, InstanceContent content) { + super(children, new AbstractLookup(content)); + this.setDisplayName(folder.getName()); + + if (folder instanceof Group) { + content.add(new OpenCookie() { + + @Override + public void open() { + final List<InputGraph> graphs = ((Group) folder).getGraphs(); + if (graphs.isEmpty()) { + JOptionPane.showMessageDialog(null, "Cannot open compilation, because there was no snapshots recorded!"); + } else { + Lookup.getDefault().lookup(GraphViewer.class).view(graphs.get(0)); + } + } + }); + } + content.add(folder); + folder.getChangedEvent().addListener(this); + } + + @Override + public void changed(Object folder) { + if (this.getChildren() == Children.LEAF) { + setChildren(createFolderChildren((Folder) folder)); + this.fireIconChange(); + } + } + + private static class FolderChildren extends Children.Keys<Folder> { + + private final Folder folder; + + public FolderChildren(Folder folder) { + this.folder = folder; + folder.getChangedEvent().addListener(changedListener); + } + + @Override + protected Node[] createNodes(Folder e) { + return new Node[]{new CompilationNode(e)}; + } + + @Override + public void addNotify() { + List<Folder> result = new ArrayList<>(); + for (FolderElement o : folder.getElements()) { + if (o instanceof Folder) { + result.add((Folder) o); + } + } + this.setKeys(result); + } + private final ChangedListener changedListener = new ChangedListener() { + + @Override + public void changed(Object source) { + addNotify(); + } + }; + } + + @Override + public Image getIcon(int i) { + if (this.getChildren() == Children.LEAF) { + return ImageUtilities.loadImage("com/oracle/graal/visualizer/outline/images/leaf_node.gif"); + } else { + return ImageUtilities.loadImage("com/oracle/graal/visualizer/outline/images/node.gif"); + } + } + + protected CompilationNode(Folder folder) { + this(folder, createFolderChildren(folder), new InstanceContent()); + } + + private static Children createFolderChildren(Folder folder) { + for (FolderElement elem : folder.getElements()) { + if (elem instanceof Folder) { + return new FolderChildren(folder); + } + } + return Children.LEAF; + } + + @Override + public Action[] getActions(boolean context) { + List<Action> actions = new ArrayList<>(); + actions.add((Action) OpenAction.findObject(OpenAction.class, true)); + actions.addAll(Lookups.forPath(OutlineTopComponent.NODE_ACTIONS_FOLDER).lookupAll(Action.class)); + return actions.toArray(new Action[actions.size()]); + } + + @Override + public Action getPreferredAction() { + return (Action) OpenAction.findObject(OpenAction.class, true); + } + + @Override + public Image getOpenedIcon(int i) { + return getIcon(i); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.form Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="treeView"> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/> + </AuxValues> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription"> + <BorderConstraints direction="Center"/> + </Constraint> + </Constraints> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + </Container> + </SubComponents> +</Form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,123 @@ +/* + * 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.outline; + +import com.oracle.graal.visualizer.outline.server.ServerPanel; +import com.oracle.graal.visualizer.util.LookupUtils; +import com.sun.hotspot.igv.data.GraphDocument; +import java.awt.BorderLayout; +import javax.swing.Action; +import org.openide.actions.GarbageCollectAction; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.Toolbar; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; +import org.openide.explorer.view.BeanTreeView; +import org.openide.util.NbBundle; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; + +@TopComponent.Description(preferredID = OutlineTopComponent.PREFERRED_ID, persistenceType = TopComponent.PERSISTENCE_ALWAYS) +@TopComponent.Registration(mode = "explorer", openAtStartup = true) +@ActionID(category = "Window", id = "com.oracle.graal.visualizer.outline.OutlineTopComponent") +@ActionReference(path = "Menu/Window") +@TopComponent.OpenActionRegistration(displayName = "Outline", preferredID = OutlineTopComponent.PREFERRED_ID) +public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider { + + public static final String GLOBAL_ACTIONS_FOLDER = "Actions/Outline/Global"; + public static final String NODE_ACTIONS_FOLDER = "Actions/Outline/Nodes"; + public static OutlineTopComponent instance; + public static final String PREFERRED_ID = "OutlineTopComponent"; + private ExplorerManager manager; + private GraphDocument document; + + private OutlineTopComponent() { + initComponents(); + + setName(NbBundle.getMessage(OutlineTopComponent.class, "CTL_OutlineTopComponent")); + setToolTipText(NbBundle.getMessage(OutlineTopComponent.class, "HINT_OutlineTopComponent")); + + document = new GraphDocument(); + initListView(); + initToolbar(); + } + + private void initListView() { + manager = new ExplorerManager(); + manager.setRootContext(new CompilationNode(document)); + ((BeanTreeView) this.treeView).setRootVisible(false); + associateLookup(ExplorerUtils.createLookup(manager, getActionMap())); + } + + private void initToolbar() { + Toolbar toolbar = new Toolbar(); + this.add(toolbar, BorderLayout.NORTH); + for (Action a : LookupUtils.lookupActions(GLOBAL_ACTIONS_FOLDER, getLookup())) { + toolbar.add(a); + } + toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter()); + toolbar.add(new ServerPanel(getDocument())); + } + + @Override + public ExplorerManager getExplorerManager() { + return manager; + } + + public GraphDocument getDocument() { + return document; + } + + public static OutlineTopComponent findInstance() { + return (OutlineTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER; + } + + @Override + protected String preferredID() { + return PREFERRED_ID; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + treeView = new BeanTreeView(); + + setLayout(new java.awt.BorderLayout()); + add(treeView, java.awt.BorderLayout.CENTER); + }// </editor-fold>//GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane treeView; + // End of variables declaration//GEN-END:variables +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/ImportAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,155 @@ +/* + * 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.outline.actions; + +import com.oracle.graal.visualizer.outline.OutlineTopComponent; +import com.sun.hotspot.igv.data.GraphDocument; +import com.sun.hotspot.igv.data.serialization.Parser; +import com.sun.hotspot.igv.data.serialization.XMLParser; +import com.sun.hotspot.igv.settings.Settings; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.filechooser.FileFilter; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressHandleFactory; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; +import org.openide.util.RequestProcessor; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +@ActionID(id = "com.oracle.graal.visualizer.outline.actions.ImportAction", category = "File") +@ActionRegistration(displayName = "Import", iconBase="com/oracle/graal/visualizer/outline/images/import.png") +@ActionReferences(value = { + @ActionReference(path = "Menu/File", position = 100), + @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)}) +public final class ImportAction implements ActionListener { + + public static FileFilter getFileFilter() { + return new FileFilter() { + + @Override + public boolean accept(File f) { + return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory(); + } + + @Override + public String getDescription() { + return "XML files (*.xml)"; + } + }; + } + + @Override + public void actionPerformed(ActionEvent e) { + + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(ImportAction.getFileFilter()); + fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT))); + + if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + + File dir = file; + if (!dir.isDirectory()) { + dir = dir.getParentFile(); + } + + Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath()); + + try { + final FileInputStream inputStream = new FileInputStream(file); + final InputSource is = new InputSource(inputStream); + + final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName()); + final int basis = 1000; + handle.start(basis); + final int start = inputStream.available(); + + final XMLParser.ParseMonitor parseMonitor = new XMLParser.ParseMonitor() { + + @Override + public void setProgress(double d) { + try { + int curAvailable = inputStream.available(); + int prog = (int) (basis * (double) (start - curAvailable) / (double) start); + handle.progress(prog); + } catch (IOException ex) { + } + } + + @Override + public void setState(String state) { + setProgress(0.0); + handle.progress(state); + } + }; + final Parser parser = new Parser(); + final OutlineTopComponent component = OutlineTopComponent.findInstance(); + + component.requestActive(); + + RequestProcessor.getDefault().post(new Runnable() { + + @Override + public void run() { + try { + final GraphDocument document = parser.parse(is, parseMonitor); + parseMonitor.setState("Finishing"); + SwingUtilities.invokeLater(new Runnable(){ + + @Override + public void run() { + component.getDocument().addGraphDocument(document); + } + }); + } catch (SAXException ex) { + String s = "Exception during parsing the XML file, could not load document!"; + if (ex instanceof XMLParser.MissingAttributeException) { + XMLParser.MissingAttributeException e = (XMLParser.MissingAttributeException) ex; + s += "\nMissing attribute \"" + e.getAttributeName() + "\""; + } + NotifyDescriptor d = new NotifyDescriptor.Message(s, NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notify(d); + } + handle.finish(); + } + }); + + } catch (IOException ex) { + DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error reading file!", NotifyDescriptor.ERROR_MESSAGE)); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,55 @@ +/* + * 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.outline.actions; + +import com.oracle.graal.visualizer.outline.OutlineTopComponent; +import com.sun.hotspot.igv.data.FolderElement; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.outline.actions.RemoveAction", category = "Edit") +@ActionRegistration(displayName = "Remove", iconBase = "com/oracle/graal/visualizer/outline/images/remove.png") +@ActionReferences(value = { + @ActionReference(path = "Menu/File", position = 400), + @ActionReference(path = OutlineTopComponent.NODE_ACTIONS_FOLDER)}) +public final class RemoveAction implements ActionListener { + + List<FolderElement> elements; + + public RemoveAction(List<FolderElement> elements) { + this.elements = elements; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (FolderElement element : elements) { + element.getParent().removeElement(element); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAllAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,46 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.outline.actions; + +import com.oracle.graal.visualizer.outline.OutlineTopComponent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.outline.actions.RemoveAllAction", category = "Edit") +@ActionRegistration(displayName = "Remove all", iconBase = "com/oracle/graal/visualizer/outline/images/removeall.png") +@ActionReferences(value = { + @ActionReference(path = "Menu/File", position = 500), + @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)}) +public final class RemoveAllAction implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + OutlineTopComponent.findInstance().getDocument().clear(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAllAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,47 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.outline.actions; + +import com.oracle.graal.visualizer.outline.OutlineTopComponent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.outline.actions.SaveAllAction", category = "File") +@ActionRegistration(displayName = "Save all..", iconBase = "com/oracle/graal/visualizer/outline/images/saveall.gif") +@ActionReferences(value = { + @ActionReference(path = "Menu/File", position = 300), + @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)}) +public final class SaveAllAction implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + final OutlineTopComponent component = OutlineTopComponent.findInstance(); + SaveAsAction.save(component.getDocument()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAsAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,105 @@ +/* + * 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.outline.actions; + +import com.oracle.graal.visualizer.outline.OutlineTopComponent; +import com.sun.hotspot.igv.data.Folder; +import com.sun.hotspot.igv.data.FolderElement; +import com.sun.hotspot.igv.data.GraphDocument; +import com.sun.hotspot.igv.data.serialization.Printer; +import com.sun.hotspot.igv.settings.Settings; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import java.util.List; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.outline.actions.SaveAsAction", category = "File") +@ActionRegistration(displayName = "Save as...", iconBase="com/oracle/graal/visualizer/outline/images/save.png") +@ActionReferences(value = { + @ActionReference(path = "Menu/File", position = 200), + @ActionReference(path = OutlineTopComponent.NODE_ACTIONS_FOLDER)}) +public final class SaveAsAction implements ActionListener { + + private final List<FolderElement> elements; + + public SaveAsAction(List<FolderElement> elements) { + this.elements = elements; + } + + + @Override + public void actionPerformed(ActionEvent e) { + GraphDocument doc = new GraphDocument(); + outer: for (FolderElement element : elements) { + Folder cur = element.getParent(); + while (cur instanceof FolderElement) { + FolderElement curElement = (FolderElement) cur; + if (elements.contains(curElement)) { + continue outer; + } + cur = curElement.getParent(); + } + + Folder previousParent = element.getParent(); + doc.addElement(element); + element.setParent(previousParent); + } + + save(doc); + } + + public static void save(GraphDocument doc) { + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(ImportAction.getFileFilter()); + fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT))); + + if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + if (!file.getName().contains(".")) { + file = new File(file.getAbsolutePath() + ".xml"); + } + + File dir = file; + if (!dir.isDirectory()) { + dir = dir.getParentFile(); + } + Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath()); + try { + try (Writer writer = new OutputStreamWriter(new FileOutputStream(file))) { + Printer p = new Printer(); + p.export(writer, doc); + } + } catch (IOException e) { + JOptionPane.showMessageDialog(null, "Error writing file " + file.getAbsolutePath()); + } + } + } +}
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/import.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/leaf_node.gif has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/node.gif has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/remove.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/removeall.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/save.png has changed
Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/saveall.gif has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,161 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd"> +<filesystem> + <folder name="Actions"/> + + <folder name="Menu"> + <folder name="File"> + <file name="Separator2.instance_hidden"/> + <file name="Separator3.instance_hidden"/> + <file name="SeparatorOpen.instance_hidden"/> + <file name="SeparatorSave.instance"> + <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/> + <attr name="position" intvalue="150"/> + </file> + <file name="SeparatorRemove.instance"> + <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/> + <attr name="position" intvalue="350"/> + </file> + + <!-- Hidden menu entries from other modules --> + <file name="org-netbeans-modules-editor-ExportHtmlAction.shadow_hidden"/> + <file name="org-netbeans-modules-openfile-OpenFileAction.shadow_hidden"/> + <file name="org-netbeans-modules-openfile-RecentFileAction.shadow_hidden"/> + <file name="org-netbeans-modules-print-action-PageSetupAction.shadow_hidden"/> + <file name="org-netbeans-modules-print-action-PrintAction.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-CloseProject.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-CustomizeProject.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-NewFile.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-NewProject.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-OpenProject.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-RecentProjects.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-groups-GroupsMenu.shadow_hidden"/> + <file name="org-openide-actions-SaveAction.shadow_hidden"/> + <file name="org-openide-actions-SaveAllAction.shadow_hidden"/> + <file name="org-openide-actions-SaveAsAction.shadow_hidden"/> + </folder> + + <folder name="Edit"> + <!-- Hidden menu entries from other modules --> + <file name="Separator1.instance_hidden"/> + <file name="Separator2.instance_hidden"/> + <file name="SeparatorAfterFindPrevious.instance_hidden"/> + <file name="SeparatorAfterProjectsSearch.instance_hidden"/> + <file name="WhereUsedAction.shadow_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$FindNextAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$FindPreviousAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$FindSelectionAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$PasteFormattedAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$SelectAllAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$SelectIdentifierAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$StartMacroRecordingAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-MainMenuAction$StopMacroRecordingAction.instance_hidden"/> + <file name="org-netbeans-modules-search-FindInFilesAction.shadow_hidden"/> + <file name="org-netbeans-modules-search-ReplaceInFilesAction.shadow_hidden"/> + <file name="org-openide-actions-CopyAction.shadow_hidden"/> + <file name="org-openide-actions-CutAction.shadow_hidden"/> + <file name="org-openide-actions-DeleteAction.shadow_hidden"/> + <file name="org-openide-actions-FindAction.shadow_hidden"/> + <file name="org-openide-actions-PasteAction.shadow_hidden"/> + <file name="org-openide-actions-ReplaceAction.shadow_hidden"/> + <file name="sep-before-reposearch.instance_hidden"/> + </folder> + + <folder name="View"> + <!-- Hidden menu entries from other modules --> + <file name="Separator1.instance_hidden"/> + <file name="Separator2.instance_hidden"/> + <file name="org-netbeans-core-actions-HTMLViewAction.shadow_hidden"/> + <file name="org-netbeans-core-actions-LogAction.shadow_hidden"/> + <file name="org-netbeans-core-multiview-EditorsAction.instance_hidden"/> + <file name="org-netbeans-core-windows-actions-ToolbarsListAction.instance_hidden"/> + <file name="org-netbeans-modules-editor-NbCodeFoldingAction.instance_hidden"/> + <file name="org-netbeans-modules-project-ui-SyncEditorWithViewsAction.shadow_hidden"/> + <file name="org-netbeans-modules-versioning-ShowTextAnnotationsAction.shadow_hidden"/> + <file name="org-netbeans-modules-versioning-diff-ShowDiffSidebarAction.shadow_hidden"/> + <file name="toggle-line-numbers.shadow_hidden"/> + <file name="toggle-non-printable-characters.shadow_hidden"/> + <file name="toggle-toolbar.shadow_hidden"/> + </folder> + + <!-- Hidden menus --> + <folder name="GoTo_hidden"/> + <folder name="Source_hidden"/> + <folder name="Refactoring_hidden"/> + <folder name="BuildProject_hidden"/> + <folder name="RunProject_hidden"/> + <folder name="Versioning_hidden"/> + + <folder name="Tools"> + <!-- Hidden menu entries from other modules --> + <file name="LibrariesCustomizerAction.shadow_hidden"/> + <file name="PaletteManager_hidden"/> + <file name="Separator1.instance_hidden"/> + <file name="Separator2.instance_hidden"/> + <file name="ServerManagerAction3.shadow_hidden"/> + <file name="VariablesCustomizerAction.shadow_hidden"/> + <file name="org-netbeans-modules-autoupdate-ui-actions-PluginManagerAction.shadow_hidden"/> + <file name="org-netbeans-modules-favorites-templates-TemplatesAction.shadow_hidden"/> + <file name="org-netbeans-modules-options-OptionsWindowAction-separatorBefore.instance_hidden"/> + <file name="org-netbeans-modules-xml-catalog-CatalogAction.shadow_hidden"/> + <file name="org-openide-actions-ToolsAction.shadow_hidden"/> + </folder> + + <folder name="Window"> + + <!-- Hidden menu entries from other modules --> + <file name="Debug_hidden"/> + <file name="Navigator_hidden"/> + <file name="Other_hidden"/> + <file name="Output_hidden"/> + <file name="ProgressListAction.shadow_hidden"/> + <file name="ShowPaletteAction.shadow_hidden"/> + <file name="SwitchToRecentDocumentAction.shadow_hidden"/> + <file name="Versioning_hidden"/> + <file name="org-netbeans-core-ide-ServicesTabAction.shadow_hidden"/> + <file name="org-netbeans-modules-favorites-View.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-logical-tab-action.shadow_hidden"/> + <file name="org-netbeans-modules-project-ui-physical-tab-action.shadow_hidden"/> + <file name="org-netbeans-modules-tasklist-ui-TaskListAction.shadow_hidden"/> + <file name="CloneDocumentAction.shadow_hidden"/> + </folder> + + <folder name="Help"> + <!-- Hidden menu entries from other modules --> + <file name="Separator1.instance_hidden"/> + <file name="netbeans-kb.url_hidden"/> + <file name="org-netbeans-modules-autoupdate-ui-actions-CheckForUpdatesAction.shadow_hidden"/> + <file name="org-netbeans-modules-bugzilla-ReportNBIssueAction.shadow_hidden"/> + <file name="org-netbeans-modules-usersguide-master.xml_hidden"/> + <file name="shortcuts.xml_hidden"/> + </folder> + </folder> + + <folder name="OptionsDialog"> + <!-- Hidden option tabs from other modules --> + <file name="Editor.instance_hidden"/> + <file name="FontsAndColors.instance_hidden"/> + <file name="General.instance_hidden"/> + <file name="Keymaps.instance_hidden"/> + <folder name="Advanced"> + <file name="Files.instance_hidden"/> + <file name="IssueTracking.instance_hidden"/> + <file name="JavaScript.instance_hidden"/> + <file name="Spellchecker.instance_hidden"/> + <file name="TermAdvancedOption.instance_hidden"/> + <file name="ToDo.instance_hidden"/> + <file name="Versioning.instance_hidden"/> + </folder> + </folder> + + <folder name="Toolbars"> + <file name="Build_hidden"/> + <file name="Clipboard_hidden"/> + <file name="Debug_hidden"/> + <file name="Debugging.xml_hidden"/> + <file name="File_hidden"/> + <file name="Memory_hidden"/> + <file name="Standard.xml_hidden"/> + <file name="UndoRedo_hidden"/> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=NetworkConnection
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Client.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,67 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.outline.server; + +import com.sun.hotspot.igv.data.serialization.Parser; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class Client implements Runnable { + + private Socket socket; + private ServerCallback callback; + + public Client(Socket socket, ServerCallback callback) { + this.callback = callback; + this.socket = socket; + } + + @Override + public void run() { + callback.connectionOpened(socket.getInetAddress()); + try { + InputStream inputStream = new BufferedInputStream(socket.getInputStream()); + InputSource is = new InputSource(inputStream); + + try { + Parser parser = new Parser(callback); + parser.parse(is, null); + } catch (SAXException ex) { + throw new IOException(ex); + } + } catch (IOException ex) { + } finally { + try { + socket.close(); + } catch (IOException ex) { + } + callback.connectionClosed(); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Server.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,89 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.outline.server; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.util.RequestProcessor; + +public class Server { + + private Runnable serverRunnable; + private ServerSocket serverSocket; + + private Server() {} + + + public static Server start(final ServerCallback callback, int port) { + + final Server server = new Server(); + + try { + server.serverSocket = new java.net.ServerSocket(port); + } catch (IOException ex) { + NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(message); + return null; + } + + Runnable runnable = new Runnable() { + + @Override + public void run() { + while (true) { + try { + Socket clientSocket = server.serverSocket.accept(); + if (server.serverRunnable != this) { + clientSocket.close(); + return; + } + RequestProcessor.getDefault().post(new Client(clientSocket, callback), 0, Thread.MAX_PRIORITY); + } catch (IOException ex) { + server.serverSocket = null; + NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(message); + return; + } + } + } + }; + + server.serverRunnable = runnable; + RequestProcessor.getDefault().post(runnable, 0, Thread.MAX_PRIORITY); + return server; + } + + void shutdown() { + try { + serverSocket.close(); + } catch (IOException ex) { + } + + serverSocket = null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerCallback.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,37 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.outline.server; + +import com.sun.hotspot.igv.data.services.GroupCallback; +import java.net.InetAddress; + +public interface ServerCallback extends GroupCallback { + + public void connectionOpened(InetAddress inetAddress); + + public void connectionClosed(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerPanel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,130 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.outline.server; + +import com.sun.hotspot.igv.data.GraphDocument; +import com.sun.hotspot.igv.data.Group; +import com.sun.hotspot.igv.settings.Settings; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Font; +import java.net.InetAddress; +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +public class ServerPanel extends JPanel { + + private final static int BORDER_SIZE = 2; + JLabel label; + private Server server; + private int port = -1; + private int numberOfConnections; + private final GraphDocument document; + private final PreferenceChangeListener preferenceChanged = new PreferenceChangeListener() { + + @Override + public void preferenceChange(PreferenceChangeEvent evt) { + updateServer(); + } + }; + private ServerCallback callback = new ServerCallback() { + + @Override + public void connectionOpened(InetAddress inetAddress) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + numberOfConnections++; + updateLabel(); + } + }); + } + + @Override + public void connectionClosed() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + numberOfConnections--; + updateLabel(); + } + }); + } + + @Override + public void started(Group g) { + document.addElement(g); + } + }; + + private void updateLabel() { + if (numberOfConnections == 0) { + label.setText(String.format("Listening on %d", port)); + label.setFont(label.getFont().deriveFont(Font.PLAIN)); + } else { + label.setText(String.format("%d connections", numberOfConnections)); + label.setFont(label.getFont().deriveFont(Font.BOLD)); + } + } + + private void updateServer() { + int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT)); + if (curPort != port) { + port = curPort; + if (server != null) { + server.shutdown(); + } + server = Server.start(callback, port); + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + updateLabel(); + } + }); + } + } + + public ServerPanel(GraphDocument document) { + + this.document = document; + Settings.get().addPreferenceChangeListener(preferenceChanged); + label = new JLabel(); + label.setBorder(BorderFactory.createEmptyBorder(0, BORDER_SIZE, 0, BORDER_SIZE)); + this.setLayout(new BorderLayout()); + this.add(label, BorderLayout.WEST); + updateServer(); + } + + public Component getToolbarPresenter() { + return label; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=SelectionCoordinator
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/SelectionCoordinator.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,138 @@ +/* + * 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.sun.hotspot.igv.selectioncoordinator; + +import com.sun.hotspot.igv.data.ChangedEvent; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author Thomas + */ +public class SelectionCoordinator { + + private static SelectionCoordinator singleInstance = new SelectionCoordinator(); + private Set<Object> selectedObjects; + private Set<Object> highlightedObjects; + private ChangedEvent<SelectionCoordinator> selectedChangedEvent; + private ChangedEvent<SelectionCoordinator> highlightedChangedEvent; + + public static SelectionCoordinator getInstance() { + return singleInstance; + } + + private SelectionCoordinator() { + selectedChangedEvent = new ChangedEvent<>(this); + highlightedChangedEvent = new ChangedEvent<>(this); + selectedObjects = new HashSet<>(); + highlightedObjects = new HashSet<>(); + } + + public Set<Object> getSelectedObjects() { + return Collections.unmodifiableSet(selectedObjects); + } + + public Set<Object> getHighlightedObjects() { + return Collections.unmodifiableSet(highlightedObjects); + } + + public ChangedEvent<SelectionCoordinator> getHighlightedChangedEvent() { + return highlightedChangedEvent; + } + + public ChangedEvent<SelectionCoordinator> getSelectedChangedEvent() { + return selectedChangedEvent; + } + + public void addHighlighted(Object o) { + if (!highlightedObjects.contains(o)) { + highlightedObjects.add(o); + highlightedObjectsChanged(); + } + } + + public void removeHighlighted(Object o) { + if (highlightedObjects.contains(o)) { + highlightedObjects.remove(o); + highlightedObjectsChanged(); + } + } + + public void addAllHighlighted(Set<? extends Object> s) { + int oldSize = highlightedObjects.size(); + highlightedObjects.addAll(s); + if (oldSize != highlightedObjects.size()) { + highlightedObjectsChanged(); + } + } + + public void removeAllHighlighted(Set<? extends Object> s) { + int oldSize = highlightedObjects.size(); + highlightedObjects.removeAll(s); + if (oldSize != highlightedObjects.size()) { + highlightedObjectsChanged(); + } + } + + private void highlightedObjectsChanged() { + highlightedChangedEvent.fire(); + } + + public void addAllSelected(Set<? extends Object> s) { + int oldSize = selectedObjects.size(); + selectedObjects.addAll(s); + if (oldSize != selectedObjects.size()) { + selectedObjectsChanged(); + } + } + + public void removeAllSelected(Set<? extends Object> s) { + int oldSize = selectedObjects.size(); + selectedObjects.removeAll(s); + if (oldSize != selectedObjects.size()) { + selectedObjectsChanged(); + } + } + + public void setSelectedObjects(Set<? extends Object> s) { + assert s != null; + selectedObjects.clear(); + selectedObjects.addAll(s); + selectedObjectsChanged(); + } + + private void selectedObjectsChanged() { + selectedChangedEvent.fire(); + } + + public void setHighlightedObjects(Set<? extends Object> s) { + assert s != null; + this.highlightedObjects.clear(); + this.highlightedObjects.addAll(s); + highlightedObjectsChanged(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.settings" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.settings.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.settings +OpenIDE-Module-Layer: com/sun/hotspot/igv/settings/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/settings/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.settings-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=8869440a +build.xml.script.CRC32=7ef09117 +build.xml.stylesheet.CRC32=79c3b980 +# 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=8869440a +nbproject/build-impl.xml.script.CRC32=1a0e7f21 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.settings</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>org.jdesktop.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.16.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.modules.options.api</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.21.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.30.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.14.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.sun.hotspot.igv.settings</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +AdvancedOption_DisplayName_Settings=Settings +AdvancedOption_Tooltip_Settings=Application Settings +OpenIDE-Module-Name=Settings +OptionsCategory_Name_View=General +OptionsCategory_Title_View=View Settings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1998, 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.settings; + +import java.util.prefs.Preferences; + +/** + * + * @author Thomas Wuerthinger + */ +public class Settings { + + public final static String NODE_TEXT = "nodeText"; + public final static String NODE_TEXT_DEFAULT = "[idx] [name]"; + public final static String NODE_WIDTH = "nodeWidth"; + public final static String NODE_WIDTH_DEFAULT = "100"; + public final static String PORT = "port"; + public final static String PORT_DEFAULT = "4444"; + public final static String DIRECTORY = "directory"; + public final static String DIRECTORY_DEFAULT = System.getProperty("user.dir"); + + public static Preferences get() { + return Preferences.userNodeForPackage(Settings.class); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.settings; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import org.netbeans.spi.options.OptionsCategory; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle; + +/** + * + * @author Thomas Wuerthinger + */ +public final class ViewOptionsCategory extends OptionsCategory { + + @Override + public Icon getIcon() { + return new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/settings/settings.png")); + } + + @Override + public String getCategoryName() { + return NbBundle.getMessage(ViewOptionsCategory.class, "OptionsCategory_Name_View"); + } + + @Override + public String getTitle() { + return NbBundle.getMessage(ViewOptionsCategory.class, "OptionsCategory_Title_View"); + } + + @Override + public OptionsPanelController create() { + return new ViewOptionsPanelController(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.settings; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import javax.swing.JComponent; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; + +/** + * + * @author Thomas Wuerthinger + */ +final class ViewOptionsPanelController extends OptionsPanelController { + + private ViewPanel panel; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private boolean changed; + + @Override + public void update() { + getPanel().load(); + changed = false; + } + + @Override + public void applyChanges() { + getPanel().store(); + changed = false; + } + + @Override + public void cancel() { + // need not do anything special, if no changes have been persisted yet + } + + @Override + public boolean isValid() { + return getPanel().valid(); + } + + @Override + public boolean isChanged() { + return changed; + } + + @Override + public HelpCtx getHelpCtx() { + return null; // new HelpCtx("...ID") if you have a help set + } + + @Override + public JComponent getComponent(Lookup masterLookup) { + return getPanel(); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener l) { + pcs.addPropertyChangeListener(l); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener l) { + pcs.removePropertyChangeListener(l); + } + + private ViewPanel getPanel() { + if (panel == null) { + panel = new ViewPanel(this); + } + return panel; + } + + void changed() { + if (!changed) { + changed = true; + pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true); + } + pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.form Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jPanel1" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jPanel1" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="206" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel1"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jLabel1" min="-2" max="-2" attributes="0"/> + <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="39" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="portSpinner" alignment="0" min="-2" pref="63" max="-2" attributes="0"/> + <Component id="nodeWidthSpinner" alignment="0" min="-2" pref="63" max="-2" attributes="0"/> + <Component id="jScrollPane1" alignment="0" min="-2" pref="365" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jScrollPane1" min="-2" max="-2" attributes="0"/> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="nodeWidthSpinner" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="portSpinner" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="73" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="jLabel1"> + <Properties> + <Property name="text" type="java.lang.String" value="Node Text"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel2"> + <Properties> + <Property name="text" type="java.lang.String" value="Node Width"/> + </Properties> + </Component> + <Component class="javax.swing.JSpinner" name="portSpinner"> + </Component> + <Container class="javax.swing.JScrollPane" name="jScrollPane1"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTextArea" name="nodeTextArea"> + <Properties> + <Property name="columns" type="int" value="20"/> + <Property name="rows" type="int" value="5"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JSpinner" name="nodeWidthSpinner"> + </Component> + <Component class="javax.swing.JLabel" name="jLabel3"> + <Properties> + <Property name="text" type="java.lang.String" value="Network Port"/> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> +</Form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.settings; + +/** + * + * @author Thomas Wuerthinger + */ +final class ViewPanel extends javax.swing.JPanel { + + private final ViewOptionsPanelController controller; + + ViewPanel(ViewOptionsPanelController controller) { + this.controller = controller; + initComponents(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + portSpinner = new javax.swing.JSpinner(); + jScrollPane1 = new javax.swing.JScrollPane(); + nodeTextArea = new javax.swing.JTextArea(); + nodeWidthSpinner = new javax.swing.JSpinner(); + jLabel3 = new javax.swing.JLabel(); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, "Node Text"); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, "Node Width"); + + nodeTextArea.setColumns(20); + nodeTextArea.setRows(5); + jScrollPane1.setViewportView(nodeTextArea); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, "Network Port"); + + org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup() + .addContainerGap() + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jLabel1) + .add(jLabel3) + .add(jLabel2)) + .add(39, 39, 39) + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(portSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(nodeWidthSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 365, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jPanel1Layout.createSequentialGroup() + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(18, 18, 18) + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(nodeWidthSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(jLabel2)) + .add(18, 18, 18) + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(portSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(jLabel3))) + .add(jLabel1)) + .add(73, 73, 73)) + ); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 232, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addContainerGap(206, Short.MAX_VALUE)) + ); + }// </editor-fold>//GEN-END:initComponents + void load() { + nodeTextArea.setText(Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT)); + nodeWidthSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.NODE_WIDTH, Settings.NODE_WIDTH_DEFAULT))); + portSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT))); + } + + void store() { + Settings.get().put(Settings.NODE_TEXT, nodeTextArea.getText()); + Settings.get().put(Settings.NODE_WIDTH, nodeWidthSpinner.getValue().toString()); + Settings.get().put(Settings.PORT, portSpinner.getValue().toString()); + } + + boolean valid() { + return true; + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea nodeTextArea; + private javax.swing.JSpinner nodeWidthSpinner; + private javax.swing.JSpinner portSpinner; + // End of variables declaration//GEN-END:variables +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <folder name="OptionsDialog"> + <!-- <file name="Advanced.instance_hidden"/> + <file name="General.instance_hidden"/>--> + <file name="com-sun-hotspot-igv-settings-ViewOptionsCategory.instance"> + <attr name="position" intvalue="100" /> + </file> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.oracle.graal.visualizer.sharedactions" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.oracle.graal.visualizer.sharedactions.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.oracle.graal.visualizer.sharedactions +OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/sharedactions/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.oracle.graal.visualizer.sharedactions-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=c3bdef4e +build.xml.script.CRC32=da3659b1 +build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 +# 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=c3bdef4e +nbproject/build-impl.xml.script.CRC32=567ad23a +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.oracle.graal.visualizer.sharedactions</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.svg</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.actions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.24.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.39.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.dialogs</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.23.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.19.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.oracle.graal.visualizer.sharedactions</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=SharedActions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,118 @@ +/* + * 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.sharedactions; + +import com.sun.hotspot.igv.svg.BatikSVG; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import javax.swing.JFileChooser; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; +import org.openide.util.NbPreferences; + +@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ExportSVGAction", category = "File") +@ActionRegistration(displayName = "Export", iconBase = "com/oracle/graal/visualizer/sharedactions/images/export.png") +@ActionReference(path = "Menu/File", position = 600) +public class ExportSVGAction implements ActionListener { + + private static final String PREFERENCE_DIR = "dir"; + private ExportSVGCookie exportCookie; + + public ExportSVGAction(ExportSVGCookie exportCookie) { + this.exportCookie = exportCookie; + } + + @Override + public void actionPerformed(ActionEvent actionEvent) { + Graphics2D svgGenerator = BatikSVG.createGraphicsObject(); + if (svgGenerator == null) { + NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(message); + return; + } + + File f = selectFile(); + if (f != null) { + exportCookie.paint(svgGenerator); + FileOutputStream os = null; + try { + os = new FileOutputStream(f); + Writer out = new OutputStreamWriter(os, "UTF-8"); + BatikSVG.printToStream(svgGenerator, out, true); + } catch (FileNotFoundException e) { + NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE); + DialogDisplayer.getDefault().notifyLater(message); + + } catch (UnsupportedEncodingException e) { + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + } + } + } + } + } + + private File selectFile() { + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(new javax.swing.filechooser.FileFilter() { + + @Override + public boolean accept(File f) { + return true; + } + + @Override + public String getDescription() { + return "SVG files (*.svg)"; + } + }); + fc.setCurrentDirectory(new File(NbPreferences.forModule(ExportSVGAction.class).get(PREFERENCE_DIR, "~"))); + + + if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + if (!file.getName().contains(".")) { + file = new File(file.getAbsolutePath() + ".svg"); + } + + File dir = file; + if (!dir.isDirectory()) { + dir = dir.getParentFile(); + } + + NbPreferences.forModule(ExportSVGAction.class).put(PREFERENCE_DIR, dir.getAbsolutePath()); + return file; + } + + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGCookie.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +/* + * 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.sharedactions; + +import java.awt.Graphics2D; + +public interface ExportSVGCookie { + void paint(Graphics2D g); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ShowAllAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,50 @@ +/* + * 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.sharedactions; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ShowAllAction", category = "View") +@ActionRegistration(displayName = "Fit Scene to Window", iconBase="com/oracle/graal/visualizer/sharedactions/images/autosize.gif") +@ActionReference(path = "Menu/View", position = 500) +public class ShowAllAction implements ActionListener { + + private List<ZoomCookie> zoomCookies; + + public ShowAllAction(List<ZoomCookie> zoomCookies) { + this.zoomCookies = zoomCookies; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (ZoomCookie c : zoomCookies) { + c.showAll(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomCookie.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,31 @@ +/* + * 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.sharedactions; + +public interface ZoomCookie { + void zoomIn(); + void zoomOut(); + void showAll(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomInAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,50 @@ +/* + * 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.sharedactions; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ZoomInAction", category = "View") +@ActionRegistration(displayName = "Zoom In", iconBase="com/oracle/graal/visualizer/sharedactions/images/zoomin.gif") +@ActionReference(path = "Menu/View", position = 600) +public class ZoomInAction implements ActionListener { + + private List<ZoomCookie> zoomCookies; + + public ZoomInAction(List<ZoomCookie> zoomCookies) { + this.zoomCookies = zoomCookies; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (ZoomCookie c : zoomCookies) { + c.zoomIn(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomOutAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,50 @@ +/* + * 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.sharedactions; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ZoomOutAction", category = "View") +@ActionRegistration(displayName = "Zoom Out", iconBase="com/oracle/graal/visualizer/sharedactions/images/zoomout.gif") +@ActionReference(path = "Menu/View", position = 700) +public class ZoomOutAction implements ActionListener { + + private List<ZoomCookie> zoomCookies; + + public ZoomOutAction(List<ZoomCookie> zoomCookies) { + this.zoomCookies = zoomCookies; + } + + @Override + public void actionPerformed(ActionEvent e) { + for (ZoomCookie c : zoomCookies) { + c.zoomOut(); + } + } +}
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/autosize.gif has changed
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/export.png has changed
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomin.gif has changed
Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomout.gif has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.oracle.graal.visualizer.snapshots" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.oracle.graal.visualizer.snapshots.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.oracle.graal.visualizer.snapshots +OpenIDE-Module-Layer: com/oracle/graal/visualizer/snapshots/layer.xml +OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/snapshots/Bundle.properties +OpenIDE-Module-Requires: org.openide.windows.WindowManager +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.oracle.graal.visualizer.snapshots-impl" basedir=".."> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=8a85c130 +build.xml.script.CRC32=d28dc95d +build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 +# 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=8a85c130 +nbproject/build-impl.xml.script.CRC32=dfcb8f66 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,204 @@ +cluster.path=\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + com.jcraft.jsch,\ + com.jcraft.jzlib,\ + org.apache.commons.codec,\ + org.apache.commons.httpclient,\ + org.apache.commons.io,\ + org.apache.commons.lang,\ + org.apache.commons.logging,\ + org.apache.ws.commons.util,\ + org.apache.xml.resolver,\ + org.apache.xmlrpc,\ + org.eclipse.core.contenttype,\ + org.eclipse.core.jobs,\ + org.eclipse.core.net,\ + org.eclipse.core.runtime,\ + org.eclipse.core.runtime.compatibility.auth,\ + org.eclipse.equinox.app,\ + org.eclipse.equinox.common,\ + org.eclipse.equinox.preferences,\ + org.eclipse.equinox.registry,\ + org.eclipse.equinox.security,\ + org.eclipse.jgit,\ + org.eclipse.mylyn.bugzilla.core,\ + org.eclipse.mylyn.commons.core,\ + org.eclipse.mylyn.commons.net,\ + org.eclipse.mylyn.commons.xmlrpc,\ + org.eclipse.mylyn.tasks.core,\ + org.mozilla.rhino.patched,\ + org.netbeans.api.debugger,\ + org.netbeans.api.java.classpath,\ + org.netbeans.api.xml,\ + org.netbeans.core.browser,\ + org.netbeans.core.execution,\ + org.netbeans.core.ide,\ + org.netbeans.core.io.ui,\ + org.netbeans.core.multiview,\ + org.netbeans.core.nativeaccess,\ + org.netbeans.core.osgi,\ + org.netbeans.lib.cvsclient,\ + org.netbeans.lib.terminalemulator,\ + org.netbeans.libs.antlr3.runtime,\ + org.netbeans.libs.bytelist,\ + org.netbeans.libs.commons_net,\ + org.netbeans.libs.freemarker,\ + org.netbeans.libs.git,\ + org.netbeans.libs.ini4j,\ + org.netbeans.libs.jaxb,\ + org.netbeans.libs.jsr223,\ + org.netbeans.libs.junit4,\ + org.netbeans.libs.jvyamlb,\ + org.netbeans.libs.lucene,\ + org.netbeans.libs.smack,\ + org.netbeans.libs.svnClientAdapter,\ + org.netbeans.libs.svnClientAdapter.javahl,\ + org.netbeans.libs.svnClientAdapter.svnkit,\ + org.netbeans.libs.swingx,\ + org.netbeans.libs.xerces,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.bugtracking,\ + org.netbeans.modules.bugtracking.bridge,\ + org.netbeans.modules.bugzilla,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.csl.api,\ + org.netbeans.modules.css.editor,\ + org.netbeans.modules.css.lib,\ + org.netbeans.modules.css.visual,\ + org.netbeans.modules.db,\ + org.netbeans.modules.db.core,\ + org.netbeans.modules.db.dataview,\ + org.netbeans.modules.db.drivers,\ + org.netbeans.modules.db.kit,\ + org.netbeans.modules.db.metadata.model,\ + org.netbeans.modules.db.mysql,\ + org.netbeans.modules.db.sql.editor,\ + org.netbeans.modules.db.sql.visualeditor,\ + org.netbeans.modules.dbapi,\ + org.netbeans.modules.defaults,\ + org.netbeans.modules.derby,\ + org.netbeans.modules.dlight.nativeexecution,\ + org.netbeans.modules.dlight.terminal,\ + org.netbeans.modules.editor.bookmarks,\ + org.netbeans.modules.editor.bracesmatching,\ + org.netbeans.modules.editor.codetemplates,\ + org.netbeans.modules.editor.completion,\ + org.netbeans.modules.editor.guards,\ + org.netbeans.modules.editor.indent.project,\ + org.netbeans.modules.editor.kit,\ + org.netbeans.modules.editor.macros,\ + org.netbeans.modules.editor.structure,\ + org.netbeans.modules.extbrowser,\ + org.netbeans.modules.extexecution,\ + org.netbeans.modules.extexecution.destroy,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.git,\ + org.netbeans.modules.glassfish.common,\ + org.netbeans.modules.gototest,\ + org.netbeans.modules.gsf.codecoverage,\ + org.netbeans.modules.gsf.testrunner,\ + org.netbeans.modules.html,\ + org.netbeans.modules.html.editor,\ + org.netbeans.modules.html.editor.lib,\ + org.netbeans.modules.html.lexer,\ + org.netbeans.modules.html.parser,\ + org.netbeans.modules.html.validation,\ + org.netbeans.modules.httpserver,\ + org.netbeans.modules.hudson,\ + org.netbeans.modules.hudson.git,\ + org.netbeans.modules.hudson.mercurial,\ + org.netbeans.modules.hudson.subversion,\ + org.netbeans.modules.hudson.tasklist,\ + org.netbeans.modules.ide.kit,\ + org.netbeans.modules.image,\ + org.netbeans.modules.javascript.editing,\ + org.netbeans.modules.javascript.hints,\ + org.netbeans.modules.javascript.kit,\ + org.netbeans.modules.javascript.refactoring,\ + org.netbeans.modules.jellytools.ide,\ + org.netbeans.modules.jumpto,\ + org.netbeans.modules.keyring.impl,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.languages.diff,\ + org.netbeans.modules.languages.manifest,\ + org.netbeans.modules.languages.yaml,\ + org.netbeans.modules.lexer.nbbridge,\ + org.netbeans.modules.localhistory,\ + org.netbeans.modules.mercurial,\ + org.netbeans.modules.netbinox,\ + org.netbeans.modules.parsing.api,\ + org.netbeans.modules.parsing.lucene,\ + org.netbeans.modules.print.editor,\ + org.netbeans.modules.project.ant,\ + org.netbeans.modules.project.libraries,\ + org.netbeans.modules.projectui,\ + org.netbeans.modules.projectui.buildmenu,\ + org.netbeans.modules.projectuiapi,\ + org.netbeans.modules.properties,\ + org.netbeans.modules.properties.syntax,\ + org.netbeans.modules.refactoring.api,\ + org.netbeans.modules.schema2beans,\ + org.netbeans.modules.server,\ + org.netbeans.modules.servletapi,\ + org.netbeans.modules.spellchecker,\ + org.netbeans.modules.spellchecker.apimodule,\ + org.netbeans.modules.spellchecker.bindings.htmlxml,\ + org.netbeans.modules.spellchecker.bindings.properties,\ + org.netbeans.modules.spellchecker.dictionary_en,\ + org.netbeans.modules.spellchecker.kit,\ + org.netbeans.modules.spi.actions,\ + org.netbeans.modules.subversion,\ + org.netbeans.modules.swing.validation,\ + org.netbeans.modules.target.iterator,\ + org.netbeans.modules.tasklist.kit,\ + org.netbeans.modules.tasklist.projectint,\ + org.netbeans.modules.tasklist.todo,\ + org.netbeans.modules.tasklist.ui,\ + org.netbeans.modules.terminal,\ + org.netbeans.modules.usersguide,\ + org.netbeans.modules.utilities,\ + org.netbeans.modules.utilities.project,\ + org.netbeans.modules.versioning,\ + org.netbeans.modules.versioning.indexingbridge,\ + org.netbeans.modules.versioning.system.cvss.installer,\ + org.netbeans.modules.versioning.util,\ + org.netbeans.modules.web.client.tools.api,\ + org.netbeans.modules.web.common,\ + org.netbeans.modules.web.indent,\ + org.netbeans.modules.xml,\ + org.netbeans.modules.xml.axi,\ + org.netbeans.modules.xml.catalog,\ + org.netbeans.modules.xml.core,\ + org.netbeans.modules.xml.jaxb.api,\ + org.netbeans.modules.xml.lexer,\ + org.netbeans.modules.xml.multiview,\ + org.netbeans.modules.xml.retriever,\ + org.netbeans.modules.xml.schema.completion,\ + org.netbeans.modules.xml.schema.model,\ + org.netbeans.modules.xml.tax,\ + org.netbeans.modules.xml.text,\ + org.netbeans.modules.xml.tools,\ + org.netbeans.modules.xml.wsdl.model,\ + org.netbeans.modules.xml.xam,\ + org.netbeans.modules.xml.xdm,\ + org.netbeans.modules.xsl,\ + org.netbeans.spi.debugger.ui,\ + org.netbeans.spi.editor.hints,\ + org.netbeans.spi.navigator,\ + org.netbeans.spi.palette,\ + org.netbeans.spi.tasklist,\ + org.netbeans.spi.viewmodel,\ + org.netbeans.swing.dirchooser,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.options,\ + org.openide.util.enumerations +## Not disabled because of NetBeans bug 206347: +## Applications not using OSGi don't start on NbP 7.1 +# org.netbeans.core.netigso,\ +# org.netbeans.libs.felix,\ +# org.netbeans.libs.osgi,\ +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.6 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.oracle.graal.visualizer.snapshots</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.oracle.graal.visualizer.editor</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.modules.settings</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.33.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.39.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.19.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.11.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.48.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages/> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=SnapshotsView
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.form Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="400" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="300" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + </Layout> +</Form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,128 @@ +/* + * 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.snapshots; + +import com.oracle.graal.visualizer.editor.EditorTopComponent; +import com.oracle.graal.visualizer.util.LookupUtils; +import com.sun.hotspot.igv.data.ChangedEvent; +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.util.RangeSlider; +import com.sun.hotspot.igv.util.RangeSliderModel; +import java.awt.BorderLayout; +import javax.swing.JScrollPane; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.util.Lookup.Result; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; + +@TopComponent.Description(preferredID = SnapshotTopComponent.PREFERRED_ID, persistenceType = TopComponent.PERSISTENCE_ALWAYS) +@TopComponent.Registration(mode = "belowExplorer", openAtStartup = true) +@ActionID(category = "Window", id = "com.oracle.graal.visualizer.snapshots.SnapshotTopComponent") +@ActionReference(path = "Menu/Window") +@TopComponent.OpenActionRegistration(displayName = "Snapshot", preferredID = SnapshotTopComponent.PREFERRED_ID) +public final class SnapshotTopComponent extends TopComponent { + public static final String PREFERRED_ID = "SnapshotTopComponent"; + + private final Result<RangeSliderModel> result; + private final RangeSlider rangeSlider; + private final ChangedEvent<RangeSliderModel> rangeSliderChangedEvent = new ChangedEvent<RangeSliderModel>(null); + private final LookupListener lookupListener = new LookupListener() { + + @Override + public void resultChanged(LookupEvent le) { + update(); + } + }; + + private final ChangedListener<RangeSliderModel> rangeSliderChangedListener = new ChangedListener<RangeSliderModel>(){ + + @Override + public void changed(RangeSliderModel source) { + rangeSliderChangedEvent.fire(); + } + }; + + public SnapshotTopComponent() { + initComponents(); + setName("Snapshot Window"); + setToolTipText("This is a Snapshot window"); + + result = LookupUtils.getLastActiveDelegatingLookup(EditorTopComponent.class).lookupResult(RangeSliderModel.class); + result.addLookupListener(lookupListener); + this.rangeSlider = new RangeSlider(null); + this.setLayout(new BorderLayout()); + this.add(new JScrollPane(rangeSlider), BorderLayout.CENTER); + update(); + } + + private void update() { + RangeSliderModel newModel; + if (result.allInstances().size() > 0) { + newModel = result.allInstances().iterator().next(); + } else { + newModel = null; + } + if (rangeSlider.getModel() != null) { + rangeSlider.getModel().getChangedEvent().removeListener(rangeSliderChangedListener); + } + rangeSlider.setModel(newModel); + rangeSliderChangedEvent.changeObject(newModel); + if (newModel != null) { + newModel.getChangedEvent().addListener(rangeSliderChangedListener); + } + } + + public ChangedEvent<RangeSliderModel> getRangeSliderChangedEvent() { + return rangeSliderChangedEvent; + } + + public static SnapshotTopComponent findInstance() { + return (SnapshotTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID); + } + + /** + * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// </editor-fold>//GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/NextSnapshotAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,66 @@ +/* + * 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.snapshots.actions; + +import com.oracle.graal.visualizer.snapshots.SnapshotTopComponent; +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.util.RangeSliderModel; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.editor.actions.NextSnapshotAction", category = "View") +@ActionRegistration(displayName = "Next snapshot", iconBase = "com/oracle/graal/visualizer/snapshots/images/next_snapshot.png") +@ActionReference(path = "Menu/View", position = 150) +public final class NextSnapshotAction extends AbstractAction{ + + private RangeSliderModel model; + + public NextSnapshotAction() { + SnapshotTopComponent.findInstance().getRangeSliderChangedEvent().addListenerAndFire(changeListener); + } + private final ChangedListener<RangeSliderModel> changeListener = new ChangedListener<RangeSliderModel>() { + + @Override + public void changed(RangeSliderModel source) { + model = source; + setEnabled(model != null && model.getSecondPosition() != model.getPositions().size() - 1); + } + }; + + @Override + public void actionPerformed(ActionEvent e) { + if (model != null) { + int fp = model.getFirstPosition(); + int sp = model.getSecondPosition(); + if (sp != model.getPositions().size() - 1) { + int nfp = fp + 1; + int nsp = sp + 1; + model.setPositions(nfp, nsp); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/PrevSnapshotAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008, 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.snapshots.actions; + +import com.oracle.graal.visualizer.snapshots.SnapshotTopComponent; +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.util.RangeSliderModel; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; + +@ActionID(id = "com.oracle.graal.visualizer.editor.actions.PrevSnapshotAction", category = "View") +@ActionRegistration(displayName = "Previous snapshot", iconBase = "com/oracle/graal/visualizer/snapshots/images/prev_snapshot.png") +@ActionReference(path = "Menu/View", position = 100) +public final class PrevSnapshotAction extends AbstractAction { + + private RangeSliderModel model; + + public PrevSnapshotAction() { + SnapshotTopComponent.findInstance().getRangeSliderChangedEvent().addListenerAndFire(changeListener); + } + private final ChangedListener<RangeSliderModel> changeListener = new ChangedListener<RangeSliderModel>() { + + @Override + public void changed(RangeSliderModel source) { + model = source; + setEnabled(model != null && model.getFirstPosition() != 0); + } + }; + + @Override + public void actionPerformed(ActionEvent e) { + if (model != null) { + int fp = model.getFirstPosition(); + int sp = model.getSecondPosition(); + if (fp != 0) { + int nfp = fp - 1; + int nsp = sp - 1; + model.setPositions(nfp, nsp); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/belowExplorerWsmode.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mode version="2.4"> + <name unique="belowExplorer"/> + <kind type="view"/> + <state type="joined"/> + <constraints> + <path orientation="horizontal" number="20" weight="0.3"/> + <path orientation="vertical" number="21" weight="0.548"/> + </constraints> + <bounds x="0" y="0" width="0" height="0"/> + <frame state="0"/> + + <empty-behavior permanent="false"/> +</mode>
Binary file visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/next_snapshot.png has changed
Binary file visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/prev_snapshot.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd"> +<filesystem> + <folder name="Windows2"> + <folder name="Modes"> + <file name="belowExplorer.wsmode" url="belowExplorerWsmode.xml"/> + </folder> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.util" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.util.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.util +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/util/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.util-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=a470a16f +build.xml.script.CRC32=466cf03b +build.xml.stylesheet.CRC32=05353c81 +# 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=a470a16f +nbproject/build-impl.xml.script.CRC32=39f45e01 +nbproject/build-impl.xml.stylesheet.CRC32=3f8b4615
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.util</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.api.visual</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>2.27.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.nodes</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.14.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.48.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.oracle.graal.visualizer.util</package> + <package>com.sun.hotspot.igv.util</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/oracle/graal/visualizer/util/LookupUtils.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,123 @@ +/* + * 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.util; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.Action; +import org.openide.util.ContextAwareAction; +import org.openide.util.Lookup; +import org.openide.util.Lookup.Provider; +import org.openide.util.lookup.Lookups; +import org.openide.windows.TopComponent; + +/** + * Utilities that build upon the Lookup API. + */ +public class LookupUtils { + + + /** + * Creates a new lookup that will delegate to the last open window of a specified top component class. If the window is closed, the lookup will be empty. + * @param clazz the class identifying the top component type + * @return a delegating lookup + */ + public static Lookup getLastActiveDelegatingLookup(Class<?> clazz) { + final TopComponentLookup topComponentLookupImpl = new TopComponentLookup(clazz); + TopComponent.getRegistry().addPropertyChangeListener(topComponentLookupImpl); + return topComponentLookupImpl.lookup; + } + + public static Iterable<Action> lookupActions(String path) { + return lookupActions(path, null); + } + + public static Iterable<Action> lookupActions(String path, Lookup context) { + List<Action> actions = new ArrayList<>(); + for (Action a : Lookups.forPath(path).lookupAll(Action.class)) { + Action newAction = a; + if (a instanceof ContextAwareAction && context != null) { + newAction = ((ContextAwareAction) a).createContextAwareInstance(context); + } + newAction.putValue(Action.SHORT_DESCRIPTION, newAction.getValue(Action.NAME)); + actions.add(newAction); + + } + return actions; + } + + private static class TopComponentLookup implements PropertyChangeListener { + private final Class<?> clazz; + private final Lookup lookup; + private TopComponent lastActive; + + private final Provider lookupProvider = new Provider() { + + @Override + public Lookup getLookup() { + if (lastActive == null) { + return Lookup.EMPTY; + } else { + return lastActive.getLookup(); + } + } + }; + + public TopComponentLookup(Class<?> clazz) { + this.clazz = clazz; + lookup = Lookups.proxy(lookupProvider); + update(); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + update(); + } + + private void update() { + TopComponent curActivated = TopComponent.getRegistry().getActivated(); + if (curActivated != lastActive) { + if (clazz.isAssignableFrom(curActivated.getClass())) { + // We have a new top component for our lookup. + lastActive = curActivated; + refreshLookup(); + } else { + // We have no new top component. Check if the old one is still opened. + if (lastActive != null && !TopComponent.getRegistry().getOpened().contains(lastActive)) { + // The top component was closed => Remove lookup. + lastActive = null; + refreshLookup(); + } + } + } + } + + private void refreshLookup() { + lookup.lookup(Object.class); + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.util; + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.action.WidgetAction.State; +import org.netbeans.api.visual.action.WidgetAction.WidgetMouseWheelEvent; +import org.netbeans.api.visual.animator.SceneAnimator; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public class BoundedZoomAction extends WidgetAction.Adapter { + + private double minFactor = 0.0; + private double maxFactor = Double.MAX_VALUE; + private double zoomMultiplier; + private boolean useAnimator; + + public BoundedZoomAction(double zoomMultiplier, boolean useAnimator) { + this.zoomMultiplier = zoomMultiplier; + this.useAnimator = useAnimator; + } + + public double getMinFactor() { + return minFactor; + } + + public void setMinFactor(double d) { + minFactor = d; + } + + public double getMaxFactor() { + return maxFactor; + } + + public void setMaxFactor(double d) { + maxFactor = d; + } + + private JScrollPane findScrollPane(JComponent component) { + for (;;) { + if (component == null) { + return null; + } + if (component instanceof JScrollPane) { + return ((JScrollPane) component); + } + Container parent = component.getParent(); + if (!(parent instanceof JComponent)) { + return null; + } + component = (JComponent) parent; + } + } + + @Override + public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) { + final Scene scene = widget.getScene(); + int amount = event.getWheelRotation(); + JScrollPane scrollPane = findScrollPane(scene.getView()); + Point viewPosition = null; + Point mouseLocation = scene.convertSceneToView(event.getPoint()); + int xOffset = 0; + int yOffset = 0; + Rectangle bounds = new Rectangle(scene.getBounds()); + Dimension componentSize = new Dimension(scene.getView().getPreferredSize()); + + if (scrollPane != null) { + viewPosition = new Point(scrollPane.getViewport().getViewPosition()); + xOffset = (mouseLocation.x - viewPosition.x); + yOffset = (mouseLocation.y - viewPosition.y); + viewPosition.x += xOffset; + viewPosition.y += yOffset; + } + + if (useAnimator) { + SceneAnimator sceneAnimator = scene.getSceneAnimator(); + synchronized (sceneAnimator) { + double zoom = sceneAnimator.isAnimatingZoomFactor() ? sceneAnimator.getTargetZoomFactor() : scene.getZoomFactor(); + while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) { + zoom /= zoomMultiplier; + if (viewPosition != null) { + viewPosition.x /= zoomMultiplier; + viewPosition.y /= zoomMultiplier; + bounds.width /= zoomMultiplier; + bounds.height /= zoomMultiplier; + componentSize.width /= zoomMultiplier; + componentSize.height /= zoomMultiplier; + } + amount--; + } + while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) { + zoom *= zoomMultiplier; + if (viewPosition != null) { + viewPosition.x *= zoomMultiplier; + viewPosition.y *= zoomMultiplier; + bounds.width *= zoomMultiplier; + bounds.height *= zoomMultiplier; + componentSize.width *= zoomMultiplier; + componentSize.height *= zoomMultiplier; + } + amount++; + } + sceneAnimator.animateZoomFactor(zoom); + } + } else { + double zoom = scene.getZoomFactor(); + while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) { + zoom /= zoomMultiplier; + if (viewPosition != null) { + viewPosition.x /= zoomMultiplier; + viewPosition.y /= zoomMultiplier; + bounds.width /= zoomMultiplier; + bounds.height /= zoomMultiplier; + componentSize.width /= zoomMultiplier; + componentSize.height /= zoomMultiplier; + } + amount--; + } + while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) { + zoom *= zoomMultiplier; + if (viewPosition != null) { + viewPosition.x *= zoomMultiplier; + viewPosition.y *= zoomMultiplier; + bounds.width *= zoomMultiplier; + bounds.height *= zoomMultiplier; + componentSize.width *= zoomMultiplier; + componentSize.height *= zoomMultiplier; + } + amount++; + } + scene.setZoomFactor(zoom); + } + + if (scrollPane != null) { + scene.validate(); // Call validate to update size of scene + Dimension size = scrollPane.getViewport().getExtentSize(); + viewPosition.x -= xOffset; + viewPosition.y -= yOffset; + scene.resolveBounds(scene.getLocation(), bounds); + scene.getView().setPreferredSize(componentSize); + scene.getView().revalidate(); + scene.getView().addNotify(); + scrollPane.getViewport().setViewPosition(viewPosition); + } + + return WidgetAction.State.CONSUMED; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Util
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.util; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import javax.swing.Icon; + +/** + * + * @author Thomas Wuerthinger + */ +public class ColorIcon implements Icon { + + private Color color; + + public ColorIcon(Color c) { + color = c; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + g.setColor(color); + g.fillRect(x, y, 16, 16); + } + + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/CompilationViewModel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package com.sun.hotspot.igv.util; + +import com.sun.hotspot.igv.data.*; +import java.awt.Color; +import java.util.List; + +public class CompilationViewModel implements ChangedEventProvider<CompilationViewModel> { + + private final ChangedEvent<CompilationViewModel> changedEvent = new ChangedEvent<>(this); + private final RangeSliderModel model; + private final Group group; + + @Override + public ChangedEvent<CompilationViewModel> getChangedEvent() { + return changedEvent; + } + + public CompilationViewModel(RangeSliderModel model, Group group) { + this.model = model; + this.group = group; + model.getChangedEvent().addListener(rangeSliderChangedListener); + } + + private final ChangedListener<RangeSliderModel> rangeSliderChangedListener = new ChangedListener<RangeSliderModel>() { + @Override + public void changed(RangeSliderModel source) { + changedEvent.fire(); + } + }; + + public InputGraph getFirstSnapshot() { + return group.getGraphs().get(model.getFirstPosition()); + } + + public InputGraph getSecondSnapshot() { + return group.getGraphs().get(model.getSecondPosition()); + } + + public void setColors(List<Color> colors) { + model.setColors(colors); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.util; + +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public class DoubleClickAction extends WidgetAction.Adapter { + + private DoubleClickHandler handler; + + public DoubleClickAction(DoubleClickHandler handler) { + this.handler = handler; + } + + @Override + public WidgetAction.State mouseClicked(Widget widget, WidgetAction.WidgetMouseEvent event) { + if (event.getClickCount() > 1) { + handler.handleDoubleClick(widget, event); + return WidgetAction.State.CONSUMED; + } + return WidgetAction.State.REJECTED; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.util; + +import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public interface DoubleClickHandler { + + public void handleDoubleClick(Widget w, WidgetMouseEvent e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.util; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.JComponent; +import org.netbeans.api.visual.widget.Scene; + +/** + * @author David Kaspar + * @author Thomas Wuerthinger + */ +public class ExtendedSatelliteComponent extends JComponent implements MouseListener, MouseMotionListener, Scene.SceneListener, ComponentListener { + + private Scene scene; + private Image image; + private int imageWidth; + private int imageHeight; + + public ExtendedSatelliteComponent(Scene scene) { + this.scene = scene; + setDoubleBuffered(true); + setPreferredSize(new Dimension(128, 128)); + addMouseListener(this); + addMouseMotionListener(this); + } + + @Override + public void addNotify() { + super.addNotify(); + scene.addSceneListener(this); + JComponent viewComponent = scene.getView(); + if (viewComponent == null) { + viewComponent = scene.createView(); + } + viewComponent.addComponentListener(this); + repaint(); + } + + @Override + public void removeNotify() { + scene.getView().removeComponentListener(this); + scene.removeSceneListener(this); + super.removeNotify(); + } + + public void update() { + this.image = null; + repaint(); + } + + @Override + public void paint(Graphics g) { + Graphics2D gr = (Graphics2D) g; + super.paint(g); + Rectangle bounds = scene.getBounds(); + Dimension size = getSize(); + + double sx = bounds.width > 0 ? (double) size.width / bounds.width : 0.0; + double sy = bounds.width > 0 ? (double) size.height / bounds.height : 0.0; + double scale = Math.min(sx, sy); + + int vw = (int) (scale * bounds.width); + int vh = (int) (scale * bounds.height); + int vx = (size.width - vw) / 2; + int vy = (size.height - vh) / 2; + + + if (image == null || vw != imageWidth || vh != imageHeight) { + + imageWidth = vw; + imageHeight = vh; + image = this.createImage(imageWidth, imageHeight); + Graphics2D ig = (Graphics2D) image.getGraphics(); + ig.scale(scale, scale); + scene.paint(ig); + } + + gr.drawImage(image, vx, vy, this); + + JComponent component = scene.getView(); + double zoomFactor = scene.getZoomFactor(); + Rectangle viewRectangle = component != null ? component.getVisibleRect() : null; + if (viewRectangle != null) { + Rectangle window = new Rectangle( + (int) ((double) viewRectangle.x * scale / zoomFactor), + (int) ((double) viewRectangle.y * scale / zoomFactor), + (int) ((double) viewRectangle.width * scale / zoomFactor), + (int) ((double) viewRectangle.height * scale / zoomFactor)); + window.translate(vx, vy); + gr.setColor(new Color(200, 200, 200, 128)); + gr.fill(window); + gr.setColor(Color.BLACK); + gr.drawRect(window.x, window.y, window.width - 1, window.height - 1); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + moveVisibleRect(e.getPoint()); + } + + @Override + public void mouseReleased(MouseEvent e) { + moveVisibleRect(e.getPoint()); + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseDragged(MouseEvent e) { + moveVisibleRect(e.getPoint()); + } + + @Override + public void mouseMoved(MouseEvent e) { + } + + private void moveVisibleRect(Point center) { + JComponent component = scene.getView(); + if (component == null) { + return; + } + double zoomFactor = scene.getZoomFactor(); + Rectangle bounds = scene.getBounds(); + Dimension size = getSize(); + + double sx = bounds.width > 0 ? (double) size.width / bounds.width : 0.0; + double sy = bounds.width > 0 ? (double) size.height / bounds.height : 0.0; + double scale = Math.min(sx, sy); + + int vw = (int) (scale * bounds.width); + int vh = (int) (scale * bounds.height); + int vx = (size.width - vw) / 2; + int vy = (size.height - vh) / 2; + + int cx = (int) ((double) (center.x - vx) / scale * zoomFactor); + int cy = (int) ((double) (center.y - vy) / scale * zoomFactor); + + Rectangle visibleRect = component.getVisibleRect(); + visibleRect.x = cx - visibleRect.width / 2; + visibleRect.y = cy - visibleRect.height / 2; + component.scrollRectToVisible(visibleRect); + + } + + @Override + public void sceneRepaint() { + } + + @Override + public void sceneValidating() { + } + + @Override + public void sceneValidated() { + } + + @Override + public void componentResized(ComponentEvent e) { + repaint(); + } + + @Override + public void componentMoved(ComponentEvent e) { + repaint(); + } + + @Override + public void componentShown(ComponentEvent e) { + } + + @Override + public void componentHidden(ComponentEvent e) { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.util; + +import java.awt.event.MouseEvent; +import javax.swing.JPanel; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.SelectProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.action.WidgetAction.State; +import org.netbeans.api.visual.action.WidgetAction.WidgetKeyEvent; +import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public class ExtendedSelectAction extends WidgetAction.Adapter { + + private WidgetAction innerAction; + private JPanel panel; + + public ExtendedSelectAction(SelectProvider provider) { + innerAction = ActionFactory.createSelectAction(provider); + panel = new JPanel(); + } + + @Override + public State mousePressed(Widget widget, WidgetMouseEvent event) { + // TODO: Solve this differently? + if (event.getButton() != MouseEvent.BUTTON2) { + return innerAction.mousePressed(widget, new WidgetMouseEvent(event.getEventID(), new MouseEvent(panel, (int) event.getEventID(), event.getWhen(), event.getModifiersEx(), event.getPoint().x, event.getPoint().y, event.getClickCount(), event.isPopupTrigger(), MouseEvent.BUTTON1))); + } else { + return super.mousePressed(widget, event); + } + } + + @Override + public State mouseReleased(Widget widget, WidgetMouseEvent event) { + return innerAction.mouseReleased(widget, event); + } + + @Override + public State keyTyped(Widget widget, WidgetKeyEvent event) { + return innerAction.keyTyped(widget, event); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1998, 2008, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.util; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.Property; +import java.lang.reflect.InvocationTargetException; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; + +/** + * + * @author Thomas Wuerthinger + */ +public class PropertiesSheet { + + public static void initializeSheet(final Properties properties, Sheet s) { + + Sheet.Set set1 = Sheet.createPropertiesSet(); + set1.setDisplayName("Properties"); + for (final Property p : properties) { + Node.Property<String> prop = new Node.Property<String>(String.class) { + + @Override + public boolean canRead() { + return true; + } + + @Override + public String getValue() throws IllegalAccessException, InvocationTargetException { + return p.getValue(); + } + + @Override + public boolean canWrite() { + return false; + } + + @Override + public void setValue(String arg0) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + properties.setProperty(p.getName(), arg0); + } + }; + prop.setName(p.getName()); + set1.put(prop); + } + s.put(set1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,262 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.util; + +import com.sun.hotspot.igv.data.ChangedListener; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.util.List; +import javax.swing.JComponent; + +public final class RangeSlider extends JComponent { + + public static final int BAR_THICKNESS = 2; + public static final int BAR_CIRCLE_SIZE = 9; + public static final int MOUSE_ENDING_OFFSET = 3; + public static final Color BACKGROUND_COLOR = Color.white; + public static final Color BAR_COLOR = Color.black; + public static final Color BAR_SELECTION_COLOR = new Color(255, 0, 0, 120); + public static final Color TEXT_SELECTION_COLOR = new Color(200, 200, 200, 255); + public static final int ITEM_HEIGHT = 30; + public static final int ITEM_WIDTH = 30; + private RangeSliderModel model; + private Point startPoint; + private RangeSliderModel tempModel; + private Point lastMouseMove; + + public RangeSlider(RangeSliderModel newModel) { + this.addMouseMotionListener(mouseMotionListener); + this.addMouseListener(mouseListener); + setModel(newModel); + } + + private RangeSliderModel getPaintingModel() { + if (tempModel != null) { + return tempModel; + } + return model; + } + + @Override + public Dimension getPreferredSize() { + if (getPaintingModel() != null) { + Graphics g = this.getGraphics(); + int maxWidth = 0; + List<String> list = getPaintingModel().getPositions(); + for (int i = 0; i < list.size(); i++) { + String curS = list.get(i); + if (curS != null && curS.length() > 0) { + FontMetrics metrics = g.getFontMetrics(); + Rectangle bounds = metrics.getStringBounds(curS, g).getBounds(); + maxWidth = Math.max(maxWidth, (int) bounds.getWidth()); + } + } + return new Dimension(maxWidth + ITEM_WIDTH, ITEM_HEIGHT * list.size()); + } + return super.getPreferredSize(); + } + private ChangedListener<RangeSliderModel> modelChangedListener = new ChangedListener<RangeSliderModel>() { + + @Override + public void changed(RangeSliderModel source) { + update(); + } + }; + + private void update() { + this.repaint(); + } + + private Rectangle getItemBounds(int index) { + Rectangle r = new Rectangle(); + r.width = ITEM_WIDTH; + r.height = ITEM_HEIGHT; + r.x = 0; + r.y = ITEM_HEIGHT * index; + return r; + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + int width = getWidth(); + int height = getHeight(); + + g2.setColor(BACKGROUND_COLOR); + g2.fillRect(0, 0, width, height); + + // Nothing to paint? + if (getPaintingModel() == null || getPaintingModel().getPositions().isEmpty()) { + return; + } + + paintSelected(g2); + paintBar(g2); + + } + + private void fillRect(Graphics2D g, int startX, int startY, int endY, int thickness) { + g.fillRect(startX - thickness / 2, startY, thickness, endY - startY); + } + + private void paintBar(Graphics2D g) { + List<String> list = getPaintingModel().getPositions(); + + g.setColor(BAR_COLOR); + Rectangle firstItemBounds = getItemBounds(0); + Rectangle lastItemBounds = getItemBounds(list.size() - 1); + fillRect(g, (int) firstItemBounds.getCenterX(), (int) firstItemBounds.getCenterY(), (int) lastItemBounds.getCenterY(), BAR_THICKNESS); + + for (int i = 0; i < list.size(); i++) { + Rectangle curItemBounds = getItemBounds(i); + g.setColor(getPaintingModel().getColors().get(i)); + g.fillOval((int) curItemBounds.getCenterX() - BAR_CIRCLE_SIZE / 2, (int) curItemBounds.getCenterY() - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE); + g.setColor(Color.black); + g.drawOval((int) curItemBounds.getCenterX() - BAR_CIRCLE_SIZE / 2, (int) curItemBounds.getCenterY() - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE); + + String curS = list.get(i); + if (curS != null && curS.length() > 0) { + FontMetrics metrics = g.getFontMetrics(); + Rectangle bounds = metrics.getStringBounds(curS, g).getBounds(); + g.setColor(Color.black); + g.drawString(curS, curItemBounds.x + curItemBounds.width, (int) curItemBounds.getCenterY() + bounds.height / 2 - 2); + } + } + + } + + private void paintSelected(Graphics2D g) { + List<String> list = getPaintingModel().getPositions(); + for (int i = 0; i < list.size(); i++) { + Rectangle curItemBounds = getItemBounds(i); + if (lastMouseMove != null && curItemBounds.y <= lastMouseMove.y && curItemBounds.y + curItemBounds.height > lastMouseMove.y) { + g.setColor(TEXT_SELECTION_COLOR); + g.fillRect(0, curItemBounds.y, getWidth(), curItemBounds.height); + } + } + final Rectangle barBounds = getBarBounds(); + + g.setColor(BAR_SELECTION_COLOR); + g.fill(barBounds); + } + + private Rectangle getBarBounds() { + final Rectangle startItemBounds = getItemBounds(getPaintingModel().getFirstPosition()); + final Rectangle endItemBounds = getItemBounds(getPaintingModel().getSecondPosition()); + int startY = startItemBounds.y; + int endY = endItemBounds.y + endItemBounds.height; + return new Rectangle(0, startY, getWidth(), endY - startY); + } + + private int getIndexFromPosition(int y) { + for (int i = 0; i < getPaintingModel().getPositions().size() - 1; i++) { + Rectangle bounds = getItemBounds(i); + if (bounds.y <= y && bounds.y + bounds.height >= y) { + return i; + } + } + return getPaintingModel().getPositions().size() - 1; + } + private final MouseMotionListener mouseMotionListener = new MouseMotionListener() { + + @Override + public void mouseDragged(MouseEvent e) { + if (startPoint != null) { + int startIndex = getIndexFromPosition(startPoint.y); + int curIndex = getIndexFromPosition(e.getPoint().y); + tempModel.setPositions(startIndex, curIndex); + } + } + + @Override + public void mouseMoved(MouseEvent e) { + lastMouseMove = e.getPoint(); + update(); + } + }; + private final MouseListener mouseListener = new MouseListener() { + + @Override + public void mouseClicked(MouseEvent e) { + if (model != null) { + int index = getIndexFromPosition(e.getPoint().y); + model.setPositions(index, index); + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (model != null) { + int index = getIndexFromPosition(e.getPoint().y); + startPoint = e.getPoint(); + tempModel = model.copy(); + tempModel.getChangedEvent().addListener(modelChangedListener); + tempModel.setPositions(index, index); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (tempModel != null) { + model.setPositions(tempModel.getFirstPosition(), tempModel.getSecondPosition()); + tempModel = null; + startPoint = null; + } + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + lastMouseMove = null; + repaint(); + } + }; + + public RangeSliderModel getModel() { + return model; + } + + public void setModel(RangeSliderModel newModel) { + if (newModel != this.model) { + if (this.model != null) { + this.model.getChangedEvent().removeListener(modelChangedListener); + } + this.model = newModel; + if (newModel != null) { + newModel.getChangedEvent().addListener(modelChangedListener); + } + this.tempModel = null; + update(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1998, 2008, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.hotspot.igv.util; + +import com.sun.hotspot.igv.data.ChangedEvent; +import com.sun.hotspot.igv.data.ChangedEventProvider; +import java.awt.Color; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class RangeSliderModel implements ChangedEventProvider<RangeSliderModel> { + + // Warning: Update setData method if fields are added + private ChangedEvent<RangeSliderModel> changedEvent; + private List<String> positions; + private int firstPosition; + private int secondPosition; + private List<Color> colors; + + public void setData(RangeSliderModel model) { + boolean changed = false; + changed |= (positions != model.positions); + positions = model.positions; + changed |= (firstPosition != model.firstPosition); + firstPosition = model.firstPosition; + changed |= (secondPosition != model.secondPosition); + secondPosition = model.secondPosition; + changed |= (colors != model.colors); + colors = model.colors; + if (changed) { + changedEvent.fire(); + } + } + + public RangeSliderModel(List<String> positions) { + assert positions.size() > 0; + this.changedEvent = new ChangedEvent<>(this); + setPositions(positions); + } + + protected final void setPositions(List<String> positions) { + this.positions = positions; + colors = new ArrayList<>(); + for (int i = 0; i < positions.size(); i++) { + colors.add(Color.black); + } + firstPosition = Math.min(firstPosition, positions.size() - 1); + secondPosition = Math.min(secondPosition, positions.size() - 1); + changedEvent.fire(); + } + + public void setColors(List<Color> colors) { + this.colors = colors; + changedEvent.fire(); + } + + public List<Color> getColors() { + return colors; + } + + public RangeSliderModel copy() { + RangeSliderModel newModel = new RangeSliderModel(positions); + newModel.setData(this); + return newModel; + } + + public List<String> getPositions() { + return Collections.unmodifiableList(positions); + } + + public int getFirstPosition() { + return firstPosition; + } + + public int getSecondPosition() { + return secondPosition; + } + + public void setPositions(int fp, int sp) { + assert fp >= 0 && fp < positions.size(); + assert sp >= 0 && sp < positions.size(); + firstPosition = fp; + secondPosition = sp; + ensureOrder(); + changedEvent.fire(); + } + + private void ensureOrder() { + if (secondPosition < firstPosition) { + int tmp = secondPosition; + secondPosition = firstPosition; + firstPosition = tmp; + } + } + + @Override + public ChangedEvent<RangeSliderModel> getChangedEvent() { + return changedEvent; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="com.sun.hotspot.igv.view" default="netbeans" basedir="."> + <description>Builds, tests, and runs the project com.sun.hotspot.igv.view.</description> + <import file="nbproject/build-impl.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/manifest.mf Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.view +OpenIDE-Module-Layer: com/sun/hotspot/igv/view/layer.xml +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/view/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="com.sun.hotspot.igv.view-impl" basedir=".."> + <property file="nbproject/private/suite-private.properties"/> + <property file="nbproject/suite.properties"/> + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail> + <property file="${suite.dir}/nbproject/private/platform-private.properties"/> + <property file="${suite.dir}/nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/> + <fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'"> + <condition> + <not> + <available file="${harness.dir}" type="dir"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/build.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=2de95ef6 +build.xml.script.CRC32=31afe4b1 +build.xml.stylesheet.CRC32=79c3b980 +# 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=2de95ef6 +nbproject/build-impl.xml.script.CRC32=fa7a4119 +nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,29 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + harness,\ + ide8,\ + java1,\ + nb6.0,\ + profiler2 +disabled.modules=\ + org.netbeans.core.execution,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.modules.applemenu,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.masterfs,\ + org.netbeans.modules.options.keymap,\ + org.netbeans.modules.sendopts,\ + org.netbeans.modules.templates,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.util.enumerations +enabled.clusters=\ + platform7 +nbjdk.active=JDK_1.6 +nbplatform.active=default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3"> + <code-name-base>com.sun.hotspot.igv.view</code-name-base> + <suite-component/> + <module-dependencies> + <dependency> + <code-name-base>com.oracle.graal.visualizer.editor</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.oracle.graal.visualizer.sharedactions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.data</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.difference</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.filter</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.graph</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.hierarchicallayout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.layout</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.settings</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.svg</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>com.sun.hotspot.igv.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.api.visual</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>2.27.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.netbeans.spi.quicksearch</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.0</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.actions</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.21.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.awt</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.30.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.dialogs</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.18.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.loaders</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.nodes</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>7.20.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.14.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.util.lookup</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>8.6.1</specification-version> + </run-dependency> + </dependency> + <dependency> + <code-name-base>org.openide.windows</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>6.39.1</specification-version> + </run-dependency> + </dependency> + </module-dependencies> + <public-packages> + <package>com.sun.hotspot.igv.view</package> + </public-packages> + </data> + </configuration> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/nbproject/suite.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +com.sun.hotspot.igv.view.scene.GraphCompilationViewerFactory
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=View \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,4 @@ +CTL_EditorAction=Open Editor Window +CTL_EnableBlockLayoutAction=Enable block layout +CTL_NodeFindAction=Find +CTL_ExportAction=Export current graph...
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.actions; + +import com.oracle.graal.visualizer.editor.EditorTopComponent; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CallableSystemAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class ExpandPredecessorsAction extends CallableSystemAction { + + @Override + public void performAction() { + EditorTopComponent editor = EditorTopComponent.getActive(); + if (editor != null) { + //editor.expandPredecessors(); + } + } + + @Override + public String getName() { + return "Expand Above"; + } + + @Override + protected void initialize() { + super.initialize(); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.actions; + +import com.oracle.graal.visualizer.editor.EditorTopComponent; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CallableSystemAction; + +/** + * + * @author Thomas Wuerthinger + */ +public final class ExpandSuccessorsAction extends CallableSystemAction { + + @Override + public void performAction() { + EditorTopComponent editor = EditorTopComponent.getActive(); + if (editor != null) { + //editor.expandSuccessors(); + } + } + + @Override + public String getName() { + return "Expand Below"; + } + + @Override + protected void initialize() { + super.initialize(); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.actions; + +import com.oracle.graal.visualizer.editor.EditorTopComponent; +import java.awt.Event; +import java.awt.event.KeyEvent; +import javax.swing.Action; +import javax.swing.KeyStroke; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CallableSystemAction; + +/** + * + * @author Thomas Wuerthinger + */ +@ActionID(id = "com.sun.hotspot.igv.view.actions.ExtractAction", category = "View") +@ActionRegistration(displayName = "Extract nodes") +@ActionReference(path = "Menu/View", position = 300) +public final class ExtractAction extends CallableSystemAction { + + @Override + public void performAction() { + EditorTopComponent editor = EditorTopComponent.getActive(); + if (editor != null) { + //editor.extract(); + } + } + + public ExtractAction() { + putValue(Action.SHORT_DESCRIPTION, "Extract current set of selected nodes"); + putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK, false)); + } + + @Override + public String getName() { + return "Extract action"; + } + + @Override + protected void initialize() { + super.initialize(); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/view/images/extract.gif"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.actions; + +import com.oracle.graal.visualizer.editor.EditorTopComponent; +import java.awt.Event; +import java.awt.event.KeyEvent; +import javax.swing.Action; +import javax.swing.KeyStroke; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionRegistration; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CallableSystemAction; + +/** + * + * @author Thomas Wuerthinger + */ +@ActionID(id = "com.sun.hotspot.igv.view.actions.HideAction", category = "View") +@ActionRegistration(displayName = "Hide nodes") +@ActionReference(path = "Menu/View", position = 400) +public final class HideAction extends CallableSystemAction { + + @Override + public void performAction() { + EditorTopComponent editor = EditorTopComponent.getActive(); + if (editor != null) { + //editor.hideNodes(); + } + } + + public HideAction() { + putValue(Action.SHORT_DESCRIPTION, "Hide selected nodes"); + putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.CTRL_MASK, false)); + } + + @Override + public String getName() { + return "Hide"; + } + + @Override + protected void initialize() { + super.initialize(); + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } + + @Override + protected String iconResource() { + return "com/sun/hotspot/igv/view/images/hide.gif"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.actions; + +import org.netbeans.api.visual.action.HoverProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.action.WidgetAction.State; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public class MouseOverAction extends WidgetAction.Adapter { + + private long eventID = Integer.MIN_VALUE; + private HoverProvider provider; + + public MouseOverAction(HoverProvider provider) { + this.provider = provider; + } + + @Override + public State mouseMoved(Widget widget, WidgetMouseEvent event) { + long id = event.getEventID(); + if (id != eventID) { + eventID = id; + provider.widgetHovered(widget); + } + return State.REJECTED; + } + + @Override + public State mouseExited(Widget widget, WidgetMouseEvent event) { + provider.widgetHovered(null); + return State.REJECTED; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.actions; + +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ImageIcon; +import org.openide.util.ImageUtilities; + +/** + * + * @author Thomas Wuerthinger + */ +public class PredSuccAction extends AbstractAction { + + private boolean state; + public static final String STATE = "state"; + + public PredSuccAction() { + state = true; + putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource()))); + putValue(STATE, true); + putValue(Action.SHORT_DESCRIPTION, "Show neighboring nodes of fully visible nodes semi-transparent"); + } + + @Override + public void actionPerformed(ActionEvent ev) { + this.state = !state; + this.putValue(STATE, state); + } + + protected String iconResource() { + return "com/sun/hotspot/igv/view/images/predsucc.gif"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/layer.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd"> +<filesystem> + <folder name="CompilationViewer"> + <folder name="Graph"> + <folder name="Actions"> + <file name="com-oracle-graal-visualizer-sharedactions-ShowAllAction.shadow"> + <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ShowAllAction.instance"/> + </file> + <file name="com-oracle-graal-visualizer-sharedactions-ZoomInAction.shadow"> + <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomInAction.instance"/> + </file> + <file name="com-oracle-graal-visualizer-sharedactions-ZoomOutAction.shadow"> + <attr name="originalFile" stringvalue="Actions/View/com-oracle-graal-visualizer-sharedactions-ZoomOutAction.instance"/> + </file> + <file name="com-oracle-graal-visualizer-sharedactions-ExportSVGAction.shadow"> + <attr name="originalFile" stringvalue="Actions/File/com-oracle-graal-visualizer-sharedactions-ExportSVGAction.instance"/> + </file> + </folder> + </folder> + </folder> +</filesystem>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/CustomizablePanWidgetAction.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,146 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package com.sun.hotspot.igv.view.scene; + +import java.awt.Container; +import java.awt.Point; +import java.awt.Rectangle; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.action.WidgetAction.State; +import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + +/** + * @author David Kaspar + * @author Peter Hofer + */ +public class CustomizablePanWidgetAction extends WidgetAction.LockedAdapter { + private boolean enabled = true; + + private Scene scene; + private JScrollPane scrollPane; + private Point lastLocation; + + private final int modifiersExMask; + private final int modifiersEx; + + public CustomizablePanWidgetAction(int modifiersExMask, int modifiersEx) { + this.modifiersExMask = modifiersExMask; + this.modifiersEx = modifiersEx; + } + + @Override + protected boolean isLocked() { + return scrollPane != null; + } + + public void setEnabled(boolean enabled) { + if (this.enabled != enabled) { + if (isLocked()) + throw new IllegalStateException(); + + this.enabled = enabled; + } + } + + @Override + public State mousePressed (Widget widget, WidgetMouseEvent event) { + if (isLocked ()) + return State.createLocked (widget, this); + if (enabled && (event.getModifiersEx() & modifiersExMask) == modifiersEx) { + scene = widget.getScene (); + scrollPane = findScrollPane (scene.getView ()); + if (scrollPane != null) { + lastLocation = scene.convertSceneToView (widget.convertLocalToScene (event.getPoint ())); + SwingUtilities.convertPointToScreen (lastLocation, scene.getView ()); + return State.createLocked (widget, this); + } + } + return State.REJECTED; + } + + private JScrollPane findScrollPane (JComponent component) { + for (;;) { + if (component == null) + return null; + if (component instanceof JScrollPane) + return ((JScrollPane) component); + Container parent = component.getParent (); + if (! (parent instanceof JComponent)) + return null; + component = (JComponent) parent; + } + } + + @Override + public State mouseReleased (Widget widget, WidgetMouseEvent event) { + boolean state = pan (widget, event.getPoint ()); + if (state) + scrollPane = null; + return state ? State.createLocked (widget, this) : State.REJECTED; + } + + @Override + public State mouseDragged (Widget widget, WidgetMouseEvent event) { + return pan (widget, event.getPoint ()) ? State.createLocked (widget, this) : State.REJECTED; + } + + private boolean pan (Widget widget, Point newLocation) { + if (scrollPane == null || scene != widget.getScene ()) + return false; + newLocation = scene.convertSceneToView (widget.convertLocalToScene (newLocation)); + SwingUtilities.convertPointToScreen (newLocation, scene.getView ()); + JComponent view = scene.getView (); + Rectangle rectangle = view.getVisibleRect (); + rectangle.x += lastLocation.x - newLocation.x; + rectangle.y += lastLocation.y - newLocation.y; + view.scrollRectToVisible (rectangle); + lastLocation = newLocation; + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/DiagramScene.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,964 @@ +/* + * 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.sun.hotspot.igv.view.scene; + +import com.oracle.graal.visualizer.editor.DiagramViewModel; +import com.oracle.graal.visualizer.sharedactions.ExportSVGCookie; +import com.oracle.graal.visualizer.sharedactions.ZoomCookie; +import com.sun.hotspot.igv.data.ChangedListener; +import com.sun.hotspot.igv.data.Pair; +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.graph.*; +import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager; +import com.sun.hotspot.igv.layout.LayoutGraph; +import com.sun.hotspot.igv.util.ColorIcon; +import com.sun.hotspot.igv.util.DoubleClickAction; +import com.sun.hotspot.igv.util.PropertiesSheet; +import com.sun.hotspot.igv.view.widgets.*; +import java.awt.*; +import java.awt.event.*; +import java.util.List; +import java.util.*; +import javax.swing.*; +import org.netbeans.api.visual.action.*; +import org.netbeans.api.visual.animator.SceneAnimator; +import org.netbeans.api.visual.layout.LayoutFactory; +import org.netbeans.api.visual.model.*; +import org.netbeans.api.visual.widget.LayerWidget; +import org.netbeans.api.visual.widget.Widget; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Sheet; +import org.openide.util.Lookup; +import org.openide.util.lookup.AbstractLookup; +import org.openide.util.lookup.InstanceContent; + +public class DiagramScene extends ObjectScene implements ExportSVGCookie, ZoomCookie { + + private CustomizablePanWidgetAction panAction; + private WidgetAction hoverAction; + private WidgetAction selectAction; + private Lookup lookup; + private InstanceContent content; + private Action[] actions; + private LayerWidget connectionLayer; + private JScrollPane scrollPane; + private LayerWidget mainLayer; + private LayerWidget blockLayer; + private Widget topLeft; + private Widget bottomRight; + private DiagramViewModel model; + private WidgetAction zoomAction; + private boolean rebuilding; + /** + * The alpha level of partially visible figures. + */ + public static final float ALPHA = 0.4f; + /** + * The offset of the graph to the border of the window showing it. + */ + public static final int BORDER_SIZE = 20; + public static final int UNDOREDO_LIMIT = 100; + public static final int SCROLL_UNIT_INCREMENT = 80; + public static final int SCROLL_BLOCK_INCREMENT = 400; + public static final float ZOOM_MAX_FACTOR = 3.0f; + public static final float ZOOM_MIN_FACTOR = 0.0f;//0.15f; + public static final float ZOOM_INCREMENT = 1.5f; + public static final int SLOT_OFFSET = 6; + public static final int ANIMATION_LIMIT = 40; + private PopupMenuProvider popupMenuProvider = new PopupMenuProvider() { + + @Override + public JPopupMenu getPopupMenu(Widget widget, Point localLocation) { + return DiagramScene.this.createPopupMenu(); + } + }; + private RectangularSelectDecorator rectangularSelectDecorator = new RectangularSelectDecorator() { + + @Override + public Widget createSelectionWidget() { + Widget widget = new Widget(DiagramScene.this); + widget.setBorder(BorderFactory.createLineBorder(Color.black, 2)); + widget.setForeground(Color.red); + return widget; + } + }; + + @SuppressWarnings("unchecked") + public <T> T getWidget(Object o) { + Widget w = this.findWidget(o); + return (T) w; + } + + @SuppressWarnings("unchecked") + public <T> T getWidget(Object o, Class<T> klass) { + Widget w = this.findWidget(o); + return (T) w; + } + + public void zoomOut() { + double zoom = getZoomFactor(); + Point viewPosition = getScrollPane().getViewport().getViewPosition(); + double newZoom = zoom / DiagramScene.ZOOM_INCREMENT; + if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) { + setZoomFactor(newZoom); + validate(); + getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x / DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y / DiagramScene.ZOOM_INCREMENT))); + } + } + + public void zoomIn() { + + double zoom = getZoomFactor(); + Point viewPosition = getScrollPane().getViewport().getViewPosition(); + double newZoom = zoom * DiagramScene.ZOOM_INCREMENT; + if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) { + setZoomFactor(newZoom); + validate(); + getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x * DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y * DiagramScene.ZOOM_INCREMENT))); + } + } + + private void centerFigures(Collection<Figure> list) { + gotoFigures(list); + } + + private RectangularSelectProvider rectangularSelectProvider = new RectangularSelectProvider() { + + @Override + public void performSelection(Rectangle rectangle) { + if (rectangle.width < 0) { + rectangle.x += rectangle.width; + rectangle.width *= -1; + } + + if (rectangle.height < 0) { + rectangle.y += rectangle.height; + rectangle.height *= -1; + } + + Set<Object> selectedObjects = new HashSet<>(); + for (Figure f : getModel().getDiagramToView().getFigures()) { + FigureWidget w = getWidget(f); + if (w != null) { + Rectangle r = new Rectangle(w.getBounds()); + r.setLocation(w.getLocation()); + + if (r.intersects(rectangle)) { + selectedObjects.add(f); + } + + for (Slot s : f.getSlots()) { + SlotWidget sw = getWidget(s); + Rectangle r2 = new Rectangle(sw.getBounds()); + r2.setLocation(sw.convertLocalToScene(new Point(0, 0))); + + if (r2.intersects(rectangle)) { + selectedObjects.add(s); + } + } + } else { + assert false : "w should not be null here!"; + } + } + + setSelectedObjects(selectedObjects); + } + }; + private MouseWheelListener mouseWheelListener = new MouseWheelListener() { + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + if (e.isControlDown()) { + DiagramScene.this.relayoutWithoutLayout(null); + } + } + }; + + public Point getScrollPosition() { + return getScrollPane().getViewport().getViewPosition(); + } + + public void setScrollPosition(Point p) { + getScrollPane().getViewport().setViewPosition(p); + } + + private JScrollPane createScrollPane() { + JComponent comp = this.createView(); + comp.setDoubleBuffered(true); + comp.setBackground(Color.WHITE); + comp.setOpaque(true); + this.setBackground(Color.WHITE); + this.setOpaque(true); + JScrollPane result = new JScrollPane(comp); + result.setBackground(Color.WHITE); + result.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT); + result.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT); + result.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT); + result.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT); + return result; + } + private ObjectSceneListener selectionChangedListener = new ObjectSceneListener() { + + @Override + public void objectAdded(ObjectSceneEvent arg0, Object arg1) { + } + + @Override + public void objectRemoved(ObjectSceneEvent arg0, Object arg1) { + } + + @Override + public void objectStateChanged(ObjectSceneEvent e, Object o, ObjectState oldState, ObjectState newState) { + } + + @Override + public void selectionChanged(ObjectSceneEvent e, Set<Object> oldSet, Set<Object> newSet) { + DiagramScene scene = (DiagramScene) e.getObjectScene(); + if (scene.isRebuilding()) { + return; + } + + content.set(newSet, null); + + Set<Integer> nodeSelection = new HashSet<>(); + for (Object o : newSet) { + if (o instanceof Properties.Provider) { + final Properties.Provider provider = (Properties.Provider) o; + AbstractNode node = new AbstractNode(Children.LEAF) { + + @Override + protected Sheet createSheet() { + Sheet s = super.createSheet(); + PropertiesSheet.initializeSheet(provider.getProperties(), s); + return s; + } + }; + node.setDisplayName(provider.getProperties().get("name")); + content.add(node); + } + + + if (o instanceof Figure) { + nodeSelection.addAll(((Figure) o).getSource().getSourceNodesAsSet()); + } else if (o instanceof Slot) { + nodeSelection.addAll(((Slot) o).getSource().getSourceNodesAsSet()); + } + } + getModel().setSelectedNodes(nodeSelection); + } + + @Override + public void highlightingChanged(ObjectSceneEvent e, Set<Object> oldSet, Set<Object> newSet) { + Set<Integer> nodeHighlighting = new HashSet<>(); + for (Object o : newSet) { + if (o instanceof Figure) { + nodeHighlighting.addAll(((Figure) o).getSource().getSourceNodesAsSet()); + } else if (o instanceof Slot) { + nodeHighlighting.addAll(((Slot) o).getSource().getSourceNodesAsSet()); + } + } +// boolean b = highlightedCoordinatorListener.isEnabled(); +// highlightedCoordinatorListener.setEnabled(false); +// SelectionCoordinator.getInstance().setHighlightedObjects(nodeHighlighting); +// highlightedCoordinatorListener.setEnabled(b); + validate(); + } + + @Override + public void hoverChanged(ObjectSceneEvent e, Object oldObject, Object newObject) { + Set<Object> newHighlightedObjects = new HashSet<>(DiagramScene.this.getHighlightedObjects()); + if (oldObject != null) { + newHighlightedObjects.remove(oldObject); + } + if (newObject != null) { + newHighlightedObjects.add(newObject); + } + DiagramScene.this.setHighlightedObjects(newHighlightedObjects); + } + + @Override + public void focusChanged(ObjectSceneEvent arg0, Object arg1, Object arg2) { + } + }; + + public void setActions(Action[] actions) { + this.actions = actions; + } + + + + public DiagramScene(DiagramViewModel model) { + + this.model = model; + content = new InstanceContent(); + lookup = new AbstractLookup(content); + content.add(this); + + this.setCheckClipping(true); + + scrollPane = createScrollPane(); + + hoverAction = createObjectHoverAction(); + + // This panAction handles the event only when the left mouse button is + // pressed without any modifier keys, otherwise it will not consume it + // and the selection action (below) will handle the event + panAction = new CustomizablePanWidgetAction(~0, MouseEvent.BUTTON1_DOWN_MASK); + this.getActions().addAction(panAction); + + selectAction = createSelectAction(); + this.getActions().addAction(selectAction); + + blockLayer = new LayerWidget(this); + this.addChild(blockLayer); + + mainLayer = new LayerWidget(this); + this.addChild(mainLayer); + + topLeft = new Widget(this); + topLeft.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE)); + this.addChild(topLeft); + + bottomRight = new Widget(this); + bottomRight.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE)); + this.addChild(bottomRight); + + connectionLayer = new LayerWidget(this); + this.addChild(connectionLayer); + + LayerWidget selectionLayer = new LayerWidget(this); + this.addChild(selectionLayer); + + this.setLayout(LayoutFactory.createAbsoluteLayout()); + + this.getInputBindings().setZoomActionModifiers(KeyEvent.CTRL_MASK); + zoomAction = ActionFactory.createMouseCenteredZoomAction(1.2); + this.getActions().addAction(zoomAction); + this.getView().addMouseWheelListener(mouseWheelListener); + this.getActions().addAction(ActionFactory.createPopupMenuAction(popupMenuProvider)); + + this.getActions().addAction(ActionFactory.createWheelPanAction()); + + LayerWidget selectLayer = new LayerWidget(this); + this.addChild(selectLayer); + this.getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider)); + + this.addObjectSceneListener(selectionChangedListener, ObjectSceneEventType.OBJECT_SELECTION_CHANGED, ObjectSceneEventType.OBJECT_HIGHLIGHTING_CHANGED, ObjectSceneEventType.OBJECT_HOVER_CHANGED); + + update(); + } + + public DiagramViewModel getModel() { + return model; + } + + public JScrollPane getScrollPane() { + return scrollPane; + } + + Component getComponent() { + return scrollPane; + } + + public boolean isAllVisible() { + return getModel().getHiddenNodes().isEmpty(); + } + + public Action createGotoAction(final Figure f) { + final DiagramScene diagramScene = this; + Action a = new AbstractAction() { + + @Override + public void actionPerformed(ActionEvent e) { + diagramScene.gotoFigure(f); + } + }; + + a.setEnabled(true); + a.putValue(Action.SMALL_ICON, new ColorIcon(f.getColor())); + String name = f.getLines()[0]; + + name += " ("; + + if (!this.getWidget(f, FigureWidget.class).isVisible()) { + name += "hidden"; + } + name += ")"; + a.putValue(Action.NAME, name); + return a; + } + + private void update() { + mainLayer.removeChildren(); + blockLayer.removeChildren(); + + rebuilding = true; + + Collection<Object> objects = new ArrayList<>(this.getObjects()); + for (Object o : objects) { + this.removeObject(o); + } + + Diagram d = getModel().getDiagramToView(); + + for (Figure f : d.getFigures()) { + FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer); + w.getActions().addAction(ActionFactory.createPopupMenuAction(w)); + w.getActions().addAction(selectAction); + w.getActions().addAction(hoverAction); + w.setVisible(false); + + this.addObject(f, w); + + for (InputSlot s : f.getInputSlots()) { + SlotWidget sw = new InputSlotWidget(s, this, w, w); + addObject(s, sw); + sw.getActions().addAction(new DoubleClickAction(sw)); + sw.getActions().addAction(hoverAction); + sw.getActions().addAction(selectAction); + } + + for (OutputSlot s : f.getOutputSlots()) { + SlotWidget sw = new OutputSlotWidget(s, this, w, w); + addObject(s, sw); + sw.getActions().addAction(new DoubleClickAction(sw)); + sw.getActions().addAction(hoverAction); + sw.getActions().addAction(selectAction); + } + } + + rebuilding = false; + this.smallUpdate(true); + } + + public boolean isRebuilding() { + return rebuilding; + } + + private void smallUpdate(boolean relayout) { + + this.updateHiddenNodes(model.getHiddenNodes(), relayout); + this.validate(); + } + + private boolean isVisible(Connection c) { + FigureWidget w1 = getWidget(c.getInputSlot().getFigure()); + FigureWidget w2 = getWidget(c.getOutputSlot().getFigure()); + + if (w1.isVisible() && w2.isVisible()) { + return true; + } + + return false; + } + + private void relayout(Set<Widget> oldVisibleWidgets) { + System.out.println("relayout called with old visible widgets: " + oldVisibleWidgets); + + Diagram diagram = getModel().getDiagramToView(); + + HashSet<Figure> figures = new HashSet<>(); + + for (Figure f : diagram.getFigures()) { + FigureWidget w = getWidget(f); + if (w.isVisible()) { + figures.add(f); + } + } + + HashSet<Connection> edges = new HashSet<>(); + + for (Connection c : diagram.getConnections()) { + if (isVisible(c)) { + edges.add(c); + } + } + + HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); + manager.setMaxLayerLength(10); + manager.doLayout(new LayoutGraph(edges, figures)); + relayoutWithoutLayout(oldVisibleWidgets); + } + private Set<Pair<Point, Point>> lineCache = new HashSet<>(); + + private void relayoutWithoutLayout(Set<Widget> oldVisibleWidgets) { + + System.out.println("relayout without layout with visible widgets: " + oldVisibleWidgets); + + Diagram diagram = getModel().getDiagramToView(); + + int maxX = -BORDER_SIZE; + int maxY = -BORDER_SIZE; + for (Figure f : diagram.getFigures()) { + FigureWidget w = getWidget(f); + if (w.isVisible()) { + Point p = f.getPosition(); + Dimension d = f.getSize(); + maxX = Math.max(maxX, p.x + d.width); + maxY = Math.max(maxY, p.y + d.height); + } + } + + for (Connection c : diagram.getConnections()) { + List<Point> points = c.getControlPoints(); + FigureWidget w1 = getWidget((Figure) c.getTo().getVertex()); + FigureWidget w2 = getWidget((Figure) c.getFrom().getVertex()); + if (w1.isVisible() && w2.isVisible()) { + for (Point p : points) { + if (p != null) { + maxX = Math.max(maxX, p.x); + maxY = Math.max(maxY, p.y); + } + } + } + } + + bottomRight.setPreferredLocation(new Point(maxX + BORDER_SIZE, maxY + BORDER_SIZE)); + int offx = 0; + int offy = 0; + int curWidth = maxX + 2 * BORDER_SIZE; + int curHeight = maxY + 2 * BORDER_SIZE; + + Rectangle bounds = this.getScrollPane().getBounds(); + bounds.width /= getZoomFactor(); + bounds.height /= getZoomFactor(); + if (curWidth < bounds.width) { + offx = (bounds.width - curWidth) / 2; + } + + if (curHeight < bounds.height) { + offy = (bounds.height - curHeight) / 2; + } + + final int offx2 = offx; + final int offy2 = offy; + + SceneAnimator animator = this.getSceneAnimator(); + connectionLayer.removeChildren(); + int visibleFigureCount = 0; + for (Figure f : diagram.getFigures()) { + if (getWidget(f, FigureWidget.class).isVisible()) { + visibleFigureCount++; + } + } + + + Set<Pair<Point, Point>> lastLineCache = lineCache; + lineCache = new HashSet<>(); + for (Figure f : diagram.getFigures()) { + for (OutputSlot s : f.getOutputSlots()) { + SceneAnimator anim = animator; + if (visibleFigureCount > ANIMATION_LIMIT || oldVisibleWidgets == null) { + anim = null; + } + processOutputSlot(lastLineCache, s, s.getConnections(), 0, null, null, offx2, offy2, anim); + } + } + + for (Figure f : diagram.getFigures()) { + FigureWidget w = getWidget(f); + if (w.isVisible()) { + Point p = f.getPosition(); + Point p2 = new Point(p.x + offx2, p.y + offy2); + if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) { + animator.animatePreferredLocation(w, p2); + } else { + w.setPreferredLocation(p2); + animator.animatePreferredLocation(w, p2); + } + } + } + + this.validate(); + } + private final Point specialNullPoint = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); + + private void processOutputSlot(Set<Pair<Point, Point>> lastLineCache, OutputSlot s, List<Connection> connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) { + Map<Point, List<Connection>> pointMap = new HashMap<>(connections.size()); + + for (Connection c : connections) { + + if (!isVisible(c)) { + continue; + } + + List<Point> controlPoints = c.getControlPoints(); + if (controlPointIndex >= controlPoints.size()) { + continue; + } + + Point cur = controlPoints.get(controlPointIndex); + if (cur == null) { + cur = specialNullPoint; + } else if (controlPointIndex == 0 && !s.shouldShowName()) { + cur = new Point(cur.x, cur.y - SLOT_OFFSET); + } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().shouldShowName()) { + cur = new Point(cur.x, cur.y + SLOT_OFFSET); + } + + if (pointMap.containsKey(cur)) { + pointMap.get(cur).add(c); + } else { + List<Connection> newList = new ArrayList<>(2); + newList.add(c); + pointMap.put(cur, newList); + } + + } + + for (Point p : pointMap.keySet()) { + List<Connection> connectionList = pointMap.get(p); + + boolean isBold = false; + boolean isDashed = true; + + for (Connection c : connectionList) { + + if (c.getStyle() == Connection.ConnectionStyle.BOLD) { + isBold = true; + } + + if (c.getStyle() != Connection.ConnectionStyle.DASHED) { + isDashed = false; + } + } + + LineWidget newPredecessor = predecessor; + if (p == specialNullPoint) { + } else if (lastPoint == specialNullPoint) { + } else if (lastPoint != null) { + Point p1 = new Point(lastPoint.x + offx, lastPoint.y + offy); + Point p2 = new Point(p.x + offx, p.y + offy); + + Pair<Point, Point> curPair = new Pair<>(p1, p2); + SceneAnimator curAnimator = animator; + if (lastLineCache.contains(curPair)) { + curAnimator = null; + } + LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, curAnimator, isBold, isDashed); + lineCache.add(curPair); + + newPredecessor = w; + connectionLayer.addChild(w); + w.getActions().addAction(hoverAction); + } + + processOutputSlot(lastLineCache, s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator); + } + } + + @Override + public Lookup getLookup() { + return lookup; + } + + private void gotoFigures(final Collection<Figure> figures) { + Rectangle overall = null; + getModel().showFigures(figures); + for (Figure f : figures) { + + FigureWidget fw = getWidget(f); + if (fw != null) { + Rectangle r = fw.getBounds(); + Point p = fw.getLocation(); + Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height); + + if (overall == null) { + overall = r2; + } else { + overall = overall.union(r2); + } + } + } + if (overall != null) { + centerRectangle(overall); + } + } + + private Set<Object> idSetToObjectSet(Set<Object> ids) { + + Set<Object> result = new HashSet<>(); + for (Figure f : getModel().getDiagramToView().getFigures()) { + if (DiagramScene.doesIntersect(f.getSource().getSourceNodesAsSet(), ids)) { + result.add(f); + } + + for (Slot s : f.getSlots()) { + if (DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), ids)) { + result.add(s); + } + } + } + return result; + } + + public void gotoSelection(Set<Object> ids) { + + Rectangle overall = null; + Set<Integer> hiddenNodes = new HashSet<>(this.getModel().getHiddenNodes()); + hiddenNodes.removeAll(ids); + this.getModel().showNot(hiddenNodes); + + Set<Object> objects = idSetToObjectSet(ids); + for (Object o : objects) { + + Widget w = getWidget(o); + if (w != null) { + Rectangle r = w.getBounds(); + Point p = w.convertLocalToScene(new Point(0, 0)); + + Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height); + + if (overall == null) { + overall = r2; + } else { + overall = overall.union(r2); + } + } + } + if (overall != null) { + centerRectangle(overall); + } + + setSelectedObjects(objects); + } + + private Point calcCenter(Rectangle r) { + + Point center = new Point((int) r.getCenterX(), (int) r.getCenterY()); + center.x -= getScrollPane().getViewport().getViewRect().width / 2; + center.y -= getScrollPane().getViewport().getViewRect().height / 2; + + // Ensure to be within area + center.x = Math.max(0, center.x); + center.x = Math.min(getScrollPane().getViewport().getViewSize().width - getScrollPane().getViewport().getViewRect().width, center.x); + center.y = Math.max(0, center.y); + center.y = Math.min(getScrollPane().getViewport().getViewSize().height - getScrollPane().getViewport().getViewRect().height, center.y); + + return center; + } + + private void centerRectangle(Rectangle r) { + + if (getScrollPane().getViewport().getViewRect().width == 0 || getScrollPane().getViewport().getViewRect().height == 0) { + return; + } + + Rectangle r2 = new Rectangle(r.x, r.y, r.width, r.height); + r2 = convertSceneToView(r2); + + double factorX = (double) r2.width / (double) getScrollPane().getViewport().getViewRect().width; + double factorY = (double) r2.height / (double) getScrollPane().getViewport().getViewRect().height; + double factor = Math.max(factorX, factorY); + if (factor >= 1.0) { + Point p = getScrollPane().getViewport().getViewPosition(); + setZoomFactor(getZoomFactor() / factor); + r2.x /= factor; + r2.y /= factor; + r2.width /= factor; + r2.height /= factor; + getScrollPane().getViewport().setViewPosition(calcCenter(r2)); + } else { + getScrollPane().getViewport().setViewPosition(calcCenter(r2)); + } + } + + void setSelection(Collection<Figure> list) { + super.setSelectedObjects(new HashSet<>(list)); + centerFigures(list); + } + + private boolean isVisible(Figure f) { + for (Integer n : f.getSource().getSourceNodesAsSet()) { + if (getModel().getHiddenNodes().contains(n)) { + return false; + } + } + return true; + } + + public static boolean doesIntersect(Set<?> s1, Set<?> s2) { + if (s1.size() > s2.size()) { + Set<?> tmp = s1; + s1 = s2; + s2 = tmp; + } + + for (Object o : s1) { + if (s2.contains(o)) { + return true; + } + } + + return false; + } + + private void updateHiddenNodes(Set<Integer> newHiddenNodes, boolean doRelayout) { + + System.out.println("newHiddenNodes: " + newHiddenNodes); + + Diagram diagram = getModel().getDiagramToView(); + assert diagram != null; + + Set<Widget> oldVisibleWidgets = new HashSet<>(); + + for (Figure f : diagram.getFigures()) { + FigureWidget w = getWidget(f); + if (w != null && w.isVisible()) { + oldVisibleWidgets.add(w); + } + } + + for (Figure f : diagram.getFigures()) { + boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes); + + FigureWidget w = getWidget(f); + w.setBoundary(false); + if (!hiddenAfter) { + // Figure is shown + w.setVisible(true); + } else { + // Figure is hidden + w.setVisible(false); + } + } + + if (getModel().getShowNodeHull()) { + List<FigureWidget> boundaries = new ArrayList<>(); + for (Figure f : diagram.getFigures()) { + FigureWidget w = getWidget(f); + if (!w.isVisible()) { + Set<Figure> set = new HashSet<>(f.getPredecessorSet()); + set.addAll(f.getSuccessorSet()); + + boolean b = false; + for (Figure neighbor : set) { + FigureWidget neighborWidget = getWidget(neighbor); + if (neighborWidget.isVisible()) { + b = true; + break; + } + } + + if (b) { + w.setBoundary(true); + boundaries.add(w); + } + } + } + + for (FigureWidget w : boundaries) { + if (w.isBoundary()) { + w.setVisible(true); + } + } + } + + if (doRelayout) { + relayout(oldVisibleWidgets); + } + this.validate(); + } + + private void showFigure(Figure f) { + HashSet<Integer> newHiddenNodes = new HashSet<>(getModel().getHiddenNodes()); + newHiddenNodes.removeAll(f.getSource().getSourceNodesAsSet()); + updateHiddenNodes(newHiddenNodes, true); + } + + public void show(final Figure f) { + showFigure(f); + } + + public void setSelectedObjects(Object... args) { + Set<Object> set = new HashSet<>(); + for (Object o : args) { + set.add(o); + } + super.setSelectedObjects(set); + } + + private void centerWidget(Widget w) { + Rectangle r = w.getBounds(); + Point p = w.getLocation(); + centerRectangle(new Rectangle(p.x, p.y, r.width, r.height)); + } + + public void gotoFigure(final Figure f) { + if (!isVisible(f)) { + showFigure(f); + } + + FigureWidget fw = getWidget(f); + if (fw != null) { + setSelection(new HashSet<>(Arrays.asList(f))); + } + } + + public JPopupMenu createPopupMenu() { + JPopupMenu menu = new JPopupMenu(); + for (Action a : actions) { + if (a == null) { + menu.addSeparator(); + } else { + menu.add(a); + } + } + return menu; + } + + private final ChangedListener<DiagramViewModel> fullChange = new ChangedListener<DiagramViewModel>() { + + @Override + public void changed(DiagramViewModel source) { + assert source == model : "Receive only changed event from current model!"; + assert source != null; + update(); + } + }; + private final ChangedListener<DiagramViewModel> hiddenNodesChange = new ChangedListener<DiagramViewModel>() { + + @Override + public void changed(DiagramViewModel source) { + assert source == model : "Receive only changed event from current model!"; + assert source != null; + smallUpdate(true); + } + }; + private final ChangedListener<DiagramViewModel> selectionChange = new ChangedListener<DiagramViewModel>() { + + @Override + public void changed(DiagramViewModel source) { + assert source == model : "Receive only changed event from current model!"; + assert source != null; + smallUpdate(false); + } + }; + + @Override + public void showAll() { + // TODO(tw): Implement. + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewer.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.scene; + +import com.sun.hotspot.igv.svg.BatikSVG; +import com.oracle.graal.visualizer.editor.CompilationViewer; +import com.oracle.graal.visualizer.editor.DiagramViewModel; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.view.actions.*; +import java.awt.Component; +import java.awt.Graphics2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.*; +import java.util.Collection; +import javax.swing.Action; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; + +public class GraphCompilationViewer implements CompilationViewer, PropertyChangeListener { + + private DiagramScene scene; + private PredSuccAction predSuccAction; + + GraphCompilationViewer(DiagramViewModel model) { + + scene = new DiagramScene(model); + + Action[] actions = new Action[]{ + }; + + scene.setActions(actions); + } + + @Override + public Lookup getLookup() { + return scene.getLookup(); + } + + @Override + public Component getComponent() { + return scene.getComponent(); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getSource() == this.predSuccAction) { + boolean b = (Boolean) predSuccAction.getValue(PredSuccAction.STATE); + scene.getModel().setShowNodeHull(b); + } else { + assert false : "Unknown event source"; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewerFactory.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,58 @@ +/* + * 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.sun.hotspot.igv.view.scene; + +import com.oracle.graal.visualizer.editor.CompilationViewer; +import com.oracle.graal.visualizer.editor.CompilationViewerFactory; +import com.oracle.graal.visualizer.editor.DiagramViewModel; +import com.sun.hotspot.igv.data.InputGraph; +import com.sun.hotspot.igv.filter.FilterChain; +import com.sun.hotspot.igv.filter.FilterChainProvider; +import org.openide.util.Lookup; + +public class GraphCompilationViewerFactory implements CompilationViewerFactory{ + + @Override + public CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph) { + FilterChain filterChain; + FilterChain sequence; + FilterChainProvider provider = Lookup.getDefault().lookup(FilterChainProvider.class); + if (provider == null) { + filterChain = new FilterChain(); + sequence = new FilterChain(); + } else { + filterChain = provider.getFilterChain(); + sequence = provider.getSequence(); + } + DiagramViewModel model = new DiagramViewModel(firstGraph, secondGraph, firstGraph.getGroup(), filterChain, filterChain); + return new GraphCompilationViewer(model); + } + + @Override + public String getName() { + return "Graph"; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.widgets; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.util.DoubleClickAction; +import com.sun.hotspot.igv.util.DoubleClickHandler; +import com.sun.hotspot.igv.util.PropertiesSheet; +import com.sun.hotspot.igv.view.scene.DiagramScene; +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import org.netbeans.api.visual.action.PopupMenuProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.layout.LayoutFactory; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.LabelWidget; +import org.netbeans.api.visual.widget.Widget; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; + +/** + * + * @author Thomas Wuerthinger + */ +public class FigureWidget extends Widget implements Properties.Provider, PopupMenuProvider, DoubleClickHandler { + + public static final boolean VERTICAL_LAYOUT = true; + //public static final int MAX_STRING_LENGTH = 20; + private static final double LABEL_ZOOM_FACTOR = 0.3; + private static final double ZOOM_FACTOR = 0.1; + private Font font; + private Font boldFont; + private Figure figure; + private Widget leftWidget; + private Widget rightWidget; + private Widget middleWidget; + private ArrayList<LabelWidget> labelWidgets; + private DiagramScene diagramScene; + private boolean boundary; + private Node node; + private Widget dummyTop; + + public void setBoundary(boolean b) { + boundary = b; + } + + public boolean isBoundary() { + return boundary; + } + + public Node getNode() { + return node; + } + + @Override + public boolean isHitAt(Point localLocation) { + return middleWidget.isHitAt(localLocation); + } + + + public FigureWidget(final Figure f, WidgetAction hoverAction, WidgetAction selectAction, DiagramScene scene, Widget parent) { + + super(scene); + + assert this.getScene() != null; + assert this.getScene().getView() != null; + + this.figure = f; + font = f.getDiagram().getFont(); + boldFont = f.getDiagram().getFont().deriveFont(Font.BOLD); + this.setCheckClipping(true); + this.diagramScene = scene; + parent.addChild(this); + + Widget outer = new Widget(scene); + outer.setBackground(f.getColor()); + outer.setLayout(LayoutFactory.createOverlayLayout()); + + middleWidget = new Widget(scene); + middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 0)); + middleWidget.setBackground(f.getColor()); + middleWidget.setOpaque(true); + //middleWidget.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + middleWidget.getActions().addAction(new DoubleClickAction(this)); + middleWidget.setCheckClipping(true); + + labelWidgets = new ArrayList<>(); + + String[] strings = figure.getLines(); + + dummyTop = new Widget(scene); + dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1)); + middleWidget.addChild(dummyTop); + + + for (String cur : strings) { + + String displayString = cur; + + LabelWidget lw = new LabelWidget(scene); + labelWidgets.add(lw); + middleWidget.addChild(lw); + lw.setLabel(displayString); + lw.setFont(font); + lw.setForeground(Color.BLACK); + lw.setAlignment(LabelWidget.Alignment.CENTER); + lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER); + lw.setBorder(BorderFactory.createEmptyBorder()); + } + + Widget dummyBottom = new Widget(scene); + dummyBottom.setMinimumSize(new Dimension(Figure.INSET / 2, 1)); + middleWidget.addChild(dummyBottom); + + middleWidget.setPreferredBounds(new Rectangle(0, Figure.SLOT_WIDTH - Figure.OVERLAPPING, f.getWidth(), f.getHeight())); + //outer.addChild(middleWidget); + this.addChild(middleWidget); + + // Initialize node for property sheet + node = new AbstractNode(Children.LEAF) { + + @Override + protected Sheet createSheet() { + Sheet s = super.createSheet(); + PropertiesSheet.initializeSheet(f.getProperties(), s); + return s; + } + }; + node.setDisplayName(getName()); + } + + public Widget getLeftWidget() { + return leftWidget; + } + + public Widget getRightWidget() { + return rightWidget; + } + + @Override + protected void notifyStateChanged(ObjectState previousState, ObjectState state) { + super.notifyStateChanged(previousState, state); + + Color borderColor = Color.BLACK; + Color innerBorderColor = getFigure().getColor(); + int thickness = 1; + boolean repaint = false; + Font f = font; + if (state.isSelected() || state.isHighlighted()) { + thickness = 2; + } + if(state.isSelected()) { + f = boldFont; + innerBorderColor = borderColor; + } else { + } + + if (state.isHighlighted()) { + innerBorderColor = borderColor = Color.BLUE; + repaint = true; + } else { + repaint = true; + } + + if (state.isHovered() != previousState.isHovered()) { + + /* + if (state.isHovered()) { + diagramScene.addAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet()); + } else { + diagramScene.removeAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet()); + }*/ + repaint = true; + } + + if (state.isSelected() != previousState.isSelected()) { + repaint = true; + } + + if (repaint) { + middleWidget.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor, 1), BorderFactory.createLineBorder(innerBorderColor, 1))); + for (LabelWidget labelWidget : labelWidgets) { + labelWidget.setFont(f); + } + repaint(); + } + } + + public String getName() { + return getProperties().get("name"); + } + + @Override + public Properties getProperties() { + return figure.getProperties(); + } + + public Figure getFigure() { + return figure; + } + + @Override + protected void paintChildren() { + Composite oldComposite = null; + if (boundary) { + oldComposite = getScene().getGraphics().getComposite(); + float alpha = DiagramScene.ALPHA; + this.getScene().getGraphics().setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); + } + + if (diagramScene.getZoomFactor() < LABEL_ZOOM_FACTOR) { + + for (LabelWidget labelWidget : labelWidgets) { + labelWidget.setVisible(false); + } + super.paintChildren(); + for (LabelWidget labelWidget : labelWidgets) { + labelWidget.setVisible(true); + } + + } else { + super.paintChildren(); + } + + if (boundary) { + getScene().getGraphics().setComposite(oldComposite); + } + } + + @Override + public JPopupMenu getPopupMenu(Widget widget, Point point) { + JPopupMenu menu = diagramScene.createPopupMenu(); + menu.addSeparator(); + + JMenu predecessors = new JMenu("Nodes Above"); + predecessors.addMenuListener(new NeighborMenuListener(predecessors, getFigure(), false)); + menu.add(predecessors); + + JMenu successors = new JMenu("Nodes Below"); + successors.addMenuListener(new NeighborMenuListener(successors, getFigure(), true)); + menu.add(successors); + + return menu; + } + + /** + * Builds the submenu for a figure's neighbors on demand. + */ + private class NeighborMenuListener implements MenuListener { + + private final JMenu menu; + private final Figure figure; + private final boolean successors; + + public NeighborMenuListener(JMenu menu, Figure figure, boolean successors) { + this.menu = menu; + this.figure = figure; + this.successors = successors; + } + + @Override + public void menuSelected(MenuEvent e) { + if (menu.getItemCount() > 0) { + // already built before + return; + } + + Set<Figure> set = figure.getPredecessorSet(); + if (successors) { + set = figure.getSuccessorSet(); + } + + boolean first = true; + for (Figure f : set) { + if (f == figure) { + continue; + } + + if (first) { + first = false; + } else { + menu.addSeparator(); + } + + Action go = diagramScene.createGotoAction(f); + menu.add(go); + + JMenu preds = new JMenu("Nodes Above"); + preds.addMenuListener(new NeighborMenuListener(preds, f, false)); + menu.add(preds); + + JMenu succs = new JMenu("Nodes Below"); + succs.addMenuListener(new NeighborMenuListener(succs, f, true)); + menu.add(succs); + } + + if (menu.getItemCount() == 0) { + menu.add("(none)"); + } + } + + @Override + public void menuDeselected(MenuEvent e) { + // ignore + } + + @Override + public void menuCanceled(MenuEvent e) { + // ignore + } + } + + @Override + public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) { + + if (diagramScene.isAllVisible()) { + final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes()); + hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet()); + this.diagramScene.getModel().showNot(hiddenNodes); + } else if (isBoundary()) { + + final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes()); + hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet()); + this.diagramScene.getModel().showNot(hiddenNodes); + } else { + final Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes()); + hiddenNodes.addAll(this.getFigure().getSource().getSourceNodesAsSet()); + this.diagramScene.getModel().showNot(hiddenNodes); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.widgets; + +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.InputSlot; +import com.sun.hotspot.igv.view.scene.DiagramScene; +import java.awt.Point; +import java.util.List; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public class InputSlotWidget extends SlotWidget { + + private InputSlot inputSlot; + + public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) { + super(slot, scene, parent, fw); + inputSlot = slot; + //init(); + //getFigureWidget().getLeftWidget().addChild(this); + Point p = inputSlot.getRelativePosition(); + p.x -= this.calculateClientArea().width / 2; + p.y += Figure.SLOT_START; + this.setPreferredLocation(p); + } + + public InputSlot getInputSlot() { + return inputSlot; + } + + @Override + protected int calculateSlotWidth() { + List<InputSlot> slots = getSlot().getFigure().getInputSlots(); + assert slots.contains(getSlot()); + return calculateWidth(slots.size()); + } +/* + protected Point calculateRelativeLocation() { + if (getFigureWidget().getBounds() == null) { + return new Point(0, 0); + } + + double x = 0; + List<InputSlot> slots = inputSlot.getFigure().getInputSlots(); + assert slots.contains(inputSlot); + return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(inputSlot)))); + }*/ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.widgets; + +import com.sun.hotspot.igv.graph.Connection; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.InputSlot; +import com.sun.hotspot.igv.graph.OutputSlot; +import com.sun.hotspot.igv.view.scene.DiagramScene; +import java.awt.*; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.swing.JPopupMenu; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.PopupMenuProvider; +import org.netbeans.api.visual.action.SelectProvider; +import org.netbeans.api.visual.animator.SceneAnimator; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public class LineWidget extends Widget implements PopupMenuProvider { + + public final int BORDER = 5; + public final int ARROW_SIZE = 6; + public final int BOLD_ARROW_SIZE = 7; + public final int HOVER_ARROW_SIZE = 8; + public final int BOLD_STROKE_WIDTH = 2; + public final int HOVER_STROKE_WIDTH = 3; + private static double ZOOM_FACTOR = 0.1; + private OutputSlot outputSlot; + private DiagramScene scene; + private List<Connection> connections; + private Point from; + private Point to; + private Rectangle clientArea; + private Color color = Color.BLACK; + private LineWidget predecessor; + private List<LineWidget> successors; + private boolean highlighted; + private boolean popupVisible; + private boolean isBold; + private boolean isDashed; + + public LineWidget(DiagramScene scene, OutputSlot s, List<Connection> connections, Point from, Point to, LineWidget predecessor, SceneAnimator animator, boolean isBold, boolean isDashed) { + super(scene); + this.scene = scene; + this.outputSlot = s; + this.connections = connections; + this.from = from; + this.to = to; + this.predecessor = predecessor; + this.successors = new ArrayList<>(); + if (predecessor != null) { + predecessor.addSuccessor(this); + } + + this.isBold = isBold; + this.isDashed = isDashed; + + int minX = from.x; + int minY = from.y; + int maxX = to.x; + int maxY = to.y; + if (minX > maxX) { + int tmp = minX; + minX = maxX; + maxX = tmp; + } + + if (minY > maxY) { + int tmp = minY; + minY = maxY; + maxY = tmp; + } + + clientArea = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1); + clientArea.grow(BORDER, BORDER); + + if (connections.size() > 0) { + color = connections.get(0).getColor(); + } + + this.setToolTipText("<HTML>" + generateToolTipText(this.connections) + "</HTML>"); + + this.setCheckClipping(true); + + this.getActions().addAction(ActionFactory.createPopupMenuAction(this)); + if (animator == null) { + this.setBackground(color); + } else { + this.setBackground(Color.WHITE); + animator.animateBackgroundColor(this, color); + } + + this.getActions().addAction(ActionFactory.createSelectAction(new SelectProvider() { + + @Override + public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) { + return true; + } + + @Override + public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) { + return true; + } + + @Override + public void select(Widget arg0, Point arg1, boolean arg2) { + Set<Figure> set = new HashSet<>(); + for (Connection c : LineWidget.this.connections) { + set.add(c.getInputSlot().getFigure()); + set.add(c.getOutputSlot().getFigure()); + } + LineWidget.this.scene.setSelectedObjects(set); + } + })); + } + + private String generateToolTipText(List<Connection> conn) { + StringBuilder sb = new StringBuilder(); + for (Connection c : conn) { + sb.append(c.getToolTipText()); + sb.append("<br>"); + } + return sb.toString(); + } + + public Point getFrom() { + return from; + } + + public Point getTo() { + return to; + } + + private void addSuccessor(LineWidget widget) { + this.successors.add(widget); + } + + @Override + protected Rectangle calculateClientArea() { + return clientArea; + } + + @Override + protected void paintWidget() { + if (scene.getZoomFactor() < ZOOM_FACTOR) { + return; + } + + Graphics2D g = getScene().getGraphics(); + g.setPaint(this.getBackground()); + float width = 1.0f; + + if (isBold) { + width = BOLD_STROKE_WIDTH; + } + + if (highlighted || popupVisible) { + width = HOVER_STROKE_WIDTH; + } + + Stroke oldStroke = g.getStroke(); + if (isDashed) { + float[] dashPattern = {5, 5, 5, 5}; + g.setStroke(new BasicStroke(width, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, 10, + dashPattern, 0)); + } else { + g.setStroke(new BasicStroke(width)); + } + + g.drawLine(from.x, from.y, to.x, to.y); + + boolean sameFrom = false; + boolean sameTo = successors.size() == 0; + for (LineWidget w : successors) { + if (w.getFrom().equals(getTo())) { + sameTo = true; + } + } + + if (predecessor == null || predecessor.getTo().equals(getFrom())) { + sameFrom = true; + } + + + int size = ARROW_SIZE; + if (isBold) { + size = BOLD_ARROW_SIZE; + } + if (highlighted || popupVisible) { + size = HOVER_ARROW_SIZE; + } + if (!sameFrom) { + g.fillPolygon( + new int[]{from.x - size / 2, from.x + size / 2, from.x}, + new int[]{from.y - size / 2, from.y - size / 2, from.y + size / 2}, + 3); + } + if (!sameTo) { + g.fillPolygon( + new int[]{to.x - size / 2, to.x + size / 2, to.x}, + new int[]{to.y - size / 2, to.y - size / 2, to.y + size / 2}, + 3); + } + g.setStroke(oldStroke); + } + + private void setHighlighted(boolean b) { + this.highlighted = b; + Set<Object> highlightedObjects = new HashSet<>(scene.getHighlightedObjects()); + Set<Object> highlightedObjectsChange = new HashSet<>(); + for (Connection c : connections) { + highlightedObjectsChange.add(c.getInputSlot().getFigure()); + highlightedObjectsChange.add(c.getInputSlot()); + highlightedObjectsChange.add(c.getOutputSlot().getFigure()); + highlightedObjectsChange.add(c.getOutputSlot()); + } + if(b) { + highlightedObjects.addAll(highlightedObjectsChange); + } else { + highlightedObjects.removeAll(highlightedObjectsChange); + } + scene.setHighlightedObjects(highlightedObjects); + this.revalidate(true); + } + + private void setPopupVisible(boolean b) { + this.popupVisible = b; + this.revalidate(true); + } + + @Override + public boolean isHitAt(Point localPoint) { + return Line2D.ptLineDistSq(from.x, from.y, to.x, to.y, localPoint.x, localPoint.y) <= BORDER * BORDER; + } + + @Override + protected void notifyStateChanged(ObjectState previousState, ObjectState state) { + if (previousState.isHovered() != state.isHovered()) { + setRecursiveHighlighted(state.isHovered()); + } + } + + private void setRecursiveHighlighted(boolean b) { + LineWidget cur = predecessor; + while (cur != null) { + cur.setHighlighted(b); + cur = cur.predecessor; + } + + highlightSuccessors(b); + this.setHighlighted(b); + } + + private void highlightSuccessors(boolean b) { + for (LineWidget s : successors) { + s.setHighlighted(b); + s.highlightSuccessors(b); + } + } + + private void setRecursivePopupVisible(boolean b) { + LineWidget cur = predecessor; + while (cur != null) { + cur.setPopupVisible(b); + cur = cur.predecessor; + } + + popupVisibleSuccessors(b); + setPopupVisible(b); + } + + private void popupVisibleSuccessors(boolean b) { + for (LineWidget s : successors) { + s.setPopupVisible(b); + s.popupVisibleSuccessors(b); + } + } + + @Override + public JPopupMenu getPopupMenu(Widget widget, Point localLocation) { + JPopupMenu menu = new JPopupMenu(); + menu.add(scene.createGotoAction(outputSlot.getFigure())); + menu.addSeparator(); + + for (Connection c : connections) { + InputSlot s = c.getInputSlot(); + menu.add(scene.createGotoAction(s.getFigure())); + } + + final LineWidget w = this; + menu.addPopupMenuListener(new PopupMenuListener() { + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + w.setRecursivePopupVisible(true); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + w.setRecursivePopupVisible(false); + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + + return menu; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.widgets; + +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.OutputSlot; +import com.sun.hotspot.igv.view.scene.DiagramScene; +import java.awt.Point; +import java.util.List; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public class OutputSlotWidget extends SlotWidget { + + private OutputSlot outputSlot; + + public OutputSlotWidget(OutputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) { + super(slot, scene, parent, fw); + outputSlot = slot; + //init(); + //getFigureWidget().getRightWidget().addChild(this); + Point p = outputSlot.getRelativePosition(); + p.y += getSlot().getFigure().getHeight() - Figure.SLOT_START; + p.x -= this.calculateClientArea().width / 2; + //p.x += this.calculateClientArea().width / 2; + this.setPreferredLocation(p); + } + + public OutputSlot getOutputSlot() { + return outputSlot; + } + + @Override + protected int calculateSlotWidth() { + + List<OutputSlot> slots = getSlot().getFigure().getOutputSlots(); + assert slots.contains(getSlot()); + return calculateWidth(slots.size()); + + } + /* + protected Point calculateRelativeLocation() { + if (getFigureWidget().getBounds() == null) { + return new Point(0, 0); + } + + double x = this.getFigureWidget().getBounds().width; + List<OutputSlot> slots = outputSlot.getFigure().getOutputSlots(); + assert slots.contains(outputSlot); + return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(outputSlot)))); + }*/ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2008, 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.sun.hotspot.igv.view.widgets; + +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.OutputSlot; +import com.sun.hotspot.igv.graph.Slot; +import com.sun.hotspot.igv.util.DoubleClickHandler; +import com.sun.hotspot.igv.view.scene.DiagramScene; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.util.HashSet; +import java.util.Set; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + +/** + * + * @author Thomas Wuerthinger + */ +public abstract class SlotWidget extends Widget implements DoubleClickHandler { + + private Slot slot; + private FigureWidget figureWidget; + private static double TEXT_ZOOM_FACTOR = 0.9; + private static double ZOOM_FACTOR = 0.6; + private DiagramScene diagramScene; + + public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) { + super(scene); + this.diagramScene = scene; + this.slot = slot; + figureWidget = fw; + this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>"); + this.setCheckClipping(true); + parent.addChild(this); + + //this.setPreferredBounds(this.calculateClientArea()); + } + + + @Override + protected void notifyStateChanged(ObjectState previousState, ObjectState state) { + super.notifyStateChanged(previousState, state); + repaint(); + } + + public Slot getSlot() { + return slot; + } + + public FigureWidget getFigureWidget() { + return figureWidget; + } + + @Override + protected void paintWidget() { + + if (getScene().getZoomFactor() < ZOOM_FACTOR) { + return; + } + + Graphics2D g = this.getGraphics(); + // g.setColor(Color.DARK_GRAY); + int w = this.getBounds().width; + int h = this.getBounds().height; + + if(getSlot().getSource().getSourceNodes().size() > 0) { + final int SMALLER = 0; + g.setColor(getSlot().getColor()); + + int FONT_OFFSET = 2; + + int s = h - SMALLER; + int rectW = s; + + Font font = this.getSlot().getFigure().getDiagram().getSlotFont(); + if(this.getState().isSelected()) { + font = font.deriveFont(Font.BOLD); + } + + if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0) { + g.setFont(font); + Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g); + rectW = (int)r1.getWidth() + FONT_OFFSET * 2; + } + g.fillRect(w/2 - rectW/2, 0, rectW-1, s-1); + + if(this.getState().isHighlighted()) { + g.setColor(Color.BLUE); + } else { + g.setColor(Color.BLACK); + } + g.drawRect(w/2 - rectW/2, 0, rectW-1, s-1); + + + if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && getScene().getZoomFactor() >= TEXT_ZOOM_FACTOR) { + Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g); + g.drawString(getSlot().getShortName(), (int) (w - r1.getWidth()) / 2, g.getFontMetrics().getAscent()-1);//(int) (r1.getHeight())); + } + + } else { + + if(this.getState().isHighlighted()) { + g.setColor(Color.BLUE); + } else { + g.setColor(Color.BLACK); + } + int r = 2; + if (slot instanceof OutputSlot) { + g.fillOval(w/2-r, Figure.SLOT_WIDTH - Figure.SLOT_START - r, 2*r, 2*r); + //g.fillArc(w / 2 - r, -r, 2*r, 2*r, 180, 180); + } else { + g.fillOval(w/2-r, Figure.SLOT_START - r, 2*r, 2*r); + //g.fillArc(w / 2 - r, h - r, 2*r, 2*r, 0, 180); + } + } + } + + @Override + protected Rectangle calculateClientArea() { + return new Rectangle(0, 0, slot.getWidth(), Figure.SLOT_WIDTH); + } + + protected abstract int calculateSlotWidth(); + + protected int calculateWidth(int count) { + return getFigureWidget().getFigure().getWidth() / count; + } + + @Override + public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) { + Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes()); + if (diagramScene.isAllVisible()) { + hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes()); + } + + boolean progress = false; + for(Figure f : diagramScene.getModel().getDiagramToView().getFigures()) { + for(Slot s : f.getSlots()) { + if(DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), slot.getSource().getSourceNodesAsSet())) { + progress = true; + hiddenNodes.removeAll(f.getSource().getSourceNodesAsSet()); + } + } + } + + if(progress) { + this.diagramScene.getModel().showNot(hiddenNodes); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,7 @@ +currentVersion=Graal Visualizer {0} +LBL_splash_window_title=Starting Graal Visualizer +SPLASH_WIDTH=475 +SplashProgressBarBounds=0,273,475,6 +SplashProgressBarColor=0xFFFFFF +SplashRunningTextBounds=10,283,460,12 +SplashRunningTextColor=0xFFFFFF
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,2 @@ +CTL_MainWindow_Title=Graal Visualizer {0} +CTL_MainWindow_Title_No_Project=Graal Visualizer {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/build.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See harness/README in the NetBeans platform --> +<!-- for some information on what you could do (e.g. targets to override). --> +<!-- If you delete this file and reopen the project it will be recreated. --> +<project name="Graal Visualizer" basedir="."> + <description>Builds the module suite IdealGraphVisualizer.</description> + <import file="nbproject/build-impl.xml"/> + + <target name="build-launchers" depends="suite.build-launchers"> + <!-- Drop memory presets (-Xms, -Xmx) from default_options of packaged builds and let the executing VM choose reasonable defaults --> + <replaceregexp file="${build.launcher.dir}/etc/${app.name}.conf" byline="true" match="^default_options=.*" replace='default_options="--branding idealgraphvisualizer"' /> + </target> + + <!-- Local (environment-specific) extensions/modifications to the build --> + <import file="build-local.xml" optional="true" /> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/nbproject/build-impl.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** +--> +<project name="IdealGraphVisualizer-impl" basedir=".." xmlns:sproject="http://www.netbeans.org/ns/nb-module-suite-project/1"> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <property file="nbproject/private/platform-private.properties"/> + <property file="nbproject/platform.properties"/> + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-suite-project/1"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-suite-project/1"> + <attribute name="property"/> + <attribute name="value"/> + <sequential> + <property name="@{property}" value="@{value}"/> + </sequential> + </macrodef> + <property file="${user.properties.file}"/> + <sproject:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir"/> + <sproject:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/> + <sproject:evalprops property="cluster.path.evaluated" value="${cluster.path}"/> + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness)."> + <condition> + <not> + <contains string="${cluster.path.evaluated}" substring="platform"/> + </not> + </condition> + </fail> + <ant antfile="nbproject/platform.xml"/> + <fail message="Cannot find NetBeans build harness. ${line.separator}Check that nbplatform.${nbplatform.active}.netbeans.dest.dir and nbplatform.${nbplatform.active}.harness.dir are defined. ${line.separator}On a developer machine these are normally defined in ${user.properties.file}=${netbeans.user}/build.properties ${line.separator}but for automated builds you should pass these properties to Ant explicitly. ${line.separator}You may instead download the harness and platform: -Dbootstrap.url=.../tasks.jar -Dautoupdate.catalog.url=.../updates.xml"> + <condition> + <not> + <available file="${harness.dir}/suite.xml"/> + </not> + </condition> + </fail> + <import file="${harness.dir}/suite.xml"/> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/nbproject/genfiles.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,11 @@ +build.xml.data.CRC32=3c2c6126 +build.xml.script.CRC32=48934e60 +build.xml.stylesheet.CRC32=eaf9f76a@1.45.1 +# 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=3c2c6126 +nbproject/build-impl.xml.script.CRC32=b26e57e5 +nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.47.1 +nbproject/platform.xml.data.CRC32=3c2c6126 +nbproject/platform.xml.script.CRC32=db9e1f43 +nbproject/platform.xml.stylesheet.CRC32=df8ac4dd@2.47.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/nbproject/platform.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,212 @@ +nbplatform.active=default +bootstrap.url=http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar +autoupdate.catalog.url=http://updates.netbeans.org/netbeans/updates/7.1.1/uc/final/distribution/catalog.xml.gz +suite.dir=${basedir} +nbplatform.active.dir=${suite.dir}/nbplatform +nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform +nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness +harness.dir=${nbplatform.active.dir}/harness +cluster.path=\ + ${nbplatform.active.dir}/ide:\ + ${nbplatform.active.dir}/platform +disabled.modules=\ + com.jcraft.jsch,\ + com.jcraft.jzlib,\ + org.apache.commons.codec,\ + org.apache.commons.httpclient,\ + org.apache.commons.io,\ + org.apache.commons.lang,\ + org.apache.commons.logging,\ + org.apache.ws.commons.util,\ + org.apache.xml.resolver,\ + org.apache.xmlrpc,\ + org.eclipse.core.contenttype,\ + org.eclipse.core.jobs,\ + org.eclipse.core.net,\ + org.eclipse.core.runtime,\ + org.eclipse.core.runtime.compatibility.auth,\ + org.eclipse.equinox.app,\ + org.eclipse.equinox.common,\ + org.eclipse.equinox.preferences,\ + org.eclipse.equinox.registry,\ + org.eclipse.equinox.security,\ + org.eclipse.jgit,\ + org.eclipse.mylyn.bugzilla.core,\ + org.eclipse.mylyn.commons.core,\ + org.eclipse.mylyn.commons.net,\ + org.eclipse.mylyn.commons.xmlrpc,\ + org.eclipse.mylyn.tasks.core,\ + org.mozilla.rhino.patched,\ + org.netbeans.api.debugger,\ + org.netbeans.api.java.classpath,\ + org.netbeans.api.xml,\ + org.netbeans.core.browser,\ + org.netbeans.core.execution,\ + org.netbeans.core.ide,\ + org.netbeans.core.io.ui,\ + org.netbeans.core.multiview,\ + org.netbeans.core.nativeaccess,\ + org.netbeans.core.osgi,\ + org.netbeans.lib.cvsclient,\ + org.netbeans.lib.terminalemulator,\ + org.netbeans.libs.antlr3.runtime,\ + org.netbeans.libs.bytelist,\ + org.netbeans.libs.commons_net,\ + org.netbeans.libs.freemarker,\ + org.netbeans.libs.git,\ + org.netbeans.libs.ini4j,\ + org.netbeans.libs.jaxb,\ + org.netbeans.libs.jsr223,\ + org.netbeans.libs.junit4,\ + org.netbeans.libs.jvyamlb,\ + org.netbeans.libs.lucene,\ + org.netbeans.libs.smack,\ + org.netbeans.libs.svnClientAdapter,\ + org.netbeans.libs.svnClientAdapter.javahl,\ + org.netbeans.libs.svnClientAdapter.svnkit,\ + org.netbeans.libs.swingx,\ + org.netbeans.libs.xerces,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.bugtracking,\ + org.netbeans.modules.bugtracking.bridge,\ + org.netbeans.modules.bugzilla,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.csl.api,\ + org.netbeans.modules.css.editor,\ + org.netbeans.modules.css.lib,\ + org.netbeans.modules.css.visual,\ + org.netbeans.modules.db,\ + org.netbeans.modules.db.core,\ + org.netbeans.modules.db.dataview,\ + org.netbeans.modules.db.drivers,\ + org.netbeans.modules.db.kit,\ + org.netbeans.modules.db.metadata.model,\ + org.netbeans.modules.db.mysql,\ + org.netbeans.modules.db.sql.editor,\ + org.netbeans.modules.db.sql.visualeditor,\ + org.netbeans.modules.dbapi,\ + org.netbeans.modules.defaults,\ + org.netbeans.modules.derby,\ + org.netbeans.modules.dlight.nativeexecution,\ + org.netbeans.modules.dlight.terminal,\ + org.netbeans.modules.editor.bookmarks,\ + org.netbeans.modules.editor.bracesmatching,\ + org.netbeans.modules.editor.codetemplates,\ + org.netbeans.modules.editor.completion,\ + org.netbeans.modules.editor.guards,\ + org.netbeans.modules.editor.indent.project,\ + org.netbeans.modules.editor.kit,\ + org.netbeans.modules.editor.macros,\ + org.netbeans.modules.editor.structure,\ + org.netbeans.modules.extbrowser,\ + org.netbeans.modules.extexecution,\ + org.netbeans.modules.extexecution.destroy,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.git,\ + org.netbeans.modules.glassfish.common,\ + org.netbeans.modules.gototest,\ + org.netbeans.modules.gsf.codecoverage,\ + org.netbeans.modules.gsf.testrunner,\ + org.netbeans.modules.html,\ + org.netbeans.modules.html.editor,\ + org.netbeans.modules.html.editor.lib,\ + org.netbeans.modules.html.lexer,\ + org.netbeans.modules.html.parser,\ + org.netbeans.modules.html.validation,\ + org.netbeans.modules.httpserver,\ + org.netbeans.modules.hudson,\ + org.netbeans.modules.hudson.git,\ + org.netbeans.modules.hudson.mercurial,\ + org.netbeans.modules.hudson.subversion,\ + org.netbeans.modules.hudson.tasklist,\ + org.netbeans.modules.ide.kit,\ + org.netbeans.modules.image,\ + org.netbeans.modules.javascript.editing,\ + org.netbeans.modules.javascript.hints,\ + org.netbeans.modules.javascript.kit,\ + org.netbeans.modules.javascript.refactoring,\ + org.netbeans.modules.jellytools.ide,\ + org.netbeans.modules.jumpto,\ + org.netbeans.modules.keyring.impl,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.languages.diff,\ + org.netbeans.modules.languages.manifest,\ + org.netbeans.modules.languages.yaml,\ + org.netbeans.modules.lexer.nbbridge,\ + org.netbeans.modules.localhistory,\ + org.netbeans.modules.mercurial,\ + org.netbeans.modules.netbinox,\ + org.netbeans.modules.parsing.api,\ + org.netbeans.modules.parsing.lucene,\ + org.netbeans.modules.print.editor,\ + org.netbeans.modules.project.ant,\ + org.netbeans.modules.project.libraries,\ + org.netbeans.modules.projectui,\ + org.netbeans.modules.projectui.buildmenu,\ + org.netbeans.modules.projectuiapi,\ + org.netbeans.modules.properties,\ + org.netbeans.modules.properties.syntax,\ + org.netbeans.modules.refactoring.api,\ + org.netbeans.modules.schema2beans,\ + org.netbeans.modules.server,\ + org.netbeans.modules.servletapi,\ + org.netbeans.modules.spellchecker,\ + org.netbeans.modules.spellchecker.apimodule,\ + org.netbeans.modules.spellchecker.bindings.htmlxml,\ + org.netbeans.modules.spellchecker.bindings.properties,\ + org.netbeans.modules.spellchecker.dictionary_en,\ + org.netbeans.modules.spellchecker.kit,\ + org.netbeans.modules.spi.actions,\ + org.netbeans.modules.subversion,\ + org.netbeans.modules.swing.validation,\ + org.netbeans.modules.target.iterator,\ + org.netbeans.modules.tasklist.kit,\ + org.netbeans.modules.tasklist.projectint,\ + org.netbeans.modules.tasklist.todo,\ + org.netbeans.modules.tasklist.ui,\ + org.netbeans.modules.terminal,\ + org.netbeans.modules.usersguide,\ + org.netbeans.modules.utilities,\ + org.netbeans.modules.utilities.project,\ + org.netbeans.modules.versioning,\ + org.netbeans.modules.versioning.indexingbridge,\ + org.netbeans.modules.versioning.system.cvss.installer,\ + org.netbeans.modules.versioning.util,\ + org.netbeans.modules.web.client.tools.api,\ + org.netbeans.modules.web.common,\ + org.netbeans.modules.web.indent,\ + org.netbeans.modules.xml,\ + org.netbeans.modules.xml.axi,\ + org.netbeans.modules.xml.catalog,\ + org.netbeans.modules.xml.core,\ + org.netbeans.modules.xml.jaxb.api,\ + org.netbeans.modules.xml.lexer,\ + org.netbeans.modules.xml.multiview,\ + org.netbeans.modules.xml.retriever,\ + org.netbeans.modules.xml.schema.completion,\ + org.netbeans.modules.xml.schema.model,\ + org.netbeans.modules.xml.tax,\ + org.netbeans.modules.xml.text,\ + org.netbeans.modules.xml.tools,\ + org.netbeans.modules.xml.wsdl.model,\ + org.netbeans.modules.xml.xam,\ + org.netbeans.modules.xml.xdm,\ + org.netbeans.modules.xsl,\ + org.netbeans.spi.debugger.ui,\ + org.netbeans.spi.editor.hints,\ + org.netbeans.spi.navigator,\ + org.netbeans.spi.palette,\ + org.netbeans.spi.tasklist,\ + org.netbeans.spi.viewmodel,\ + org.netbeans.swing.dirchooser,\ + org.openide.compat,\ + org.openide.execution,\ + org.openide.options,\ + org.openide.util.enumerations +## Not disabled because of NetBeans bug 206347: +## Applications not using OSGi don't start on NbP 7.1 +# org.netbeans.core.netigso,\ +# org.netbeans.libs.felix,\ +# org.netbeans.libs.osgi,\ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/nbproject/platform.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="platform" default="download" basedir=".."> + <condition property="download.required"> + <and> + <not> + <available file="${harness.dir}/suite.xml"/> + </not> + <isset property="bootstrap.url"/> + <isset property="autoupdate.catalog.url"/> + </and> + </condition> + <target name="download" if="download.required"> + <mkdir dir="${harness.dir}"/> + <pathconvert pathsep="|" property="download.clusters"> + <mapper type="flatten"/> + <path path="${cluster.path}"/> + </pathconvert> + <property name="disabled.modules" value=""/> + <pathconvert property="module.includes" pathsep=""> + <mapper type="glob" from="${basedir}${file.separator}*" to="(?!\Q*\E)"/> + <path> + <filelist files="${disabled.modules}" dir="."/> + </path> + </pathconvert> + <echo message="Downloading clusters ${download.clusters}"/> + <property name="tasks.jar" location="${java.io.tmpdir}/tasks.jar"/> + <get src="${bootstrap.url}" dest="${tasks.jar}" usetimestamp="true" verbose="true"/> + <taskdef name="autoupdate" classname="org.netbeans.nbbuild.AutoUpdate" classpath="${tasks.jar}"/> + <autoupdate installdir="${nbplatform.active.dir}" updatecenter="${autoupdate.catalog.url}"> + <modules includes="${module.includes}.*" clusters="${download.clusters}"/> + <modules includes="org[.]netbeans[.]modules[.]apisupport[.]harness" clusters="harness"/> + </autoupdate> + </target> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/nbproject/project.properties Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,48 @@ +app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif +app.name=idealgraphvisualizer +app.title=IdealGraphVisualizer +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/nbproject/project.xml Wed Feb 08 21:15:00 2012 -0800 @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.apisupport.project.suite</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/nb-module-suite-project/1"> + <name>Graal Visualizer</name> + </data> + </configuration> +</project>