# HG changeset patch # User Gilles Duboscq # Date 1307438341 -7200 # Node ID 7474789a8120183d6c927f3a646100663c74a085 # Parent 463657856f86b6da521805def0f6e7817d29e545# Parent e55543ff91fd79148b678e4d48ab1b3c610ff084 Merge diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Tue Jun 07 11:19:01 2011 +0200 @@ -25,13 +25,12 @@ import java.util.*; -import com.oracle.graal.graph.*; import com.oracle.max.asm.*; import com.sun.c1x.alloc.*; import com.sun.c1x.asm.*; import com.sun.c1x.debug.*; import com.sun.c1x.gen.*; -import com.sun.c1x.gen.LIRGenerator.*; +import com.sun.c1x.gen.LIRGenerator.DeoptimizationStub; import com.sun.c1x.graph.*; import com.sun.c1x.lir.*; import com.sun.c1x.observer.*; @@ -56,7 +55,7 @@ public final CiAssumptions assumptions = new CiAssumptions(); public final FrameState placeholderState; - public Graph graph = new Graph(); + public CompilerGraph graph = new CompilerGraph(); private boolean hasExceptionHandlers; private final C1XCompilation parent; @@ -96,7 +95,7 @@ this.method = method; this.stats = stats == null ? new CiStatistics() : stats; this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method); - this.placeholderState = method != null && method.minimalDebugInfo() ? new FrameState(0, 0, 0, 0, graph) : null; + this.placeholderState = method != null && method.minimalDebugInfo() ? new FrameState(method, 0, 0, 0, 0, graph) : null; if (compiler.isObserved()) { compiler.fireCompilationStarted(new CompilationEvent(this)); diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XOptions.java Tue Jun 07 11:19:01 2011 +0200 @@ -90,6 +90,7 @@ public static boolean TraceRelocation = ____; public static boolean TraceLIRVisit = ____; public static boolean TraceAssembler = ____; + public static boolean TraceInlining = ____; public static int TraceBytecodeParserLevel = 0; public static boolean QuietBailout = ____; diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java --- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Tue Jun 07 11:19:01 2011 +0200 @@ -1884,7 +1884,7 @@ } } - CiFrame computeFrameForState(int opId, FrameState state, CiBitMap frameRefMap) { + CiFrame computeFrameForState(FrameState state, int opId, CiBitMap frameRefMap) { CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()]; int valueIndex = 0; @@ -1909,8 +1909,11 @@ } } } - - return new CiFrame(null, ir.compilation.method, state.bci, values, state.localsSize(), state.stackSize(), state.locksSize()); + CiFrame caller = null; + if (state.outerFrameState() != null) { + caller = computeFrameForState(state.outerFrameState(), opId, frameRefMap); + } + return new CiFrame(caller, state.method, state.bci, values, state.localsSize(), state.stackSize(), state.locksSize()); } private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) { @@ -1946,7 +1949,7 @@ if (C1XOptions.TraceLinearScanLevel >= 3) { TTY.println("creating debug information at opId %d", opId); } - return computeFrameForState(opId, state, frameRefMap); + return computeFrameForState(state, opId, frameRefMap); } private void assignLocations(List instructions, IntervalWalker iw) { diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java --- a/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java Tue Jun 07 11:19:01 2011 +0200 @@ -99,7 +99,6 @@ printer.addOmittedClass(FrameState.class); } printer.addClassColor(StartNode.class, "snow3"); - printer.addClassColor(EndNode.class, "snow3"); printer.addClassColor(LoopBegin.class, "skyblue"); printer.addClassColor(LoopEnd.class, "skyblue3"); printer.addClassColor(Unwind.class, "red"); diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Tue Jun 07 11:19:01 2011 +0200 @@ -299,7 +299,7 @@ if (Modifier.isSynchronized(compilation.method.accessFlags())) { bci = Instruction.SYNCHRONIZATION_ENTRY_BCI; } - FrameState fs = new FrameState(bci, compilation.method.maxLocals(), 0, 0, compilation.graph); + FrameState fs = new FrameState(compilation.method, bci, compilation.method.maxLocals(), 0, 0, compilation.graph); for (Node node : compilation.graph.start().usages()) { if (node instanceof Local) { Local local = (Local) node; diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java Tue Jun 07 11:19:01 2011 +0200 @@ -401,15 +401,6 @@ private ExceptionBlock unwindBlock; - private ExceptionBlock makeUnwind() { - if (unwindBlock == null) { - unwindBlock = new ExceptionBlock(); - unwindBlock.startBci = -1; - unwindBlock.endBci = -1; - } - return unwindBlock; - } - private Block makeExceptionDispatch(List handlers, int index) { RiExceptionHandler handler = handlers.get(index); if (handler.isCatchAll()) { @@ -422,14 +413,10 @@ block.endBci = -1; block.handler = handler; block.successors.add(blockMap[handler.handlerBCI()]); - Block next; if (index < handlers.size() - 1) { - next = makeExceptionDispatch(handlers, index + 1); - } else { - next = makeUnwind(); + block.next = makeExceptionDispatch(handlers, index + 1); + block.successors.add(block.next); } - block.successors.add(next); - block.next = next; exceptionDispatch.put(handler, block); } return block; diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/graph/CompilerGraph.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/CompilerGraph.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,53 @@ +/* + * 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.c1x.graph; + +import com.oracle.graal.graph.*; +import com.sun.c1x.ir.*; + + +public class CompilerGraph extends Graph { + + private Return returnSingleton; + private Unwind unwindSingleton; + + public Return createReturn(Value result) { + assert returnSingleton == null; + returnSingleton = new Return(result, this); + return returnSingleton; + } + + public Return getReturn() { + return returnSingleton; + } + + public Unwind createUnwind(Value exception) { + assert unwindSingleton == null; + unwindSingleton = new Unwind(exception, this); + return unwindSingleton; + } + + public Unwind getUnwind() { + return unwindSingleton; + } +} diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Tue Jun 07 11:19:01 2011 +0200 @@ -61,20 +61,29 @@ */ public static final int TRACELEVEL_STATE = 2; - private final IR ir; private final C1XCompilation compilation; + private final CompilerGraph graph; + private final CiStatistics stats; + private final RiRuntime runtime; + private final RiMethod method; + private final RiConstantPool constantPool; private final BytecodeStream stream; // the bytecode stream + private final LogStream log; + private final FrameStateBuilder frameState; // the current execution state + // bci-to-block mapping private Block[] blockFromBci; private ArrayList blockList; - private Block syncBlock; + private int nextBlockNumber; + + private Value methodSynchronizedObject; private CiExceptionHandler syncHandler; - // the constant pool - private final RiConstantPool constantPool; + private Block unwindBlock; + private Block returnBlock; // the worklist of blocks, sorted by depth first number private final PriorityQueue workList = new PriorityQueue(10, new Comparator() { @@ -83,14 +92,11 @@ } }); - private FrameStateBuilder frameState; // the current execution state private Instruction lastInstr; // the last instruction added - private final LogStream log; + private final Set blocksOnWorklist = new HashSet(); + private final Set blocksVisited = new HashSet(); - private Value rootMethodSynchronizedObject; - - private final Graph graph; /** * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation. @@ -99,15 +105,18 @@ * @param ir the IR to build the graph into * @param graph */ - public GraphBuilder(C1XCompilation compilation, IR ir, Graph graph) { + public GraphBuilder(C1XCompilation compilation, RiMethod method, CompilerGraph graph) { this.compilation = compilation; - this.ir = ir; + this.graph = graph; + + this.runtime = compilation.runtime; + this.method = method; this.stats = compilation.stats; - log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; - stream = new BytecodeStream(compilation.method.code()); - constantPool = compilation.runtime.getConstantPool(compilation.method); - this.graph = graph; - this.frameState = new FrameStateBuilder(compilation.method, graph); + this.log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; + this.stream = new BytecodeStream(method.code()); + + this.constantPool = runtime.getConstantPool(method); + this.frameState = new FrameStateBuilder(method, graph); } /** @@ -115,20 +124,18 @@ * @param scope the top IRScope */ public void build() { - RiMethod rootMethod = compilation.method; - if (log != null) { log.println(); - log.println("Compiling " + compilation.method); + log.println("Compiling " + method); } // 2. compute the block map, setup exception handlers and get the entrypoint(s) - BlockMap blockMap = compilation.getBlockMap(rootMethod); + BlockMap blockMap = compilation.getBlockMap(method); blockList = new ArrayList(blockMap.blocks); - blockFromBci = new Block[rootMethod.code().length]; + blockFromBci = new Block[method.code().length]; for (int i = 0; i < blockList.size(); i++) { - int blockID = ir.nextBlockNumber(); + int blockID = nextBlockNumber(); assert blockID == i; Block block = blockList.get(i); if (block.startBci >= 0) { @@ -142,18 +149,15 @@ lastInstr = createTarget(startBlock, frameState); graph.start().setStart(lastInstr); - if (isSynchronized(rootMethod.accessFlags())) { + if (isSynchronized(method.accessFlags())) { // 4A.1 add a monitor enter to the start block - rootMethodSynchronizedObject = synchronizedObject(frameState, compilation.method); - genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI); + methodSynchronizedObject = synchronizedObject(frameState, method); + genMonitorEnter(methodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI); // 4A.2 finish the start block finishStartBlock(startBlock); // 4A.3 setup an exception handler to unlock the root method synchronized object - syncBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI); - markOnWorkList(syncBlock); - - syncHandler = new CiExceptionHandler(0, rootMethod.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); + syncHandler = new CiExceptionHandler(0, method.code().length, Instruction.SYNCHRONIZATION_ENTRY_BCI, 0, null); } else { // 4B.1 simply finish the start block finishStartBlock(startBlock); @@ -165,11 +169,7 @@ addToWorkList(blockFromBci[0]); iterateAllBlocks(); - if (syncBlock != null && syncBlock.firstInstruction != null) { - // generate unlocking code if the exception handler is reachable - fillSyncHandler(rootMethodSynchronizedObject, syncBlock); - } - + // remove Placeholders for (Node n : graph.getNodes()) { if (n instanceof Placeholder) { Placeholder p = (Placeholder) n; @@ -181,21 +181,13 @@ } } - for (Node n : graph.getNodes()) { - assert !(n instanceof Placeholder); - } - - + // remove FrameStates for (Node n : graph.getNodes()) { if (n instanceof FrameState) { boolean delete = false; if (n.usages().size() == 0 && n.predecessors().size() == 0) { delete = true; } -// if (n.predecessors().size() == 0 && n.usages().size() == 1 && n.usages().get(0) instanceof BlockBegin) { -// n.usages().get(0).inputs().replace(n, null); -// delete = true; -// } if (delete) { n.delete(); } @@ -203,15 +195,40 @@ } } + private int nextBlockNumber() { + stats.blockCount++; + return nextBlockNumber++; + } + private Block nextBlock(int bci) { Block block = new Block(); block.startBci = bci; block.endBci = bci; - block.blockID = ir.nextBlockNumber(); + block.blockID = nextBlockNumber(); return block; } - private Set blocksOnWorklist = new HashSet(); + private Block unwindBlock() { + if (unwindBlock == null) { + unwindBlock = new Block(); + unwindBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; + unwindBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; + unwindBlock.blockID = nextBlockNumber(); + addToWorkList(unwindBlock); + } + return unwindBlock; + } + + private Block returnBlock() { + if (returnBlock == null) { + returnBlock = new Block(); + returnBlock.startBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; + returnBlock.endBci = Instruction.SYNCHRONIZATION_ENTRY_BCI; + returnBlock.blockID = nextBlockNumber(); + addToWorkList(returnBlock); + } + return returnBlock; + } private void markOnWorkList(Block block) { blocksOnWorklist.add(block); @@ -221,8 +238,6 @@ return blocksOnWorklist.contains(block); } - private Set blocksVisited = new HashSet(); - private void markVisited(Block block) { blocksVisited.add(block); } @@ -310,10 +325,6 @@ } } - public RiMethod method() { - return compilation.method; - } - public BytecodeStream stream() { return stream; } @@ -342,7 +353,7 @@ assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci"; RiExceptionHandler firstHandler = null; - RiExceptionHandler[] exceptionHandlers = compilation.method.exceptionHandlers(); + RiExceptionHandler[] exceptionHandlers = method.exceptionHandlers(); // join with all potential exception handlers if (exceptionHandlers != null) { for (RiExceptionHandler handler : exceptionHandlers) { @@ -376,7 +387,7 @@ assert isCatchAll(firstHandler); int handlerBCI = firstHandler.handlerBCI(); if (handlerBCI == Instruction.SYNCHRONIZATION_ENTRY_BCI) { - dispatchBlock = syncBlock; + dispatchBlock = unwindBlock(); } else { dispatchBlock = blockFromBci[handlerBCI]; } @@ -404,7 +415,7 @@ } private void genLoadConstant(int cpi) { - Object con = constantPool().lookupConstant(cpi); + Object con = constantPool.lookupConstant(cpi); if (con instanceof RiType) { // this is a load of class constant which might be unresolved @@ -532,7 +543,7 @@ private void genArithmeticOp(CiKind result, int opcode, CiKind x, CiKind y, boolean canTrap) { Value yValue = frameState.pop(y); Value xValue = frameState.pop(x); - Value result1 = append(new ArithmeticOp(opcode, result, xValue, yValue, isStrict(method().accessFlags()), canTrap, graph)); + Value result1 = append(new ArithmeticOp(opcode, result, xValue, yValue, isStrict(method.accessFlags()), canTrap, graph)); frameState.push(result, result1); } @@ -571,7 +582,7 @@ int delta = stream().readIncrement(); Value x = frameState.localAt(index); Value y = append(Constant.forInt(delta, graph)); - frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method().accessFlags()), false, graph))); + frameState.storeLocal(index, append(new ArithmeticOp(IADD, CiKind.Int, x, y, isStrict(method.accessFlags()), false, graph))); } private void genGoto(int fromBCI, int toBCI) { @@ -610,16 +621,20 @@ private void genThrow(int bci) { Value exception = frameState.apop(); append(new NullCheck(exception, graph)); + Instruction entry = handleException(exception, bci); - if (entry == null) { - entry = new Unwind(exception, graph.end(), graph); + if (entry != null) { + append(entry); + } else { + frameState.clearStack(); + frameState.apush(exception); + appendGoto(createTarget(unwindBlock(), frameState)); } - append(entry); } private void genCheckCast() { int cpi = stream().readCPI(); - RiType type = constantPool().lookupType(cpi, CHECKCAST); + RiType type = constantPool.lookupType(cpi, CHECKCAST); boolean isInitialized = type.isResolved(); Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); Value object = frameState.apop(); @@ -632,7 +647,7 @@ private void genInstanceOf() { int cpi = stream().readCPI(); - RiType type = constantPool().lookupType(cpi, INSTANCEOF); + RiType type = constantPool.lookupType(cpi, INSTANCEOF); boolean isInitialized = type.isResolved(); Value typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); Value object = frameState.apop(); @@ -644,9 +659,9 @@ } void genNewInstance(int cpi) { - RiType type = constantPool().lookupType(cpi, NEW); + RiType type = constantPool.lookupType(cpi, NEW); if (type.isResolved()) { - NewInstance n = new NewInstance(type, cpi, constantPool(), graph); + NewInstance n = new NewInstance(type, cpi, constantPool, graph); frameState.apush(append(n)); } else { append(new Deoptimize(graph)); @@ -656,13 +671,13 @@ private void genNewTypeArray(int typeCode) { CiKind kind = CiKind.fromArrayTypeCode(typeCode); - RiType elementType = compilation.runtime.asRiType(kind); + RiType elementType = runtime.asRiType(kind); NewTypeArray nta = new NewTypeArray(frameState.ipop(), elementType, graph); frameState.apush(append(nta)); } private void genNewObjectArray(int cpi) { - RiType type = constantPool().lookupType(cpi, ANEWARRAY); + RiType type = constantPool.lookupType(cpi, ANEWARRAY); Value length = frameState.ipop(); if (type.isResolved()) { NewArray n = new NewObjectArray(type, length, graph); @@ -675,14 +690,14 @@ } private void genNewMultiArray(int cpi) { - RiType type = constantPool().lookupType(cpi, MULTIANEWARRAY); + RiType type = constantPool.lookupType(cpi, MULTIANEWARRAY); int rank = stream().readUByte(bci() + 3); Value[] dims = new Value[rank]; for (int i = rank - 1; i >= 0; i--) { dims[i] = frameState.ipop(); } if (type.isResolved()) { - NewArray n = new NewMultiArray(type, dims, cpi, constantPool(), graph); + NewArray n = new NewMultiArray(type, dims, cpi, constantPool, graph); frameState.apush(append(n)); } else { append(new Deoptimize(graph)); @@ -831,7 +846,7 @@ private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) { CiKind resultType = returnKind(target); - Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(compilation.method.holder()), graph); + Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph); Value result = appendWithBCI(invoke); invoke.setExceptionEdge(handleException(null, bci())); frameState.pushReturn(resultType, result); @@ -843,7 +858,7 @@ exact = receiver.exactType(); if (exact == null) { if (receiver.isConstant()) { - exact = compilation.runtime.getTypeOf(receiver.asConstant()); + exact = runtime.getTypeOf(receiver.asConstant()); } if (exact == null) { RiType declared = receiver.declaredType(); @@ -864,7 +879,7 @@ } if (exactType == null && receiver instanceof Local && ((Local) receiver).index() == 0) { // the exact type isn't known, but the receiver is parameter 0 => use holder - receiverType = compilation.method.holder(); + receiverType = method.holder(); exactType = receiverType.exactType(); } boolean needsCheck = true; @@ -894,35 +909,23 @@ } private void genReturn(Value x) { - if (method().isConstructor() && method().holder().superType() == null) { - callRegisterFinalizer(); + frameState.clearStack(); + if (x != null) { + frameState.push(x.kind, x); } - - frameState.clearStack(); - if (Modifier.isSynchronized(method().accessFlags())) { - // unlock before exiting the method - int lockNumber = frameState.locksSize() - 1; - MonitorAddress lockAddress = null; - if (compilation.runtime.sizeOfBasicObjectLock() != 0) { - lockAddress = new MonitorAddress(lockNumber, graph); - append(lockAddress); - } - append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph)); - frameState.unlock(); - } - append(new Return(x, graph)); + appendGoto(createTarget(returnBlock(), frameState)); } private void genMonitorEnter(Value x, int bci) { int lockNumber = frameState.locksSize(); MonitorAddress lockAddress = null; - if (compilation.runtime.sizeOfBasicObjectLock() != 0) { + if (runtime.sizeOfBasicObjectLock() != 0) { lockAddress = new MonitorAddress(lockNumber, graph); append(lockAddress); } MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, graph); appendWithBCI(monitorEnter); - frameState.lock(ir, x, lockNumber + 1); + frameState.lock(x); if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) { monitorEnter.setStateAfter(frameState.create(0)); } @@ -934,7 +937,7 @@ throw new CiBailout("monitor stack underflow"); } MonitorAddress lockAddress = null; - if (compilation.runtime.sizeOfBasicObjectLock() != 0) { + if (runtime.sizeOfBasicObjectLock() != 0) { lockAddress = new MonitorAddress(lockNumber, graph); append(lockAddress); } @@ -1067,27 +1070,6 @@ } } - private void fillSyncHandler(Value lock, Block syncHandler) { - lastInstr = syncHandler.firstInstruction; - while (lastInstr.next() != null) { - // go forward to the end of the block - lastInstr = lastInstr.next(); - } - - frameState.initializeFrom(((StateSplit) syncHandler.firstInstruction).stateBefore()); - - assert lock != null; - assert frameState.locksSize() > 0 && frameState.lockAt(frameState.locksSize() - 1) == lock; - - // Exit the monitor and unwind the stack. - genMonitorExit(lock); - append(new Unwind(frameState.apop(), graph.end(), graph)); - - // The sync handler is always the last thing to add => we can clear the frameState. - frameState = null; - lastInstr = null; - } - private void iterateAllBlocks() { Block block; while ((block = removeFromWorkList()) != null) { @@ -1105,7 +1087,11 @@ lastInstr = block.firstInstruction; assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID; - if (block instanceof ExceptionBlock) { + if (block == returnBlock) { + createReturnBlock(block); + } else if (block == unwindBlock) { + createUnwindBlock(block); + } else if (block instanceof ExceptionBlock) { createExceptionDispatch((ExceptionBlock) block); } else { iterateBytecodesForBlock(block); @@ -1136,33 +1122,44 @@ } } + private void createUnwindBlock(Block block) { + if (Modifier.isSynchronized(method.accessFlags())) { + genMonitorExit(methodSynchronizedObject); + } + append(graph.createUnwind(frameState.apop())); + } + + private void createReturnBlock(Block block) { + if (method.isConstructor() && method.holder().superType() == null) { + callRegisterFinalizer(); + } + CiKind returnKind = method.signature().returnKind().stackKind(); + Value x = returnKind == CiKind.Void ? null : frameState.pop(returnKind); + assert frameState.stackSize() == 0; + + if (Modifier.isSynchronized(method.accessFlags())) { + genMonitorExit(methodSynchronizedObject); + } + append(graph.createReturn(x)); + } + private void createExceptionDispatch(ExceptionBlock block) { if (block.handler == null) { assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize(); - if (Modifier.isSynchronized(method().accessFlags())) { - // unlock before exiting the method - int lockNumber = frameState.locksSize() - 1; - MonitorAddress lockAddress = null; - if (compilation.runtime.sizeOfBasicObjectLock() != 0) { - lockAddress = new MonitorAddress(lockNumber, graph); - append(lockAddress); - } - append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph)); - frameState.unlock(); - } - append(new Unwind(frameState.apop(), graph.end(), graph)); + createUnwindBlock(block); } else { assert frameState.stackSize() == 1; + Block nextBlock = block.next == null ? unwindBlock() : block.next; if (block.handler.catchType().isResolved()) { Instruction catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState); - Instruction nextDispatch = createTarget(block.next, frameState); + Instruction nextDispatch = createTarget(nextBlock, frameState); append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph)); } else { Deoptimize deopt = new Deoptimize(graph); deopt.setMessage("unresolved " + block.handler.catchType().name()); append(deopt); - Instruction nextDispatch = createTarget(block.next, frameState); + Instruction nextDispatch = createTarget(nextBlock, frameState); appendGoto(nextDispatch); } } @@ -1186,8 +1183,7 @@ if (nextBlock != null && nextBlock != block) { assert !nextBlock.isExceptionEntry; // we fell through to the next block, add a goto and break - Instruction next = createTarget(nextBlock, frameState); - appendGoto(next); + appendGoto(createTarget(nextBlock, frameState)); break; } // read the opcode @@ -1215,7 +1211,7 @@ private void traceState() { if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { - log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method())); + log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); for (int i = 0; i < frameState.localsSize(); ++i) { Value value = frameState.localAt(i); log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); @@ -1414,14 +1410,14 @@ case DRETURN : genReturn(frameState.dpop()); break; case ARETURN : genReturn(frameState.apop()); break; case RETURN : genReturn(null ); break; - case GETSTATIC : cpi = stream.readCPI(); genGetStatic(cpi, constantPool().lookupField(cpi, opcode)); break; - case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(cpi, constantPool().lookupField(cpi, opcode)); break; - case GETFIELD : cpi = stream.readCPI(); genGetField(cpi, constantPool().lookupField(cpi, opcode)); break; - case PUTFIELD : cpi = stream.readCPI(); genPutField(cpi, constantPool().lookupField(cpi, opcode)); break; - case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break; - case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(constantPool().lookupMethod(cpi, opcode), null, cpi, constantPool()); break; - case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break; - case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool().lookupMethod(cpi, opcode), cpi, constantPool()); break; + case GETSTATIC : cpi = stream.readCPI(); genGetStatic(cpi, constantPool.lookupField(cpi, opcode)); break; + case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(cpi, constantPool.lookupField(cpi, opcode)); break; + case GETFIELD : cpi = stream.readCPI(); genGetField(cpi, constantPool.lookupField(cpi, opcode)); break; + case PUTFIELD : cpi = stream.readCPI(); genPutField(cpi, constantPool.lookupField(cpi, opcode)); break; + case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break; + case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(constantPool.lookupMethod(cpi, opcode), null, cpi, constantPool); break; + case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break; + case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(constantPool.lookupMethod(cpi, opcode), cpi, constantPool); break; case NEW : genNewInstance(stream.readCPI()); break; case NEWARRAY : genNewTypeArray(stream.readLocalIndex()); break; case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; @@ -1465,10 +1461,6 @@ frameState.ipush(append(new ArrayLength(frameState.apop(), graph))); } - private RiConstantPool constantPool() { - return constantPool; - } - /** * Adds a block to the worklist, if it is not already in the worklist. * This method will keep the worklist topologically stored (i.e. the lower diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/graph/IR.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Tue Jun 07 11:19:01 2011 +0200 @@ -22,6 +22,7 @@ */ package com.sun.c1x.graph; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.graph.*; @@ -32,6 +33,9 @@ import com.sun.c1x.ir.*; import com.sun.c1x.lir.*; import com.sun.c1x.observer.*; +import com.sun.c1x.value.*; +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; /** * This class implements the overall container for the HIR (high-level IR) graph @@ -49,8 +53,6 @@ */ public LIRBlock startBlock; - private int maxLocks; - /** * The linear-scan ordered list of blocks. */ @@ -162,12 +164,227 @@ private void buildGraph() { // Graph builder must set the startBlock and the osrEntryBlock - new GraphBuilder(compilation, this, compilation.graph).build(); + new GraphBuilder(compilation, compilation.method, compilation.graph).build(); verifyAndPrint("After graph building"); + List trivialInline = new ArrayList(); + List deoptInline = new ArrayList(); + List deoptMethods = new ArrayList(); + for (Node node : compilation.graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + RiMethod target = invoke.target; + if (target.isResolved() && !Modifier.isNative(target.accessFlags())) { + if (target.canBeStaticallyBound()) { + trivialInline.add(invoke); + } else { + RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target); + if (concrete != null) { + deoptInline.add(invoke); + deoptMethods.add(concrete); + } + } + } + } + } + + int allowedInlinings = 50; + for (Invoke invoke : trivialInline) { + if (inlineMethod(invoke, invoke.target)) { + if (--allowedInlinings <= 0) { + break; + } + } + } + + for (int i = 0; i < deoptInline.size(); i++) { + Invoke invoke = deoptInline.get(i); + RiMethod method = deoptMethods.get(i); + if (inlineMethod(invoke, method)) { + if (C1XOptions.TraceInlining) { + System.out.println("registering concrete method assumption..."); + } + compilation.assumptions.recordConcreteMethod(invoke.target, method); + if (--allowedInlinings <= 0) { + break; + } + } + } + if (C1XOptions.PrintCompilation) { - TTY.print(String.format("%3d blocks | ", this.numberOfBlocks())); + TTY.print(String.format("%3d blocks | ", compilation.stats.blockCount)); + } + } + + private boolean inlineMethod(Invoke invoke, RiMethod method) { + String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)"; + + if (method.code().length > 50) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because of code size"); + } + return false; + } + + Instruction exceptionEdge = invoke.exceptionEdge(); + if (exceptionEdge != null) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because of exceptionEdge"); + } + return false; + } + if (!method.holder().isInitialized()) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because of non-initialized class"); + } + return false; + } + + if (C1XOptions.TraceInlining) { + System.out.println("building graph: " + name); + } + CompilerGraph graph = new CompilerGraph(); + new GraphBuilder(compilation, method, graph).build(); + + boolean withReceiver = !Modifier.isStatic(method.accessFlags()); + + int argumentCount = method.signature().argumentCount(false); + Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)]; + int slot = withReceiver ? 1 : 0; + int param = withReceiver ? 1 : 0; + for (int i = 0; i < argumentCount; i++) { + parameters[param++] = invoke.argument(slot); + slot += method.signature().argumentKindAt(i).sizeInSlots(); + } + if (withReceiver) { + parameters[0] = invoke.argument(0); + } + + HashMap replacements = new HashMap(); + ArrayList nodes = new ArrayList(); + ArrayList frameStates = new ArrayList(); + Return returnNode = null; + Unwind unwindNode = null; + StartNode startNode = null; + boolean invokes = false; + for (Node node : graph.getNodes()) { + if (node != null) { + if (node instanceof StartNode) { + startNode = (StartNode) node; + } else if (node instanceof Local) { + replacements.put(node, parameters[((Local) node).index()]); + } else { + nodes.add(node); + if (node instanceof Return) { + returnNode = (Return) node; + } else if (node instanceof Unwind) { + unwindNode = (Unwind) node; + } else if (node instanceof FrameState) { + frameStates.add(node); + } + } + } + } + if (unwindNode != null) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because of unwind node"); + } + return false; + } + if (invokes) { + if (C1XOptions.TraceInlining) { + System.out.println("not inlining " + name + " because of invokes"); + } + return false; + } + + if (C1XOptions.TraceInlining) { + System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes"); + } + + Instruction pred; + if (withReceiver) { + pred = new NullCheck(parameters[0], compilation.graph); + } else { + pred = new Merge(compilation.graph); + } + assert invoke.predecessors().size() == 1; + invoke.predecessors().get(0).successors().replace(invoke, pred); + replacements.put(startNode, pred); + + Map duplicates = compilation.graph.addDuplicate(nodes, replacements); + + if (returnNode != null) { + List usages = new ArrayList(invoke.usages()); + for (Node usage : usages) { + if (returnNode.result() instanceof Local) { + usage.inputs().replace(invoke, replacements.get(returnNode.result())); + } else { + usage.inputs().replace(invoke, duplicates.get(returnNode.result())); + } + } + Node returnDuplicate = duplicates.get(returnNode); + returnDuplicate.inputs().clearAll(); + + assert returnDuplicate.predecessors().size() == 1; + Node returnPred = returnDuplicate.predecessors().get(0); + int index = returnDuplicate.predecessorsIndex().get(0); + returnPred.successors().setAndClear(index, invoke, 0); + + returnDuplicate.delete(); + } + FrameState stateAfter = invoke.stateAfter(); + if (frameStates.size() > 0) { + FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind); + for (Node frameState : frameStates) { + ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState); + } + } + + invoke.successors().clearAll(); + invoke.inputs().clearAll(); + invoke.delete(); + + stateAfter.delete(); + + deleteUnused(exceptionEdge); + + verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false)); + return true; + } + + private void deleteUnused(Node node) { + if (node != null && node.predecessors().size() == 0) { + if (node instanceof ExceptionObject) { + Node successor = node.successors().get(0); + node.successors().clearAll(); + if (successor instanceof ExceptionDispatch) { + ExceptionDispatch dispatch = (ExceptionDispatch) successor; + Node succ1 = dispatch.catchSuccessor(); + Node succ2 = dispatch.otherSuccessor(); + if (succ1 instanceof Merge) { + ((Merge) succ1).removePhiPredecessor(dispatch); + } + if (succ2 instanceof Merge) { + ((Merge) succ2).removePhiPredecessor(dispatch); + } + dispatch.successors().clearAll(); + deleteUnused(succ1); + deleteUnused(succ2); + dispatch.delete(); + } else { + assert successor instanceof Merge; + System.out.println("succ: " + successor.successors().get(0)); + Node next = successor.successors().get(0); + successor.successors().clearAll(); + deleteUnused(next); + successor.delete(); + } + node.delete(); + } else if (node instanceof Unwind) { + node.delete(); + } } } @@ -203,35 +420,23 @@ } } - - public int nextBlockNumber() { - return compilation.stats.blockCount++; - } - - public int numberOfBlocks() { - return compilation.stats.blockCount; - } - public int numLoops() { return compilation.stats.loopCount; } /** - * Updates the maximum number of locks held at any one time. - * - * @param locks a lock count that will replace the current {@linkplain #maxLocks() max locks} if it is greater - */ - public void updateMaxLocks(int locks) { - if (locks > maxLocks) { - maxLocks = locks; - } - } - - /** - * Gets the number of locks. - * @return the number of locks + * Gets the maximum number of locks in the graph's frame states. */ public final int maxLocks() { + int maxLocks = 0; + for (Node node : compilation.graph.getNodes()) { + if (node instanceof FrameState) { + int lockCount = ((FrameState) node).locksSize(); + if (lockCount > maxLocks) { + maxLocks = lockCount; + } + } + } return maxLocks; } diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/ir/LoopBegin.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/LoopBegin.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoopBegin.java Tue Jun 07 11:19:01 2011 +0200 @@ -58,6 +58,11 @@ } @Override + public String shortName() { + return "LoopBegin"; + } + + @Override public Node copy(Graph into) { LoopBegin x = new LoopBegin(into); x.setNonNull(isNonNull()); diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/ir/LoopEnd.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/LoopEnd.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoopEnd.java Tue Jun 07 11:19:01 2011 +0200 @@ -69,6 +69,11 @@ } @Override + public String shortName() { + return "LoopEnd"; + } + + @Override public Node copy(Graph into) { LoopEnd x = new LoopEnd(into); x.setNonNull(isNonNull()); diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Tue Jun 07 11:19:01 2011 +0200 @@ -267,4 +267,17 @@ x.setNonNull(isNonNull()); return x; } + + public void removePhiPredecessor(ExceptionDispatch successor) { + int predIndex = predecessors().indexOf(successor); + assert predIndex != -1; + + for (Node usage : usages()) { + if (usage instanceof Phi) { + Phi phi = (Phi) usage; + assert phi.valueCount() == predecessors().size(); + phi.removeInput(predIndex + 1); + } + } + } } diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Tue Jun 07 11:19:01 2011 +0200 @@ -131,15 +131,11 @@ @Override public String shortName() { StringBuilder str = new StringBuilder(); - for (int i = 1; i < inputs().size(); ++i) { - if (i != 1) { + for (int i = 0; i < valueCount(); ++i) { + if (i != 0) { str.append(' '); } - if (inputs().get(i) != null) { - str.append(inputs().get(i).id()); - } else { - str.append("-"); - } + str.append(valueAt(i) == null ? "-" : valueAt(i).id()); } return "Phi: (" + str + ")"; } diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/ir/Return.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java Tue Jun 07 11:19:01 2011 +0200 @@ -72,7 +72,6 @@ public Return(Value result, Graph graph) { super(result == null ? CiKind.Void : result.kind, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph); setResult(result); - successors().set(SUCCESSOR_END, graph.end()); } // for copying diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java Tue Jun 07 11:19:01 2011 +0200 @@ -34,8 +34,7 @@ private static final int INPUT_COUNT = 1; private static final int INPUT_EXCEPTION = 0; - private static final int SUCCESSOR_COUNT = 1; - private static final int SUCCESSOR_END = 0; + private static final int SUCCESSOR_COUNT = 0; @Override protected int inputCount() { @@ -64,10 +63,9 @@ return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n); } - public Unwind(Value exception, Node successor, Graph graph) { + public Unwind(Value exception, Graph graph) { super(CiKind.Object, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph); setException(exception); - successors().set(SUCCESSOR_END, successor); } @Override @@ -82,7 +80,7 @@ @Override public Node copy(Graph into) { - Unwind x = new Unwind(null, null, into); + Unwind x = new Unwind(null, into); x.setNonNull(isNonNull()); return x; } diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Tue Jun 07 11:19:01 2011 +0200 @@ -31,6 +31,7 @@ import com.sun.c1x.debug.*; import com.sun.c1x.ir.*; import com.sun.cri.ci.*; +import com.sun.cri.ri.*; /** * The {@code FrameState} class encapsulates the frame state (i.e. local variables and @@ -38,6 +39,10 @@ */ public final class FrameState extends Value implements FrameStateAccess { + private static final int INPUT_COUNT = 1; + + private static final int INPUT_OUTER_FRAME_STATE = 0; + protected final int localsSize; protected final int stackSize; @@ -56,12 +61,27 @@ return super.successorCount() + SUCCESSOR_COUNT; } + public FrameState outerFrameState() { + return (FrameState) inputs().get(super.inputCount() + INPUT_OUTER_FRAME_STATE); + } + + public FrameState setOuterFrameState(FrameState n) { + return (FrameState) inputs().set(super.inputCount() + INPUT_OUTER_FRAME_STATE, n); + } + + @Override + public void setValueAt(int i, Value x) { + inputs().set(INPUT_COUNT + i, x); + } + /** * The bytecode index to which this frame state applies. This will be {@code -1} * iff this state is mutable. */ public final int bci; + public final RiMethod method; + /** * Creates a {@code FrameState} for the given scope and maximum number of stack and local variables. * @@ -70,28 +90,27 @@ * @param stackSize size of the stack * @param lockSize number of locks */ - public FrameState(int bci, int localsSize, int stackSize, int locksSize, Graph graph) { - super(CiKind.Illegal, localsSize + stackSize + locksSize, SUCCESSOR_COUNT, graph); + public FrameState(RiMethod method, int bci, int localsSize, int stackSize, int locksSize, Graph graph) { + super(CiKind.Illegal, localsSize + stackSize + locksSize + INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.method = method; this.bci = bci; this.localsSize = localsSize; this.stackSize = stackSize; this.locksSize = locksSize; C1XMetrics.FrameStatesCreated++; C1XMetrics.FrameStateValuesCreated += localsSize + stackSize + locksSize; - //Exception e = new Exception(); - //e.printStackTrace(); } - FrameState(int bci, Value[] locals, Value[] stack, int stackSize, ArrayList locks, Graph graph) { - this(bci, locals.length, stackSize, locks.size(), graph); + FrameState(RiMethod method, int bci, Value[] locals, Value[] stack, int stackSize, ArrayList locks, Graph graph) { + this(method, bci, locals.length, stackSize, locks.size(), graph); for (int i = 0; i < locals.length; i++) { - inputs().set(i, locals[i]); + setValueAt(i, locals[i]); } for (int i = 0; i < stackSize; i++) { - inputs().set(localsSize + i, stack[i]); + setValueAt(localsSize + i, stack[i]); } for (int i = 0; i < locks.size(); i++) { - inputs().set(locals.length + stackSize + i, locks.get(i)); + setValueAt(locals.length + stackSize + i, locks.get(i)); } } @@ -109,13 +128,14 @@ */ @Override public FrameState duplicateWithEmptyStack(int bci) { - FrameState other = new FrameState(bci, localsSize, 0, locksSize(), graph()); + FrameState other = new FrameState(method, bci, localsSize, 0, locksSize(), graph()); for (int i = 0; i < localsSize; i++) { - other.inputs().set(i, localAt(i)); + other.setValueAt(i, localAt(i)); } for (int i = 0; i < locksSize; i++) { - other.inputs().set(localsSize + i, lockAt(i)); + other.setValueAt(localsSize + i, lockAt(i)); } + other.setOuterFrameState(outerFrameState()); return other; } @@ -127,20 +147,21 @@ public FrameState duplicateModified(int bci, CiKind popKind, Value... pushedValues) { int popSlots = popKind.sizeInSlots(); int pushSlots = pushedValues.length; - FrameState other = new FrameState(bci, localsSize, stackSize - popSlots + pushSlots, locksSize(), graph()); + FrameState other = new FrameState(method, bci, localsSize, stackSize - popSlots + pushSlots, locksSize(), graph()); for (int i = 0; i < localsSize; i++) { - other.inputs().set(i, localAt(i)); + other.setValueAt(i, localAt(i)); } for (int i = 0; i < stackSize - popSlots; i++) { - other.inputs().set(localsSize + i, stackAt(i)); + other.setValueAt(localsSize + i, stackAt(i)); } int slot = localsSize + stackSize - popSlots; for (int i = 0; i < pushSlots; i++) { - other.inputs().set(slot++, pushedValues[i]); + other.setValueAt(slot++, pushedValues[i]); } for (int i = 0; i < locksSize; i++) { - other.inputs().set(localsSize + other.stackSize + i, lockAt(i)); + other.setValueAt(localsSize + other.stackSize + i, lockAt(i)); } + other.setOuterFrameState(outerFrameState()); return other; } @@ -160,6 +181,9 @@ return false; } } + if (other.outerFrameState() != outerFrameState()) { + return false; + } return true; } @@ -194,7 +218,7 @@ // note that for double word locals, the high slot should already be null // unless the local is actually dead and the high slot is being reused; // in either case, it is not necessary to null the high slot - inputs().set(i, null); + setValueAt(i, null); } /** @@ -207,16 +231,16 @@ public void storeLocal(int i, Value x) { assert i < localsSize : "local variable index out of range: " + i; invalidateLocal(i); - inputs().set(i, x); + setValueAt(i, x); if (isDoubleWord(x)) { // (tw) if this was a double word then kill i+1 - inputs().set(i + 1, null); + setValueAt(i + 1, null); } if (i > 0) { // if there was a double word at i - 1, then kill it Value p = localAt(i - 1); if (isDoubleWord(p)) { - inputs().set(i - 1, null); + setValueAt(i - 1, null); } } } @@ -229,7 +253,7 @@ */ public Value localAt(int i) { assert i < localsSize : "local variable index out of range: " + i; - return (Value) inputs().get(i); + return valueAt(i); } /** @@ -240,7 +264,7 @@ */ public Value stackAt(int i) { assert i >= 0 && i < (localsSize + stackSize); - return (Value) inputs().get(localsSize + i); + return valueAt(localsSize + i); } /** @@ -250,7 +274,7 @@ */ public Value lockAt(int i) { assert i >= 0; - return (Value) inputs().get(localsSize + stackSize + i); + return valueAt(localsSize + stackSize + i); } /** @@ -268,7 +292,7 @@ } } Phi phi = new Phi(p.kind, block, graph()); - inputs().set(localsSize + i, phi); + setValueAt(localsSize + i, phi); return phi; } return null; @@ -303,8 +327,8 @@ * @return the value at index {@code i} which may be {@code null} */ public Value valueAt(int i) { - assert i < (localsSize + stackSize); - return (Value) inputs().get(i); + assert i < (localsSize + stackSize + locksSize); + return (Value) inputs().get(INPUT_COUNT + i); } /** @@ -341,7 +365,7 @@ phi.makeDead(); } } - inputs().set(i, null); + setValueAt(i, null); continue; } Phi phi = null; @@ -382,11 +406,9 @@ } public Merge block() { - if (usages().size() > 0) { - assert usages().size() == 1; - Node node = usages().get(0); - if (node instanceof Merge) { - return (Merge) node; + for (Node usage : usages()) { + if (usage instanceof Merge) { + return (Merge) usage; } } return null; @@ -432,6 +454,9 @@ proc.doValue(value); } } + if (outerFrameState() != null) { + outerFrameState().forEachLiveStateValue(proc); + } } @Override @@ -466,12 +491,12 @@ @Override public FrameState copy() { - return new FrameState(bci, localsSize, stackSize, locksSize, graph()); + return new FrameState(method, bci, localsSize, stackSize, locksSize, graph()); } private FrameState copy(int newBci) { - return new FrameState(newBci, localsSize, stackSize, locksSize, graph()); + return new FrameState(method, newBci, localsSize, stackSize, locksSize, graph()); } @Override @@ -484,13 +509,8 @@ } @Override - public void setValueAt(int j, Value v) { - inputs().set(j, v); - } - - @Override public Node copy(Graph into) { - FrameState x = new FrameState(bci, localsSize, stackSize, locksSize, into); + FrameState x = new FrameState(method, bci, localsSize, stackSize, locksSize, into); x.setNonNull(isNonNull()); return x; } diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java Tue Jun 07 11:19:01 2011 +0200 @@ -46,4 +46,6 @@ void setValueAt(int j, Value v); + Value outerFrameState(); + } diff -r 463657856f86 -r 7474789a8120 graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Tue Jun 07 11:19:01 2011 +0200 @@ -28,7 +28,6 @@ import java.util.*; import com.oracle.graal.graph.*; -import com.sun.c1x.graph.*; import com.sun.c1x.ir.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -44,7 +43,10 @@ private int stackIndex; + private final RiMethod method; + public FrameStateBuilder(RiMethod method, Graph graph) { + this.method = method; this.graph = graph; this.locals = new Value[method.maxLocals()]; this.stack = new Value[method.maxStackSize()]; @@ -97,12 +99,14 @@ } public FrameState create(int bci) { - return new FrameState(bci, locals, stack, stackIndex, locks, graph); + return new FrameState(method, bci, locals, stack, stackIndex, locks, graph); } @Override public FrameState duplicateWithEmptyStack(int bci) { - return new FrameState(bci, locals, new Value[0], 0, locks, graph); + FrameState frameState = new FrameState(method, bci, locals, new Value[0], 0, locks, graph); + frameState.setOuterFrameState(outerFrameState()); + return frameState; } /** @@ -359,9 +363,8 @@ * @param scope the IRScope in which this locking operation occurs * @param obj the object being locked */ - public void lock(IR ir, Value obj, int totalNumberOfLocks) { + public void lock(Value obj) { locks.add(obj); - ir.updateMaxLocks(totalNumberOfLocks); } /** @@ -496,4 +499,8 @@ } } + @Override + public FrameState outerFrameState() { + return null; + } } diff -r 463657856f86 -r 7474789a8120 graal/GraalGraph/src/com/oracle/graal/graph/EndNode.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/EndNode.java Tue Jun 07 11:18:18 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +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.graal.graph; - -public class EndNode extends Node { - - private static final int INPUT_COUNT = 0; - - private static final int SUCCESSOR_COUNT = 0; - - @Override - protected int inputCount() { - return super.inputCount() + INPUT_COUNT; - } - - @Override - protected int successorCount() { - return super.successorCount() + SUCCESSOR_COUNT; - } - - EndNode(Graph graph) { - super(INPUT_COUNT, SUCCESSOR_COUNT, graph); - } - - @Override - public Node replace(Node other) { - throw new UnsupportedOperationException(); - } - - @Override - public void delete() { - throw new UnsupportedOperationException(); - } - - @Override - public Node copy(Graph into) { - throw new UnsupportedOperationException(); - } -} diff -r 463657856f86 -r 7474789a8120 graal/GraalGraph/src/com/oracle/graal/graph/Graph.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java Tue Jun 07 11:19:01 2011 +0200 @@ -34,13 +34,11 @@ private final ArrayList nodes; private final StartNode start; - private final EndNode end; int nextId; public Graph() { nodes = new ArrayList(); start = new StartNode(this); - end = new EndNode(this); } public List getNodes() { @@ -61,10 +59,6 @@ return start; } - public EndNode end() { - return end; - } - public NodeBitMap createNodeBitMap() { return new NodeBitMap(this); } @@ -73,7 +67,7 @@ return new NodeMap(this); } - public void addDuplicate(Collection nodes, Map replacements) { + public Map addDuplicate(Collection nodes, Map replacements) { Map newNodes = new HashMap(); // create node duplicates for (Node node : nodes) { @@ -131,5 +125,6 @@ } } } + return newNodes; } } diff -r 463657856f86 -r 7474789a8120 graal/GraalGraph/src/com/oracle/graal/graph/Node.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/Node.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Node.java Tue Jun 07 11:19:01 2011 +0200 @@ -80,7 +80,7 @@ return graph; } - public T lookup(Class clazz) { + public T lookup(Class clazz) { return null; } @@ -118,7 +118,7 @@ public void delete() { assert !isDeleted(); - assert usages.size() == 0 && predecessors.size() == 0; + assert usages.size() == 0 && predecessors.size() == 0 : "usages: " + usages.size() + ", predecessors: " + predecessors().size(); assert predecessorsIndex.size() == 0; for (int i = 0; i < inputs.size(); ++i) { inputs.set(i, Null); diff -r 463657856f86 -r 7474789a8120 graal/GraalGraph/src/com/oracle/graal/graph/NodeArray.java --- a/graal/GraalGraph/src/com/oracle/graal/graph/NodeArray.java Tue Jun 07 11:18:18 2011 +0200 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/NodeArray.java Tue Jun 07 11:19:01 2011 +0200 @@ -127,8 +127,10 @@ if (value.predecessors.get(i) == clearedNode && value.predecessorsIndex.get(i) == clearedIndex) { value.predecessors.set(i, self()); value.predecessorsIndex.set(i, index); + return; } } + assert false; } public int size() { diff -r 463657856f86 -r 7474789a8120 graal/GraalGraph/src/com/oracle/graal/graph/Op.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Op.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,28 @@ +/* + * 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.graal.graph; + + +public interface Op { + +} diff -r 463657856f86 -r 7474789a8120 graal/GraalGraph/src/com/oracle/graal/graph/Phase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalGraph/src/com/oracle/graal/graph/Phase.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,33 @@ +/* + * 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.graal.graph; + +public abstract class Phase { + + public final void apply(Graph graph) { + assert graph != null; + run(graph); + } + + protected abstract void run(Graph graph); +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/build.xml Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project at.ssw.visualizer.texteditor. + + diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/manifest.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/manifest.mf Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: at.ssw.visualizer.texteditor +OpenIDE-Module-Layer: at/ssw/visualizer/texteditor/layer.xml +OpenIDE-Module-Localizing-Bundle: at/ssw/visualizer/texteditor/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/build-impl.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/build-impl.xml Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/genfiles.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/genfiles.properties Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=be4656f4 +build.xml.script.CRC32=eccfca0f +build.xml.stylesheet.CRC32=a56c6a5b@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=be4656f4 +nbproject/build-impl.xml.script.CRC32=72c794c1 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1 diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/platform.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/platform.properties Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,125 @@ +# Deprecated since 5.0u1; for compatibility with 5.0: +disabled.clusters=\ + apisupport1,\ + enterprise4,\ + harness,\ + java1,\ + mobility8,\ + nb6.0,\ + profiler2,\ + ruby1,\ + uml4,\ + visualweb1,\ + xml1 +disabled.modules=\ + org.apache.xml.resolver,\ + org.netbeans.api.debugger,\ + org.netbeans.api.xml,\ + org.netbeans.core.ide,\ + org.netbeans.core.multiview,\ + org.netbeans.core.output2,\ + org.netbeans.insane,\ + org.netbeans.lib.cvsclient,\ + org.netbeans.libs.commons_logging,\ + org.netbeans.libs.freemarker,\ + org.netbeans.libs.ini4j,\ + org.netbeans.libs.jsch,\ + org.netbeans.libs.jsr223,\ + org.netbeans.libs.lucene,\ + org.netbeans.libs.svnClientAdapter,\ + org.netbeans.libs.xerces,\ + org.netbeans.modules.autoupdate.services,\ + org.netbeans.modules.autoupdate.ui,\ + org.netbeans.modules.classfile,\ + org.netbeans.modules.core.kit,\ + org.netbeans.modules.css.visual,\ + org.netbeans.modules.db,\ + org.netbeans.modules.db.core,\ + org.netbeans.modules.db.kit,\ + org.netbeans.modules.db.sql.editor,\ + org.netbeans.modules.db.sql.visualeditor,\ + org.netbeans.modules.dbapi,\ + org.netbeans.modules.defaults,\ + org.netbeans.modules.diff,\ + org.netbeans.modules.editor.bookmarks,\ + org.netbeans.modules.editor.bracesmatching,\ + org.netbeans.modules.editor.codetemplates,\ + org.netbeans.modules.editor.completion,\ + org.netbeans.modules.editor.errorstripe,\ + org.netbeans.modules.editor.errorstripe.api,\ + org.netbeans.modules.editor.guards,\ + org.netbeans.modules.editor.highlights,\ + org.netbeans.modules.editor.indent,\ + org.netbeans.modules.editor.kit,\ + org.netbeans.modules.editor.structure,\ + org.netbeans.modules.extbrowser,\ + org.netbeans.modules.favorites,\ + org.netbeans.modules.html,\ + org.netbeans.modules.html.editor,\ + org.netbeans.modules.html.editor.lib,\ + org.netbeans.modules.html.lexer,\ + org.netbeans.modules.httpserver,\ + org.netbeans.modules.ide.kit,\ + org.netbeans.modules.image,\ + org.netbeans.modules.javahelp,\ + org.netbeans.modules.jumpto,\ + org.netbeans.modules.languages,\ + org.netbeans.modules.languages.bat,\ + org.netbeans.modules.languages.css,\ + org.netbeans.modules.languages.diff,\ + org.netbeans.modules.languages.javascript,\ + org.netbeans.modules.languages.manifest,\ + org.netbeans.modules.languages.sh,\ + org.netbeans.modules.localhistory,\ + org.netbeans.modules.project.ant,\ + org.netbeans.modules.project.libraries,\ + org.netbeans.modules.projectapi,\ + org.netbeans.modules.projectui,\ + 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.servletapi,\ + org.netbeans.modules.subversion,\ + org.netbeans.modules.tasklist.kit,\ + org.netbeans.modules.tasklist.projectint,\ + org.netbeans.modules.tasklist.todo,\ + org.netbeans.modules.tasklist.ui,\ + org.netbeans.modules.templates,\ + org.netbeans.modules.timers,\ + org.netbeans.modules.usersguide,\ + org.netbeans.modules.utilities,\ + org.netbeans.modules.utilities.project,\ + org.netbeans.modules.versioning,\ + org.netbeans.modules.versioning.system.cvss,\ + org.netbeans.modules.versioning.util,\ + org.netbeans.modules.web.flyingsaucer,\ + org.netbeans.modules.xml.axi,\ + org.netbeans.modules.xml.catalog,\ + org.netbeans.modules.xml.core,\ + 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.util.enumerations +enabled.clusters=\ + ide8,\ + platform7 +nbplatform.active=default diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/project.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/project.properties Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,2 @@ +javac.source=1.5 +javac.compilerargs=-Xlint -Xlint:-serial diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/project.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/project.xml Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,148 @@ + + + org.netbeans.modules.apisupport.project + + + at.ssw.visualizer.texteditor + + + + com.sun.hotspot.igv.data + + + + 1.0 + + + + org.netbeans.modules.editor + + + + 3 + 1.42.1.3.9.2 + + + + org.netbeans.modules.editor.fold + + + + 1 + 1.10.1 + + + + org.netbeans.modules.editor.lib + + + + 3 + 3.8.1.13.8 + + + + org.netbeans.modules.editor.lib2 + + + + 1 + 1.28.1.2 + + + + org.netbeans.modules.editor.mimelookup + + + + 1 + 1.11.1 + + + + org.netbeans.modules.editor.settings + + + + 1 + 1.24.1 + + + + org.netbeans.modules.editor.util + + + + 1 + 1.28.1 + + + + org.openide.actions + + + + 6.9.1.1 + + + + org.openide.awt + + + + 7.23.1 + + + + org.openide.nodes + + + + 7.9.1.1 + + + + org.openide.text + + + + 6.22.1 + + + + org.openide.util + + + + 7.22.1.1 + + + + org.openide.util.lookup + + + + 8.3.1 + + + + org.openide.windows + + + + 6.26.1 + + + + + at.ssw.visualizer.texteditor + at.ssw.visualizer.texteditor.fold + at.ssw.visualizer.texteditor.highlight + at.ssw.visualizer.texteditor.hyperlink + at.ssw.visualizer.texteditor.model + at.ssw.visualizer.texteditor.tooltip + at.ssw.visualizer.texteditor.view + + + + diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/suite.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/nbproject/suite.properties Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,1 @@ +suite.dir=${basedir}/.. diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/core/selection/Selection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/core/selection/Selection.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,72 @@ +package at.ssw.visualizer.core.selection; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.swing.Timer; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * + * @author Christian Wimmer + */ +public class Selection { + private Map elements; + private List listeners; + private Timer eventTimer; + + private ActionListener eventTimerListener = new ActionListener() { + public void actionPerformed(ActionEvent event) { + doFireChangeEvent(); + } + }; + + public Selection() { + elements = new HashMap(); + listeners = new ArrayList(); + eventTimer = new Timer(100, eventTimerListener); + eventTimer.setRepeats(false); + } + + private void doPut(Class clazz, Object element) { + elements.put(clazz, element); + for (Class i : clazz.getInterfaces()) { + doPut(i, element); + } + } + + public void put(Object element) { + doPut(element.getClass(), element); + fireChangeEvent(); + SelectionManager.getDefault().fireChangeEvent(); + } + + @SuppressWarnings(value = "unchecked") + public T get(Class clazz) { + return (T) elements.get(clazz); + } + + + protected void doFireChangeEvent() { + ChangeEvent event = new ChangeEvent(this); + for (ChangeListener listener : listeners.toArray(new ChangeListener[listeners.size()])) { + listener.stateChanged(event); + } + } + + protected void fireChangeEvent() { + eventTimer.restart(); + } + + public void addChangeListener(ChangeListener listener) { + listeners.add(listener); + } + + public void removeChangeListener(ChangeListener listener) { + listeners.remove(listener); + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/core/selection/SelectionManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/core/selection/SelectionManager.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,56 @@ +package at.ssw.visualizer.core.selection; + +import javax.swing.event.ChangeListener; + +/** + * + * @author Christian Wimmer + */ +public class SelectionManager { + private static final SelectionManager SINGLETON = new SelectionManager(); + + public static SelectionManager getDefault() { + return SINGLETON; + } + + + /** Default selection returned when no TopComponent is active. + * It is also used to maintain listeners added to the selection manager. */ + private final Selection emptySelection; + private Selection curSelection; + + private SelectionManager() { + emptySelection = new Selection(); + curSelection = emptySelection; + } + + public Selection getCurSelection() { + return curSelection; + } + + public void setSelection(Selection sel) { + if (curSelection != sel) { + curSelection = sel; + fireChangeEvent(); + } + } + + public void removeSelection(Selection sel) { + if (curSelection == sel) { + curSelection = emptySelection; + fireChangeEvent(); + } + } + + protected void fireChangeEvent() { + emptySelection.fireChangeEvent(); + } + + public void addChangeListener(ChangeListener listener) { + emptySelection.addChangeListener(listener); + } + + public void removeChangeListener(ChangeListener listener) { + emptySelection.removeChangeListener(listener); + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/core/selection/SelectionProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/core/selection/SelectionProvider.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,9 @@ +package at.ssw.visualizer.core.selection; + +/** + * + * @author Christian Wimmer + */ +public interface SelectionProvider { + public Selection getSelection(); +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/Bundle.properties Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Text Editor diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/Editor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/Editor.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,127 @@ +package at.ssw.visualizer.texteditor; + +import at.ssw.visualizer.core.selection.Selection; +import at.ssw.visualizer.core.selection.SelectionManager; +import at.ssw.visualizer.core.selection.SelectionProvider; +import at.ssw.visualizer.texteditor.model.BlockRegion; +import at.ssw.visualizer.texteditor.model.Text; +import com.sun.hotspot.igv.data.InputBlock; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.openide.text.CloneableEditor; +import org.openide.windows.TopComponent; + +/** + * Abstract template class of a Editor class of the Visualizer. + * + * Must be initialized with a custom EditorSupport class and the + * method creatClonedObject must be overwritten by + * the Editor implementation. + * + * @author Alexander Reder + */ +public abstract class Editor extends CloneableEditor implements SelectionProvider { + + protected Selection selection; + private boolean selectionUpdating; + private InputBlock[] curBlocks; + private boolean initialized; + + protected Editor(EditorSupport support) { + super(support); + selection = new Selection(); + selection.put(support.getControlFlowGraph()); + selection.addChangeListener(selectionListener); + } + + public Selection getSelection() { + return selection; + } + + @Override + protected void componentShowing() { + super.componentShowing(); + if (!initialized) { + getEditorPane().addCaretListener(caretListener); + initialized = true; + } + } + + @Override + protected void componentActivated() { + super.componentActivated(); + SelectionManager.getDefault().setSelection(selection); + } + + @Override + protected void componentClosed() { + super.componentClosed(); + SelectionManager.getDefault().removeSelection(selection); + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER; + } + + private ChangeListener selectionListener = new ChangeListener() { + public void stateChanged(ChangeEvent event) { + if (selectionUpdating) { + return; + } + selectionUpdating = true; + + Text text = (Text) getEditorPane().getDocument().getProperty(Text.class); + InputBlock[] newBlocks = selection.get(InputBlock[].class); + + if (newBlocks != null && newBlocks.length > 0 && !Arrays.equals(curBlocks, newBlocks)) { + BlockRegion r = text.getBlocks().get(newBlocks[0]); + int startOffset = r.getNameStart(); + int endOffset = r.getNameEnd(); + + if (newBlocks.length > 1) { + for (InputBlock b : newBlocks) { + r = text.getBlocks().get(b); + startOffset = Math.min(startOffset, r.getStart()); + endOffset = Math.max(endOffset, r.getEnd()); + } + } + + getEditorPane().select(startOffset, endOffset); + } + curBlocks = newBlocks; + selectionUpdating = false; + } + }; + + + private CaretListener caretListener = new CaretListener() { + public void caretUpdate(CaretEvent event) { + if (selectionUpdating) { + return; + } + selectionUpdating = true; + + Text text = (Text) getEditorPane().getDocument().getProperty(Text.class); + List newBlocks = new ArrayList(); + int startOffset = Math.min(event.getDot(), event.getMark()); + int endOffset = Math.max(event.getDot(), event.getMark()); + + for (BlockRegion region : text.getBlocks().values()) { + if (region.getStart() <= endOffset && region.getEnd() > startOffset) { + newBlocks.add(region.getBlock()); + } + } + + curBlocks = newBlocks.toArray(new InputBlock[newBlocks.size()]); + selection.put(curBlocks); + selectionUpdating = false; + } + }; + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/EditorKit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/EditorKit.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,31 @@ +package at.ssw.visualizer.texteditor; + +import at.ssw.visualizer.texteditor.tooltip.ToolTipAction; +import javax.swing.Action; +import javax.swing.text.TextAction; +import org.netbeans.modules.editor.NbEditorKit; + +/** + * Abstract template class of a EditorKit class of the Visualizer. + * + * The scanner field must be initialized with the + * custom Scanner implementation and the method + * getContentType must be overwritten and return the mime type + * for the editor. + * + * @author Alexander Reder + */ +public abstract class EditorKit extends NbEditorKit { + + @Override + protected Action[] getCustomActions() { + Action[] prev = super.getCustomActions(); + Action[] added = new Action[]{new ToolTipAction()}; + if (prev != null) { + return TextAction.augmentList(prev, added); + } else { + return added; + } + } + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/EditorSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/EditorSupport.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,149 @@ +package at.ssw.visualizer.texteditor; + +import at.ssw.visualizer.texteditor.model.Text; +import com.sun.hotspot.igv.data.InputGraph; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Date; +import javax.swing.text.EditorKit; +import javax.swing.text.StyledDocument; +import org.openide.cookies.EditorCookie; +import org.openide.cookies.EditCookie; +import org.openide.text.CloneableEditorSupport; +import org.openide.windows.CloneableOpenSupport; + +/** + * Abstract template class of a EditorSupport class of the + * Visulizer. + * + * The text field must be initialized by the implementing class + * and the methods createCloneableEditor and + * initializeCloneableEditor must be overwritten by the implenting class. + * createCloneableEditor must return a custom implementation + * of the Editor class. + * initializeClonableEditor is used to set the icon, e.g. + * editor.setIcon(Utilities.loadImage(IconsImage)); . + * + * @author Bernhard Stiftner + * @author Christian Wimmer + * @author Alexander Reder + */ +public abstract class EditorSupport extends CloneableEditorSupport implements EditCookie, EditorCookie, EditorCookie.Observable { + + protected InputGraph cfg; + protected Text text; + + protected EditorSupport(InputGraph cfg) { + super(new Env()); + ((Env) this.env).editorSupport = this; + this.cfg = cfg; + } + + public InputGraph getControlFlowGraph() { + return cfg; + } + + @Override + protected StyledDocument createStyledDocument(EditorKit kit) { + StyledDocument doc = super.createStyledDocument(kit); + + // Back-link from Document to our internal data model. + doc.putProperty(Text.class, text); + doc.putProperty(InputGraph.class, cfg); + + return doc; + } + + public abstract String getMimeType(); + + protected String messageOpening() { + return "Opening " + messageToolTip(); + } + + protected String messageOpened() { + return "Opened " + messageToolTip(); + } + + protected String messageSave() { + throw new UnsupportedOperationException("Not supported yet."); + } + + protected String messageName() { + return cfg.getName(); + } + + protected String messageToolTip() { + return cfg.getGroup().getName() + " - " + cfg.getName(); + } + + public static class Env implements CloneableEditorSupport.Env { + + private PropertyChangeSupport prop = new PropertyChangeSupport(this); + private VetoableChangeSupport veto = new VetoableChangeSupport(this); + + /** + * Back-link to outer class EditorSupport. Env must be a static class + * because it is passed to super constructor of EditorSupport. + */ + private EditorSupport editorSupport; + + public InputStream inputStream() throws IOException { + return new ByteArrayInputStream(editorSupport.text.getText().getBytes()); + } + + public OutputStream outputStream() throws IOException { + throw new IOException("Editor is readonly"); + } + + public Date getTime() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getMimeType() { + return editorSupport.getMimeType(); + } + + public boolean isValid() { + return true; + } + + public boolean isModified() { + return false; + } + + public void markModified() throws IOException { + throw new IOException("Editor is readonly"); + } + + public void unmarkModified() { + // Nothing to do. + } + + public CloneableOpenSupport findCloneableOpenSupport() { + return editorSupport; + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + prop.addPropertyChangeListener(l); + } + + public void removePropertyChangeListener(PropertyChangeListener l) { + prop.removePropertyChangeListener(l); + } + + public void addVetoableChangeListener(VetoableChangeListener l) { + veto.addVetoableChangeListener(l); + } + + public void removeVetoableChangeListener(VetoableChangeListener l) { + veto.removeVetoableChangeListener(l); + } + } + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/fold/FoldManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/fold/FoldManager.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,81 @@ +package at.ssw.visualizer.texteditor.fold; + +import at.ssw.visualizer.texteditor.model.FoldingRegion; +import at.ssw.visualizer.texteditor.model.Text; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JComponent; +import javax.swing.event.DocumentEvent; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.fold.Fold; +import org.netbeans.editor.CodeFoldingSideBar; +import org.netbeans.spi.editor.fold.FoldHierarchyTransaction; +import org.netbeans.spi.editor.fold.FoldOperation; + +/** + * + * @author Alexander Reder + */ +public class FoldManager implements org.netbeans.spi.editor.fold.FoldManager { + + protected FoldOperation operation; + + public void init(FoldOperation operation) { + this.operation = operation; + } + + public void initFolds(FoldHierarchyTransaction transaction) { + Document document = operation.getHierarchy().getComponent().getDocument(); + Text text = (Text) document.getProperty(Text.class); + if (document.getLength() == 0 || text == null) { + return; + } + + try { + for (FoldingRegion fr : text.getFoldings()) { + operation.addToHierarchy(fr.getKind(), fr.getKind().toString(), fr.isInitiallyCollapsed(), fr.getStart(), fr.getEnd(), 0, 0, null, transaction); + } + } catch (BadLocationException ex) { + Logger logger = Logger.getLogger(FoldManager.class.getName()); + logger.log(Level.SEVERE, ex.getMessage(), ex); + } + } + + public void insertUpdate(DocumentEvent arg0, FoldHierarchyTransaction arg1) { + } + + public void removeUpdate(DocumentEvent arg0, FoldHierarchyTransaction arg1) { + } + + public void changedUpdate(DocumentEvent arg0, FoldHierarchyTransaction arg1) { + } + + public void removeEmptyNotify(Fold arg0) { + } + + public void removeDamagedNotify(Fold arg0) { + } + + public void expandNotify(Fold arg0) { + } + + public void release() { + } + + public static class FoldManagerFactory implements org.netbeans.spi.editor.fold.FoldManagerFactory { + + public FoldManager createFoldManager() { + return new FoldManager(); + } + } + + public static class SideBarFactory implements org.netbeans.editor.SideBarFactory { + + public JComponent createSideBar(JTextComponent target) { + return new CodeFoldingSideBar(target); + } + } + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/highlight/HighlightsContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/highlight/HighlightsContainer.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,119 @@ +package at.ssw.visualizer.texteditor.highlight; + +import at.ssw.visualizer.texteditor.model.Scanner; +import at.ssw.visualizer.texteditor.model.Text; +import at.ssw.visualizer.texteditor.model.TextRegion; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.AttributeSet; +import javax.swing.text.Caret; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import javax.swing.text.SimpleAttributeSet; +import org.netbeans.api.editor.mimelookup.MimeLookup; +import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.api.editor.settings.FontColorSettings; +import org.netbeans.editor.TokenID; +import org.netbeans.spi.editor.highlighting.HighlightsSequence; +import org.netbeans.spi.editor.highlighting.ZOrder; +import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer; +import org.openide.util.WeakListeners; + +/** + * + * @author Christian Wimmer + * @author Alexander Reder + */ +public class HighlightsContainer extends AbstractHighlightsContainer { + + private static final String HIGHLIGHT_COLORING = "at-ssw-visualizer-highlight"; + + protected final JTextComponent component; + protected final Document document; + protected final AttributeSet highlightColoring; + protected final Scanner scanner; + + protected TextRegion[] curRegions = null; + + private final CaretListener caretListener = new CaretListener() { + + public void caretUpdate(CaretEvent event) { + TextRegion[] newRegions = findRegions(); + if (newRegions != curRegions) { + curRegions = newRegions; + fireHighlightsChange(0, document.getLength()); + } + } + + }; + + protected HighlightsContainer(JTextComponent component, Document document) { + this.document = document; + this.component = component; + component.addCaretListener(WeakListeners.create(CaretListener.class, caretListener, component)); + + // Load the coloring. + Text t = (Text) document.getProperty(Text.class); + MimePath mimePath = MimePath.parse(t.getMimeType()); + FontColorSettings fcs = MimeLookup.getLookup(mimePath).lookup(FontColorSettings.class); + AttributeSet highlight = fcs.getFontColors(HIGHLIGHT_COLORING); + highlightColoring = highlight != null ? highlight : SimpleAttributeSet.EMPTY; + + scanner = t.getScanner(); + scanner.setText(document); + curRegions = findRegions(); + } + + public HighlightsSequence getHighlights(int startOffset, int endOffset) { + return new RegionSequence(); + } + + protected TextRegion[] findRegions() { + Text text = (Text) document.getProperty(Text.class); + Caret caret = component.getCaret(); + if (text == null || caret == null) { + return null; + } + scanner.findTokenBegin(caret.getDot()); + TokenID token = scanner.nextToken(); + if (token.getNumericID() < 0) { + return null; + } + + return text.getHighlighting(scanner.getTokenString()); + } + + protected class RegionSequence implements HighlightsSequence { + + private int idx = -1; + + public boolean moveNext() { + idx++; + return curRegions != null && idx < curRegions.length; + } + + public int getStartOffset() { + return curRegions[idx].getStart(); + } + + public int getEndOffset() { + return curRegions[idx].getEnd(); + } + + public AttributeSet getAttributes() { + return highlightColoring; + } + } + + public static final class HighlightsLayerFactory implements org.netbeans.spi.editor.highlighting.HighlightsLayerFactory { + + public org.netbeans.spi.editor.highlighting.HighlightsLayer[] createLayers(Context context) { + Text t = (Text) context.getDocument().getProperty(Text.class); + if(t == null) { + return new org.netbeans.spi.editor.highlighting.HighlightsLayer[0]; + } + return new org.netbeans.spi.editor.highlighting.HighlightsLayer[]{org.netbeans.spi.editor.highlighting.HighlightsLayer.create("at-ssw-visualizer-highlighting", ZOrder.SHOW_OFF_RACK, true, new HighlightsContainer(context.getComponent(), context.getDocument()))}; + } + + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/hyperlink/HyperlinkProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/hyperlink/HyperlinkProvider.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,57 @@ +package at.ssw.visualizer.texteditor.hyperlink; + +import at.ssw.visualizer.texteditor.model.Scanner; +import at.ssw.visualizer.texteditor.model.Text; +import at.ssw.visualizer.texteditor.model.TextRegion; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import org.netbeans.editor.TokenID; +import org.netbeans.editor.Utilities; + +/** + * + * @author Bernhard Stiftner + * @author Christian Wimmer + * @author Alexander Reder + */ +public class HyperlinkProvider implements org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider { + + protected Scanner scanner = null; + + protected TextRegion findTarget(Document doc, int offset) { + Text text = (Text) doc.getProperty(Text.class); + if (text == null) { + return null; + } + + scanner = text.getScanner(); + scanner.setText(doc); + scanner.findTokenBegin(offset); + TokenID token = scanner.nextToken(); + if (token.getNumericID() < 0) { + return null; + } + + return text.getHyperlinkTarget(scanner.getTokenString()); + } + + public boolean isHyperlinkPoint(Document doc, int offset) { + return findTarget(doc, offset) != null; + } + + public int[] getHyperlinkSpan(Document doc, int offset) { + if (findTarget(doc, offset) != null) { + return new int[]{scanner.getTokenOffset(), scanner.getTokenOffset() + scanner.getTokenLength()}; + } + return null; + } + + public void performClickAction(Document doc, int offset) { + TextRegion target = findTarget(doc, offset); + if (target != null) { + JTextComponent editor = Utilities.getFocusedComponent(); + editor.select(target.getStart(), target.getEnd()); + } + } + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/layer.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/layer.xml Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/BlockRegion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/BlockRegion.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,35 @@ +package at.ssw.visualizer.texteditor.model; + +import com.sun.hotspot.igv.data.InputBlock; + +/** + * + * @author Christian Wimmer + */ +public class BlockRegion extends TextRegion { + + private InputBlock block; + + private int nameStart; + private int nameEnd; + + public BlockRegion(InputBlock block, int start, int end, int nameStart, int nameEnd) { + super(start, end); + this.block = block; + this.nameStart = nameStart; + this.nameEnd = nameEnd; + } + + + public InputBlock getBlock() { + return block; + } + + public int getNameStart() { + return nameStart; + } + + public int getNameEnd() { + return nameEnd; + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/FoldingRegion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/FoldingRegion.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,32 @@ +package at.ssw.visualizer.texteditor.model; + +import org.netbeans.api.editor.fold.FoldType; + +/** + * + * @author Christian Wimmer + * @author Alexander Reder + */ +public class FoldingRegion extends TextRegion { + + + private FoldType kind; + private boolean initallyCollapsed; + + + public FoldingRegion(FoldType kind, int start, int end, boolean initiallyCollapsed) { + super(start, end); + this.kind = kind; + this.initallyCollapsed = initiallyCollapsed; + } + + + public FoldType getKind() { + return kind; + } + + public boolean isInitiallyCollapsed() { + return initallyCollapsed; + } + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/HoverParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/HoverParser.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,117 @@ +package at.ssw.visualizer.texteditor.model; + +import java.util.Iterator; + +/** + * + * @author ChristianWimmer + */ +public class HoverParser implements Iterator { + + private static String HOVER_START = "<@"; + private static String HOVER_SEP = "|@"; + private static String HOVER_END = ">@"; + private String text; + private int curPos; + private String curText; + private String curHover; + private boolean curNewLine; + + public static String firstLine(String text) { + if (text == null) { + return ""; + } + HoverParser p = new HoverParser(text); + StringBuilder result = new StringBuilder(text.length()); + while (p.hasNext()) { + String part = p.next(); + if (p.isNewLine()) { + break; + } + result.append(part); + } + return result.toString(); + } + + public HoverParser(String text) { + this.text = text; + } + + private void advance() { + int lineStart = text.indexOf('\n', curPos); + int nextStart = text.indexOf(HOVER_START, curPos); + + if (lineStart == curPos) { + curText = "\n"; + curHover = null; + curPos = lineStart + 1; + curNewLine = true; + while (curPos < text.length() && text.charAt(curPos) <= ' ') { + curPos++; + } + return; + } + curNewLine = false; + if (lineStart != -1 && (nextStart == -1 || lineStart < nextStart)) { + curText = text.substring(curPos, lineStart); + curHover = null; + curPos = lineStart; + return; + } + + if (nextStart == curPos) { + int nextSep = text.indexOf(HOVER_SEP, nextStart); + if (nextSep != -1) { + int nextEnd = text.indexOf(HOVER_END, nextSep); + if (nextEnd != -1) { + curText = text.substring(nextStart + HOVER_START.length(), nextSep); + curHover = text.substring(nextSep + HOVER_SEP.length(), nextEnd); + while (curHover.endsWith("\n")) { + curHover = curHover.substring(0, curHover.length() - 1); + } + curPos = nextEnd + HOVER_END.length(); + return; + } + } + } + + if (nextStart == curPos) { + // Incomplete hover sequence. Make sure we make progress by just advancing to the next chararter. + nextStart++; + } + + if (nextStart != -1) { + curText = text.substring(curPos, nextStart); + curHover = null; + curPos = nextStart; + } else if (curPos < text.length()) { + curText = text.substring(curPos); + curHover = null; + curPos = text.length(); + } else { + curText = null; + curHover = null; + } + } + + public boolean hasNext() { + return curPos < text.length(); + } + + public String next() { + advance(); + return curText; + } + + public String getHover() { + return curHover; + } + + public boolean isNewLine() { + return curNewLine; + } + + public void remove() { + throw new UnsupportedOperationException("Not supported."); + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/Scanner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/Scanner.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,192 @@ +package at.ssw.visualizer.texteditor.model; + +import java.util.BitSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import org.netbeans.editor.Syntax; +import org.netbeans.editor.TokenContextPath; + +/** + * The implementing class must specify the used TokenIDs and + * implement the scanner for the specified text. + * + * @author Alexander Reder + * @author Christian Wimmer + */ +public abstract class Scanner extends Syntax { + protected static final int EOF = 0; + protected static final BitSet DIGIT = charsOf("0123456789"); + protected static final BitSet HEX = charsOf("0123456789abcdefABCDEF"); + protected static final BitSet LETTER = charsOf("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + protected static final BitSet LETTER_DIGIT = charsOf("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + protected static final BitSet LC_LETTER = charsOf("_abcdefghijklmnopqrstuvwxyz"); + protected static final BitSet LC_LETTER_DIGIT = charsOf("0123456789_abcdefghijklmnopqrstuvwxyz"); + + protected static BitSet charsOf(String s) { + BitSet result = new BitSet(); + for (int i = 0; i < s.length(); i++) { + result.set(s.charAt(i)); + } + return result; + } + + protected BitSet whitespace; + protected char ch; + + public Scanner(String whitespace, TokenContextPath tokenContextPath) { + this.whitespace = charsOf(whitespace); + this.whitespace.set(EOF); + + this.tokenContextPath = tokenContextPath; + } + + public void setText(Document document) { + try { + setText(document.getText(0, document.getLength()), 0, document.getLength()); + } catch (BadLocationException ex) { + Logger logger = Logger.getLogger(Scanner.class.getName()); + logger.log(Level.SEVERE, ex.getMessage(), ex); + } + } + + public void setText(String s, int offset, int length) { + this.buffer = s.toCharArray(); + this.offset = offset; + this.tokenOffset = offset; + this.stopOffset = Math.min(buffer.length, offset + length); + } + + public String getTokenString() { + return new String(buffer, getTokenOffset(), getTokenLength()); + } + + public void findTokenBegin(int offset) { + this.offset = Math.max(offset, 0); + findTokenBegin(); + } + + /** + * If offset is in a token this method will read backwards until a + * whitespace character occurs. + */ + protected void findTokenBegin() { + if (offset >= stopOffset) { + offset = stopOffset - 1; + } + + if (!whitespace.get(buffer[offset])) { + while (offset > 0 && !whitespace.get(buffer[offset - 1])) { + offset--; + } + } + ch = buffer[offset]; + tokenOffset = offset; + } + + /** + * Reads the next character. + */ + protected void readNext() { + offset++; + if (offset < stopOffset) { + ch = buffer[offset]; + } else { + ch = EOF; + } + } + + protected boolean isWhitespace() { + boolean result = false; + while (whitespace.get(ch) && ch != EOF) { + result = true; + readNext(); + } + return result; + } + + /** + * Read to the next whitespace + */ + protected void readToWhitespace() { + do { + readNext(); + } while (!whitespace.get(ch)); + } + + private boolean readNextOrRestart(boolean result, boolean readNext) { + if (result) { + if (readNext) { + readNext(); + } + } else { + offset = tokenOffset; + ch = buffer[offset]; + } + return result; + } + + protected boolean isKeyword(Set keywords) { + int beginOffset = offset; + int endOffset = offset; + while (endOffset < stopOffset && !whitespace.get(buffer[endOffset])) { + endOffset++; + } + String word = new String(buffer, beginOffset, endOffset - beginOffset); + if (!keywords.contains(word)) { + return false; + } + + offset = endOffset - 1; + readNext(); + return true; + } + + protected boolean expectEnd() { + return readNextOrRestart(whitespace.get(ch), false); + } + + protected boolean expectEnd(char expected) { + return readNextOrRestart(ch == expected, false) && offset + 1 < stopOffset && whitespace.get(buffer[offset + 1]); + } + + protected boolean expectChar(char expected) { + return readNextOrRestart(ch == expected, true); + } + + protected boolean expectChar(BitSet expected) { + return readNextOrRestart(expected.get(ch), true); + } + + protected boolean expectChars(BitSet expected) { + while (expected.get(ch)) { + readNext(); + } + return true; + } + + protected boolean skipUntil(char expected) { + while (ch != expected && !whitespace.get(ch)) { + readNext(); + } + return expectChar(expected); + } + + protected boolean beforeChar(char before) { + int curOffset = offset - 1; + while (curOffset >= 0 && buffer[curOffset] != before && whitespace.get(buffer[curOffset])) { + curOffset--; + } + return curOffset >= 0 && buffer[curOffset] == before; + } + + protected boolean beforeChars(BitSet before) { + int curOffset = offset - 1; + while (curOffset >= 0 && !before.get(buffer[curOffset]) && whitespace.get(buffer[curOffset])) { + curOffset--; + } + return curOffset >= 0 && before.get(buffer[curOffset]); + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/Text.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/Text.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,83 @@ +package at.ssw.visualizer.texteditor.model; + +import com.sun.hotspot.igv.data.InputBlock; +import com.sun.hotspot.igv.data.InputGraph; +import java.util.Map; + +/** + * @author Christian Wimmer + * @author Alexander Reder + */ +public class Text { + + private InputGraph cfg; + + private String text; + private FoldingRegion[] foldings; + private Map hyperlinks; + private Map stringHovers; + private Map regionHovers; + private Map highlighting; + private Map blocks; + private Scanner scanner; + private String mimeType; + + + public Text(InputGraph cfg, String text, FoldingRegion[] foldings, Map hyperlinks, Map stringHovers, Map regionHovers, Map highlighting, Map blocks, Scanner scanner, String mimeType) { + this.cfg = cfg; + this.text = text; + this.foldings = foldings; + this.hyperlinks = hyperlinks; + this.stringHovers = stringHovers; + this.regionHovers = regionHovers; + this.highlighting = highlighting; + this.blocks = blocks; + this.scanner = scanner; + this.mimeType = mimeType; + } + + public InputGraph getCfg() { + return cfg; + } + + public String getText() { + return text; + } + + public FoldingRegion[] getFoldings() { + return foldings; + } + + public TextRegion getHyperlinkTarget(String key) { + return hyperlinks.get(key); + } + + public String getStringHover(String key) { + return stringHovers.get(key); + } + + public String getRegionHover(int position) { + for (TextRegion r : regionHovers.keySet()) { + if (r.getStart() <= position && r.getEnd() >= position) { + return regionHovers.get(r); + } + } + return null; + } + + public TextRegion[] getHighlighting(String key) { + return highlighting.get(key); + } + + public Map getBlocks() { + return blocks; + } + + public Scanner getScanner() { + return scanner; + } + + public String getMimeType() { + return mimeType; + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/TextBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/TextBuilder.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,102 @@ +package at.ssw.visualizer.texteditor.model; + +import com.sun.hotspot.igv.data.InputBlock; +import com.sun.hotspot.igv.data.InputGraph; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * @author Alexander Reder + */ +public abstract class TextBuilder { + + protected StringBuilder text; + protected Scanner scanner; + protected List foldingRegions; + protected Map hyperlinks; + protected Map stringHovers; + protected Map regionHovers; + protected Map highlighting; + protected Map blocks; + protected Set hoverKeys; + protected Map hoverDefinitions; + protected Map> hoverReferences; + + public TextBuilder() { + text = new StringBuilder(4 * 1024); + foldingRegions = new ArrayList(); + hyperlinks = new HashMap(); + stringHovers = new HashMap(); + regionHovers = new HashMap(); + highlighting = new HashMap(); + blocks = new HashMap(); + hoverKeys = new HashSet(); + hoverDefinitions = new HashMap(); + hoverReferences = new HashMap>(); + } + + public abstract Text buildDocument(InputGraph cfg); + + protected abstract void buildHighlighting(); + + protected Text buildText(InputGraph cfg, String mimeType) { + buildHovers(); + buildHighlighting(); + return new Text(cfg, text.toString(), foldingRegions.toArray(new FoldingRegion[foldingRegions.size()]), hyperlinks, stringHovers, regionHovers, highlighting, blocks, scanner, mimeType); + } + + protected void appendBlockDetails(InputBlock block) { + text.append(blockDetails(block)); + } + + protected String blockDetails(InputBlock block) { + StringBuilder sb = new StringBuilder(); + sb.append(block.getName()); + hoverKeys.add(block.getName()); + // TODO: predecessors, successors, BCI, ... + return sb.toString(); + } + + protected void appendBlockList(StringBuilder sb, String prefix, List blocks) { + for (InputBlock block : blocks) { + sb.append(prefix); + prefix = ","; + sb.append(block.getName()); + } + } + + private void appendList(StringBuilder sb, String prefix, List values) { + for (String value : values) { + sb.append(prefix).append(value); + prefix = ","; + } + } + + protected void buildHovers() { + StringBuilder sb; + for(String key : hoverKeys) { + sb = new StringBuilder(); + if(hoverDefinitions.containsKey(key) && hoverReferences.containsKey(key)) { + sb.append("Definition;\n"); + sb.append(hoverDefinitions.get(key)); + sb.append("\n"); + } + if(hoverReferences.containsKey(key)) { + sb.append("References:\n"); + for(String ref : hoverReferences.get(key)) { + sb.append(ref); + sb.append("\n"); + } + } + if(sb.length() > 0) { + stringHovers.put(key, sb.toString().substring(0, sb.length() - 1)); + } + } + } + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/TextRegion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/model/TextRegion.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,27 @@ +package at.ssw.visualizer.texteditor.model; + +/** + * + * @author Christian Wimmer + * @author Alexander Reder + */ +public class TextRegion { + + private int start; + private int end; + + public TextRegion(int start, int end) { + this.start = start; + this.end = end; + } + + + public int getStart() { + return start; + } + + public int getEnd() { + return end; + } + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/preferences.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/preferences.xml Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,6 @@ + + + + + + diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/tooltip/StyledToolTip.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/tooltip/StyledToolTip.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,57 @@ +package at.ssw.visualizer.texteditor.tooltip; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import javax.swing.JEditorPane; +import javax.swing.JPanel; +import javax.swing.border.LineBorder; +import javax.swing.text.EditorKit; + +/** + * + * @author Bernhard Stiftner + * @author Christian Wimmer + * @author Alexander Reder + */ +public class StyledToolTip extends JPanel { + + public static final int BORDER = 2; + + private final String text; + private final JEditorPane toolTipPane; + + public StyledToolTip(String text, EditorKit editorKit) { + this.text = text; + + setBackground(new Color(235, 235, 163)); + setBorder(new LineBorder(Color.BLACK)); + setOpaque(true); + setLayout(new BorderLayout()); + + toolTipPane = new JEditorPane(); + toolTipPane.setEditable(false); + toolTipPane.setEditorKit(editorKit); + toolTipPane.setText(text); + + add(toolTipPane, BorderLayout.CENTER); + } + + @Override + public Dimension getPreferredSize() { + // Workaround: JEditorPane does not provide a proper width (only few pixels), + // so make the tooltip as large as the editor it is shown in + Dimension prefSize = super.getPreferredSize(); + prefSize.width = Integer.MAX_VALUE; + return prefSize; + } + + @Override + protected void paintComponent(Graphics g) { + // Workaround: Add a new line at the end so that the caret is not in the visible area. + toolTipPane.setText(text + "\n"); + + super.paintComponent(g); + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/tooltip/ToolTipAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/tooltip/ToolTipAction.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,67 @@ +package at.ssw.visualizer.texteditor.tooltip; + +import at.ssw.visualizer.texteditor.model.Scanner; +import at.ssw.visualizer.texteditor.model.Text; +import java.awt.event.ActionEvent; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorActionRegistration; +import org.netbeans.editor.BaseDocument; +import org.netbeans.editor.EditorUI; +import org.netbeans.editor.PopupManager; +import org.netbeans.editor.TokenID; +import org.netbeans.editor.Utilities; +import org.netbeans.editor.ext.ExtKit; +import org.netbeans.editor.ext.ToolTipSupport; +import org.netbeans.modules.editor.NbEditorKit; + +/** + * + * @author Christian Wimmer + * @author Alexander Reder + */ +public class ToolTipAction extends NbEditorKit.NbBuildToolTipAction { + public ToolTipAction() { + putValue(NAME, ExtKit.buildToolTipAction); + } + + @Override + public void actionPerformed(ActionEvent evt, JTextComponent target) { + if (!showTooltip(target)) { + super.actionPerformed(evt, target); + } + } + + private boolean showTooltip(JTextComponent target) { + BaseDocument document = Utilities.getDocument(target); + Text text = (Text) document.getProperty(Text.class); + if (text == null) { + return false; + } + + EditorUI ui = Utilities.getEditorUI(target); + ToolTipSupport tts = ui.getToolTipSupport(); + int offset = target.viewToModel(tts.getLastMouseEvent().getPoint()); + + String toolTipText = text.getRegionHover(offset); + + if (toolTipText == null) { + Scanner scanner = text.getScanner(); + scanner.setText(document); + scanner.findTokenBegin(offset); + TokenID token = scanner.nextToken(); + if (token.getNumericID() < 0) { + return false; + } + + toolTipText = text.getStringHover(scanner.getTokenString()); + if (toolTipText == null) { + return false; + } + } + + StyledToolTip tooltip = new StyledToolTip(toolTipText, target.getUI().getEditorKit(target)); + + tts.setToolTip(tooltip, PopupManager.ViewPortBounds, PopupManager.Largest, 0, 0); + return true; + } +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/view/AbstractTextViewTopComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Text Editor/src/at/ssw/visualizer/texteditor/view/AbstractTextViewTopComponent.java Tue Jun 07 11:19:01 2011 +0200 @@ -0,0 +1,78 @@ +package at.ssw.visualizer.texteditor.view; + +import at.ssw.visualizer.core.selection.Selection; +import at.ssw.visualizer.core.selection.SelectionManager; +import at.ssw.visualizer.texteditor.EditorKit; +import com.sun.hotspot.igv.data.InputBlock; +import com.sun.hotspot.igv.data.InputGraph; +import java.awt.BorderLayout; +import java.util.Arrays; +import javax.swing.BorderFactory; +import javax.swing.JEditorPane; +import javax.swing.JScrollPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.openide.windows.TopComponent; + +/** + * + * @author Alexander Reder + */ +public abstract class AbstractTextViewTopComponent extends TopComponent { + + protected InputGraph curCFG; + protected InputBlock[] curBlocks; + + private JEditorPane editorPane; + + // EditorKit must be set in the imlementation class + public AbstractTextViewTopComponent(EditorKit kit) { + editorPane = new JEditorPane(); + editorPane.setEditorKit(kit); + editorPane.setEditable(false); + JScrollPane scrollPane = new JScrollPane(editorPane); + scrollPane.setViewportBorder(BorderFactory.createEmptyBorder()); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + setLayout(new BorderLayout()); + add(scrollPane); + } + + @Override + protected void componentShowing() { + super.componentShowing(); + SelectionManager.getDefault().addChangeListener(selectionChangeListener); + updateContent(); + } + + @Override + protected void componentHidden() { + super.componentHidden(); + SelectionManager.getDefault().removeChangeListener(selectionChangeListener); + curCFG = null; + curBlocks = null; + } + + + private ChangeListener selectionChangeListener = new ChangeListener() { + public void stateChanged(ChangeEvent event) { + updateContent(); + } + }; + + protected void updateContent() { + Selection selection = SelectionManager.getDefault().getCurSelection(); + InputGraph newCFG = selection.get(InputGraph.class); + InputBlock[] newBlocks = selection.get(InputBlock[].class); + + if (newCFG == null || newBlocks == null || newBlocks.length == 0) { + editorPane.setText("No block selected\n"); + } else if (curCFG != newCFG || !Arrays.equals(curBlocks, newBlocks)) { + editorPane.setText(getContent(newCFG, newBlocks)); + } + curCFG = newCFG; + curBlocks = newBlocks; + } + + protected abstract String getContent(InputGraph cfg, InputBlock[] blocks); + +} diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/nbproject/platform.properties --- a/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties Tue Jun 07 11:18:18 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties Tue Jun 07 11:19:01 2011 +0200 @@ -1,13 +1,173 @@ cluster.path=\ + ${nbplatform.active.dir}/ide:\ ${nbplatform.active.dir}/platform disabled.modules=\ + org.apache.xml.resolver,\ + 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.multiview,\ + org.netbeans.lib.cvsclient,\ + org.netbeans.lib.terminalemulator,\ + org.netbeans.libs.antlr3.runtime,\ + org.netbeans.libs.bugtracking,\ + org.netbeans.libs.bugzilla,\ + org.netbeans.libs.bytelist,\ + org.netbeans.libs.commons_codec,\ + org.netbeans.libs.commons_logging,\ + org.netbeans.libs.commons_net,\ + org.netbeans.libs.freemarker,\ + org.netbeans.libs.ini4j,\ + org.netbeans.libs.jakarta_oro,\ + org.netbeans.libs.jaxb,\ + org.netbeans.libs.jsch,\ org.netbeans.libs.jsr223,\ + org.netbeans.libs.jvyamlb,\ + org.netbeans.libs.jzlib,\ + 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.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.diff,\ + 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.errorstripe,\ + org.netbeans.modules.editor.errorstripe.api,\ + 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.plain,\ + org.netbeans.modules.editor.plain.lib,\ + 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.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.mercurial,\ + org.netbeans.modules.hudson.subversion,\ + 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.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.options.editor,\ + 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.projectapi,\ + 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.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,\ + org.netbeans.modules.versioning.util,\ + org.netbeans.modules.web.client.tools.api,\ + org.netbeans.modules.web.common,\ + 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,\ diff -r 463657856f86 -r 7474789a8120 src/share/tools/IdealGraphVisualizer/nbproject/project.properties --- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Tue Jun 07 11:18:18 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Tue Jun 07 11:19:01 2011 +0200 @@ -17,7 +17,9 @@ ${project.com.sun.hotspot.igv.svg}:\ ${project.com.sun.hotspot.connection}:\ ${project.com.sun.hotspot.igv.servercompiler}:\ - ${project.com.sun.hotspot.igv.filterwindow} + ${project.com.sun.hotspot.igv.filterwindow}:\ + ${project.at.ssw.visualizer.texteditor} +project.at.ssw.visualizer.texteditor=Text Editor project.com.sun.hotspot.connection=NetworkConnection project.com.sun.hotspot.igv.bytecodes=Bytecodes project.com.sun.hotspot.igv.controlflow=ControlFlow