# HG changeset patch # User Gilles Duboscq # Date 1310130016 -7200 # Node ID 38792f9594791b72529dd14193a35d1e0a0bdbbb # Parent 536b02e3cd2b8c5b0c2624f2a4c6ee720acab8b8# Parent 3d68684b7161946d4d61a3ea7d31aa087231c5d6 Merge diff -r 536b02e3cd2b -r 38792f959479 .hgignore --- a/.hgignore Fri Jul 08 14:49:01 2011 +0200 +++ b/.hgignore Fri Jul 08 15:00:16 2011 +0200 @@ -20,6 +20,7 @@ ^Test.java$ ^diff1.txt$ ^diff2.txt$ +^examples.jar$ ^test.xml$ java\.hprof\.txt$ /nbproject/private/ diff -r 536b02e3cd2b -r 38792f959479 create_examples.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/create_examples.xml Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java Fri Jul 08 15:00:16 2011 +0200 @@ -30,7 +30,7 @@ import com.oracle.max.graal.compiler.asm.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.gen.LIRGenerator.*; +import com.oracle.max.graal.compiler.gen.LIRGenerator.DeoptimizationStub; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.observer.*; @@ -239,8 +239,8 @@ lirGenerator = compiler.backend.newLIRGenerator(this); - for (LIRBlock begin : hir.linearScanOrder()) { - lirGenerator.doBlock(begin); + for (LIRBlock b : hir.linearScanOrder()) { + lirGenerator.doBlock(b); } if (GraalOptions.Time) { @@ -258,7 +258,7 @@ private CiTargetMethod emitCode() { if (GraalOptions.GenLIR && GraalOptions.GenCode) { final LIRAssembler lirAssembler = compiler.backend.newLIRAssembler(this); - lirAssembler.emitCode(hir.linearScanOrder()); + lirAssembler.emitCode(hir.codeEmittingOrder()); // generate code for slow cases lirAssembler.emitLocalStubs(); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jul 08 15:00:16 2011 +0200 @@ -85,6 +85,8 @@ public static boolean PrintDOTGraphToPdf = ____; public static boolean OmitDOTFrameStates = ____; + public static boolean Extend = ____; + // Ideal graph visualizer output settings public static boolean Plot = ____; public static boolean PlotOnError = ____; @@ -129,6 +131,7 @@ public static boolean UseBranchPrediction = true; public static boolean UseExceptionProbability = ____; public static int MatureInvocationCount = 100; + public static boolean GenSafepoints = true; public static boolean UseConstDirectCall = ____; @@ -153,8 +156,11 @@ public static boolean CommentedAssembly = ____; public static boolean PrintLIRWithAssembly = ____; + public static boolean OptReadElimination = ____; public static boolean OptGVN = ____; public static boolean OptCanonicalizer = true; public static boolean OptLoops = ____; + public static boolean OptOptimisticSchedule = ____; + public static boolean OptReorderLoops = ____; public static boolean LoopPeeling = ____; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Fri Jul 08 15:00:16 2011 +0200 @@ -42,7 +42,7 @@ */ public static void optimize(IR ir) { ControlFlowOptimizer optimizer = new ControlFlowOptimizer(ir); - List code = ir.linearScanOrder(); + List code = ir.codeEmittingOrder(); optimizer.reorderShortLoops(code); optimizer.deleteEmptyBlocks(code); optimizer.deleteUnnecessaryJumps(code); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Jul 08 15:00:16 2011 +0200 @@ -26,20 +26,23 @@ import static java.lang.reflect.Modifier.*; import java.util.*; +import java.util.Map.Entry; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.alloc.Interval.*; +import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding; +import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority; +import com.oracle.max.graal.compiler.alloc.Interval.SpillState; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.*; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; import com.oracle.max.graal.compiler.observer.*; -import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; -import com.oracle.max.graal.compiler.value.FrameState.*; +import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure; +import com.oracle.max.graal.extensions.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -634,6 +637,7 @@ // Add uses of live locals from interpreter's point of view for proper debug information generation LIRDebugInfo info = op.info; if (info != null) { + assert info.state != null; info.state.forEachLiveStateValue(new ValueProcedure() { public void doValue(Value value) { CiValue operand = value.operand(); @@ -1837,117 +1841,183 @@ } } - CiValue toCiValue(int opId, Value value) { - if (value instanceof VirtualObject) { - return toCiVirtualObject(opId, (VirtualObject) value); - } else if (value != null && value.operand() != CiValue.IllegalValue) { - CiValue operand = value.operand(); - Constant con = null; - if (value instanceof Constant) { - con = (Constant) value; - } - - assert con == null || operand.isVariable() || operand.isConstant() || operand.isIllegal() : "Constant instructions have only constant operands (or illegal if constant is optimized away)"; + public static ThreadLocal> frameModifierLoader = new ThreadLocal>(); - if (operand.isVariable()) { - OperandMode mode = OperandMode.Input; - LIRBlock block = blockForId(opId); - if (block.numberOfSux() == 1 && opId == block.lastLirInstructionId()) { - // generating debug information for the last instruction of a block. - // if this instruction is a branch, spill moves are inserted before this branch - // and so the wrong operand would be returned (spill moves at block boundaries are not - // considered in the live ranges of intervals) - // Solution: use the first opId of the branch target block instead. - final LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1); - if (instr instanceof LIRBranch) { - if (block.liveOut.get(operandNumber(operand))) { - opId = block.suxAt(0).firstLirInstructionId(); - mode = OperandMode.Output; - } - } - } + private CiFrame overrideFrame(CiFrame frame) { + ServiceLoader serviceLoader = frameModifierLoader.get(); + if (serviceLoader == null) { + serviceLoader = ServiceLoader.load(FrameModifier.class); + frameModifierLoader.set(serviceLoader); + } - // Get current location of operand - // The operand must be live because debug information is considered when building the intervals - // if the interval is not live, colorLirOperand will cause an assert on failure - operand = colorLirOperand((CiVariable) operand, opId, mode); - assert !hasCall(opId) || operand.isStackSlot() || !isCallerSave(operand) : "cannot have caller-save register operands at calls"; - return operand; - } else if (operand.isRegister()) { - assert false : "must not reach here"; - return operand; - } else { - assert value instanceof Constant; - assert operand.isConstant() : "operand must be constant"; - return operand; - } - } else { - // return a dummy value because real value not needed - return CiValue.IllegalValue; + CiFrame result = frame; + for (FrameModifier modifier : serviceLoader) { + result = modifier.getFrame(compilation.runtime, result); } + return result; } - private CiVirtualObject toCiVirtualObject(int opId, VirtualObject obj) { - RiType type = obj.type(); - EscapeField[] escapeFields = obj.fields(); - CiValue[] values = new CiValue[escapeFields.length]; - int valuesFilled = 0; + + private class DebugFrameBuilder { + + private final FrameState topState; + private final int opId; + private final BitMap frameRefMap; + + private HashMap virtualObjects; + + public DebugFrameBuilder(FrameState topState, int opId, BitMap frameRefMap) { + this.topState = topState; + this.opId = opId; + this.frameRefMap = frameRefMap; + } + + private CiValue toCiValue(Value value) { + if (value instanceof VirtualObject) { + if (virtualObjects == null) { + virtualObjects = new HashMap(); + } + VirtualObject obj = (VirtualObject) value; + CiVirtualObject ciObj = virtualObjects.get(value); + if (ciObj == null) { + ciObj = CiVirtualObject.get(obj.type(), null, value.id()); + virtualObjects.put(obj, ciObj); + } + return ciObj; + } else if (value != null && value.operand() != CiValue.IllegalValue) { + CiValue operand = value.operand(); + Constant con = null; + if (value instanceof Constant) { + con = (Constant) value; + } + + assert con == null || operand.isVariable() || operand.isConstant() || operand.isIllegal() : "Constant instructions have only constant operands (or illegal if constant is optimized away)"; - VirtualObject current = obj; - do { - boolean found = false; - for (int i = 0; i < escapeFields.length; i++) { - if (escapeFields[i].representation() == current.field().representation()) { - if (values[i] == null) { - values[i] = toCiValue(opId, current.input()); - valuesFilled++; + int tempOpId = this.opId; + if (operand.isVariable()) { + OperandMode mode = OperandMode.Input; + LIRBlock block = blockForId(tempOpId); + if (block.numberOfSux() == 1 && tempOpId == block.lastLirInstructionId()) { + // generating debug information for the last instruction of a block. + // if this instruction is a branch, spill moves are inserted before this branch + // and so the wrong operand would be returned (spill moves at block boundaries are not + // considered in the live ranges of intervals) + // Solution: use the first opId of the branch target block instead. + final LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1); + if (instr instanceof LIRBranch) { + if (block.liveOut.get(operandNumber(operand))) { + tempOpId = block.suxAt(0).firstLirInstructionId(); + mode = OperandMode.Output; + } + } } - found = true; - break; + + // Get current location of operand + // The operand must be live because debug information is considered when building the intervals + // if the interval is not live, colorLirOperand will cause an assert on failure + operand = colorLirOperand((CiVariable) operand, tempOpId, mode); + assert !hasCall(tempOpId) || operand.isStackSlot() || !isCallerSave(operand) : "cannot have caller-save register operands at calls"; + return operand; + } else if (operand.isRegister()) { + assert false : "must not reach here"; + return operand; + } else { + assert value instanceof Constant; + assert operand.isConstant() : "operand must be constant"; + return operand; } + } else { + // return a dummy value because real value not needed + return CiValue.IllegalValue; } - assert found : type + "." + current.field() + " not found"; - current = current.object(); - } while (current != null && valuesFilled < values.length); - - for (int i = 0; i < escapeFields.length; i++) { - assert values[i] != null : type + "." + escapeFields[i]; } - return CiVirtualObject.get(type, values, obj.id()); - } + private CiFrame computeFrameForState(FrameState state) { + CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()]; + int valueIndex = 0; + + for (int i = 0; i < state.valuesSize(); i++) { + values[valueIndex++] = toCiValue(state.valueAt(i)); + } - CiFrame computeFrameForState(FrameState state, int opId, BitMap frameRefMap) { - CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()]; - int valueIndex = 0; - - for (int i = 0; i < state.valuesSize(); i++) { - values[valueIndex++] = toCiValue(opId, state.valueAt(i)); + for (int i = 0; i < state.locksSize(); i++) { + if (compilation.runtime.sizeOfBasicObjectLock() != 0) { + CiStackSlot monitorAddress = frameMap.toMonitorBaseStackAddress(i); + values[valueIndex++] = monitorAddress; + CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i); + frameRefMap.set(objectAddress.index()); + } else { + Value lock = state.lockAt(i); + if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) { + // lock on class for synchronized static method + values[valueIndex++] = lock.asConstant(); + } else { + values[valueIndex++] = toCiValue(lock); + } + } + } + CiFrame caller = null; + if (state.outerFrameState() != null) { + caller = computeFrameForState(state.outerFrameState()); + } + CiFrame frame = new CiFrame(caller, state.method, state.bci, state.rethrowException(), values, state.localsSize(), state.stackSize(), state.locksSize()); + if (GraalOptions.Extend) { + frame = overrideFrame(frame); + } + return frame; } - for (int i = 0; i < state.locksSize(); i++) { - if (compilation.runtime.sizeOfBasicObjectLock() != 0) { - CiStackSlot monitorAddress = frameMap.toMonitorBaseStackAddress(i); - values[valueIndex++] = monitorAddress; - assert frameRefMap != null; - CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i); -// LIRDebugInfo.setBit(frameRefMap, objectAddress.index()); - frameRefMap.set(objectAddress.index()); - } else { - Value lock = state.lockAt(i); - if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) { - // lock on class for synchronized static method - values[valueIndex++] = lock.asConstant(); - } else { - values[valueIndex++] = toCiValue(opId, lock); - } + public CiFrame build() { + CiFrame frame = computeFrameForState(topState); + + if (virtualObjects != null) { + // collect all VirtualObjectField instances: + HashMap objectStates = new HashMap(); + FrameState current = topState; + do { + for (Node n : current.virtualObjectMappings()) { + VirtualObjectField field = (VirtualObjectField) n; + // null states occur for objects with 0 fields + if (field != null && !objectStates.containsKey(field.object())) { + objectStates.put(field.object(), field); + } + } + current = current.outerFrameState(); + } while (current != null); + // fill in the CiVirtualObject values: + // during this process new CiVirtualObjects might be discovered, so repeat until no more changes occur. + boolean changed; + do { + changed = false; + HashMap virtualObjectsCopy = new HashMap(virtualObjects); + for (Entry entry : virtualObjectsCopy.entrySet()) { + if (entry.getValue().values() == null) { + VirtualObject vobj = entry.getKey(); + CiValue[] values = new CiValue[vobj.fields().length]; + entry.getValue().setValues(values); + if (vobj.fields().length > 0) { + changed = true; + FloatingNode currentField = objectStates.get(vobj); + assert currentField != null; + do { + if (currentField instanceof VirtualObjectField) { + int index = ((VirtualObjectField) currentField).index(); + if (values[index] == null) { + values[index] = toCiValue(((VirtualObjectField) currentField).input()); + } + currentField = ((VirtualObjectField) currentField).lastState(); + } else { + assert currentField instanceof Phi : currentField; + currentField = (FloatingNode) ((Phi) currentField).valueAt(0); + } + } while (currentField != null); + } + } + } + } while (changed); } + return frame; } - CiFrame caller = null; - if (state.outerFrameState() != null) { - caller = computeFrameForState(state.outerFrameState(), opId, frameRefMap); - } - return new CiFrame(caller, state.method, state.bci, state.rethrowException(), values, state.localsSize(), state.stackSize(), state.locksSize()); } private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) { @@ -1983,7 +2053,7 @@ if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("creating debug information at opId %d", opId); } - return computeFrameForState(state, opId, frameRefMap); + return new DebugFrameBuilder(state, opId, frameRefMap).build(); } private void assignLocations(List instructions, IntervalWalker iw) { diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java Fri Jul 08 15:00:16 2011 +0200 @@ -109,7 +109,7 @@ return; } - printer = new IdealGraphPrinter(stream); + printer = new IdealGraphPrinter(new BufferedOutputStream(stream)); if (GraalOptions.OmitDOTFrameStates) { printer.addOmittedClass(FrameState.class); } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Jul 08 15:00:16 2011 +0200 @@ -39,9 +39,11 @@ import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; +import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.Bytecodes.MemoryBarriers; import com.sun.cri.ci.*; @@ -239,11 +241,35 @@ TTY.println("BEGIN Generating LIR for block B" + block.blockID()); } - if (block.blockPredecessors().size() > 1) { + if (block == ir.startBlock) { + XirSnippet prologue = xir.genPrologue(null, compilation.method); + if (prologue != null) { + emitXir(prologue, null, null, null, false); + } + FrameState fs = setOperandsForLocals(); + if (GraalOptions.TraceLIRGeneratorLevel >= 2) { + TTY.println("STATE CHANGE (setOperandsForLocals)"); + if (GraalOptions.TraceLIRGeneratorLevel >= 3) { + TTY.println(fs.toString()); + } + } + lastState = fs; + } else if (block.blockPredecessors().size() > 1) { if (GraalOptions.TraceLIRGeneratorLevel >= 2) { TTY.println("STATE RESET"); } lastState = null; + } else if (block.blockPredecessors().size() == 1) { + LIRBlock pred = block.blockPredecessors().get(0); + FrameState fs = pred.lastState(); + assert fs != null : "block B" + block.blockID() + " pred block B" + pred.blockID(); + if (GraalOptions.TraceLIRGeneratorLevel >= 2) { + TTY.println("STATE CHANGE (singlePred)"); + if (GraalOptions.TraceLIRGeneratorLevel >= 3) { + TTY.println(fs.toString()); + } + } + lastState = fs; } for (Node instr : block.getInstructions()) { @@ -442,13 +468,13 @@ public void visitExceptionObject(ExceptionObject x) { XirSnippet snippet = xir.genExceptionObject(site(x)); emitXir(snippet, x, null, null, true); - lastState = lastState.duplicateWithException(lastState.bci, x); - if (GraalOptions.TraceLIRGeneratorLevel >= 2) { - TTY.println("STATE CHANGE (visitExceptionObject)"); - if (GraalOptions.TraceLIRGeneratorLevel >= 3) { - TTY.println(lastState.toString()); - } - } +// lastState = lastState.duplicateWithException(lastState.bci, x); +// if (GraalOptions.TraceLIRGeneratorLevel >= 2) { +// TTY.println("STATE CHANGE (visitExceptionObject)"); +// if (GraalOptions.TraceLIRGeneratorLevel >= 3) { +// TTY.println(lastState.toString()); +// } +// } } @Override @@ -478,12 +504,14 @@ } public void emitBooleanBranch(Node node, LIRBlock trueSuccessor, LIRBlock falseSuccessor, LIRDebugInfo info) { - if (node instanceof Compare) { + if (node instanceof NegateBooleanNode) { + emitBooleanBranch(((NegateBooleanNode) node).value(), falseSuccessor, trueSuccessor, info); + } else if (node instanceof Compare) { emitCompare((Compare) node, trueSuccessor, falseSuccessor); } else if (node instanceof InstanceOf) { emitInstanceOf((TypeCheck) node, trueSuccessor, falseSuccessor, info); - } else if (node instanceof NotInstanceOf) { - emitInstanceOf((TypeCheck) node, falseSuccessor, trueSuccessor, info); + } else if (node instanceof Constant) { + emitConstantBranch(((Constant) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info); } else { throw Util.unimplemented(node.toString()); } @@ -498,6 +526,21 @@ instr.setFalseSuccessor(falseSuccessor); } + + public void emitConstantBranch(boolean value, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock, LIRDebugInfo info) { + if (value) { + emitConstantBranch(trueSuccessorBlock, info); + } else { + emitConstantBranch(falseSuccessorBlock, info); + } + } + + private void emitConstantBranch(LIRBlock block, LIRDebugInfo info) { + if (block != null) { + lir.jump(block); + } + } + public void emitCompare(Compare compare, LIRBlock trueSuccessorBlock, LIRBlock falseSuccessorBlock) { CiKind kind = compare.x().kind; @@ -580,16 +623,11 @@ } protected FrameState stateBeforeInvokeReturn(Invoke invoke) { - return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind); + return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind); } protected FrameState stateBeforeInvokeWithArguments(Invoke invoke) { - return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0])); - } - - private int getBeforeInvokeBci(Invoke invoke) { - // Cannot calculate BCI, because the invoke can have changed from e.g. invokeinterface to invokespecial because of optimizations. - return invoke.bci; + return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind, invoke.arguments().toArray(new Value[0])); } @Override @@ -745,7 +783,7 @@ for (Node n : fixedGuard.inputs()) { if (n != null) { emitGuardComp((BooleanNode) n); - } + } } } @@ -763,19 +801,33 @@ XirSnippet typeCheck = xir.genTypeCheck(site(x), toXirArgument(x.object()), clazz, x.type()); emitXir(typeCheck, x, info, compilation.method, false); } else { - FrameState state = lastState; - assert state != null : "deoptimize instruction always needs a state"; - - if (deoptimizationStubs == null) { - deoptimizationStubs = new ArrayList(); + if (comp instanceof Constant && comp.asConstant().asBoolean()) { + // Nothing to emit. + } else { + DeoptimizationStub stub = createDeoptStub(); + emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info); } - DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state); - deoptimizationStubs.add(stub); - - emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info); } } + private DeoptimizationStub createDeoptStub() { + if (deoptimizationStubs == null) { + deoptimizationStubs = new ArrayList(); + } + + FrameState state = lastState; + assert state != null : "deoptimize instruction always needs a state"; + DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state); + deoptimizationStubs.add(stub); + return stub; + } + + public void deoptimizeOn(Condition cond) { + DeoptimizationStub stub = createDeoptStub(); + lir.branch(cond, stub.label, stub.info); + } + + @Override public void visitPhi(Phi i) { Util.shouldNotReachHere(); @@ -1062,30 +1114,6 @@ block.setLir(lir); lir.branchDestination(block.label()); - if (block == ir.startBlock) { - XirSnippet prologue = xir.genPrologue(null, compilation.method); - if (prologue != null) { - emitXir(prologue, null, null, null, false); - } - FrameState fs = setOperandsForLocals(); - if (GraalOptions.TraceLIRGeneratorLevel >= 2) { - TTY.println("STATE CHANGE (setOperandsForLocals)"); - if (GraalOptions.TraceLIRGeneratorLevel >= 3) { - TTY.println(fs.toString()); - } - } - lastState = fs; - } else if (block.blockPredecessors().size() == 1) { - FrameState fs = block.blockPredecessors().get(0).lastState(); - //assert fs != null : "B" + block.blockID() + ", pred=B" + block.blockPredecessors().get(0).blockID(); - if (GraalOptions.TraceLIRGeneratorLevel >= 2) { - TTY.println("STATE CHANGE (singlePred)"); - if (GraalOptions.TraceLIRGeneratorLevel >= 3) { - TTY.println(fs.toString()); - } - } - lastState = fs; - } } /** @@ -1097,7 +1125,7 @@ * @return the operand that is guaranteed to be a stack location when it is * initially defined a by move from {@code value} */ - CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) { + public CiValue forceToSpill(CiValue value, CiKind kind, boolean mustStayOnStack) { assert value.isLegal() : "value should not be illegal"; assert kind.jvmSlots == value.kind.jvmSlots : "size mismatch"; if (!value.isVariableOrRegister()) { @@ -1212,7 +1240,7 @@ } } - protected void arithmeticOpInt(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) { + public void arithmeticOpInt(int code, CiValue result, CiValue left, CiValue right, CiValue tmp) { CiValue leftOp = left; if (isTwoOperand && leftOp != result) { @@ -1252,7 +1280,7 @@ } } - protected void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) { + public void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) { CiValue leftOp = left; if (isTwoOperand && leftOp != result) { @@ -1487,6 +1515,9 @@ public void visitLoopEnd(LoopEnd x) { setNoResult(x); moveToPhi(x.loopBegin(), x); + if (GraalOptions.GenSafepoints) { + xir.genSafepoint(site(x)); + } lir.jump(getLIRBlock(x.loopBegin())); } @@ -1497,7 +1528,7 @@ int nextSuccIndex = merge.phiPredecessorIndex(pred); PhiResolver resolver = new PhiResolver(this); for (Phi phi : merge.phis()) { - if (!phi.isDead()) { + if (phi.type() == PhiType.Value) { Value curVal = phi.valueAt(nextSuccIndex); if (curVal != null && curVal != phi) { if (curVal instanceof Phi) { @@ -1559,7 +1590,7 @@ } private CiValue operandForPhi(Phi phi) { - assert !phi.isDead() : "dead phi: " + phi.id(); + assert phi.type() == PhiType.Value : "wrong phi type: " + phi.id(); if (phi.operand().isIllegal()) { // allocate a variable for this phi createResultVariable(phi); @@ -1581,7 +1612,7 @@ x.clearOperand(); } - protected CiValue setResult(Value x, CiVariable operand) { + public CiValue setResult(Value x, CiVariable operand) { x.setOperand(operand); if (GraalOptions.DetailedAsserts) { operands.recordResult(operand, x); @@ -1615,57 +1646,25 @@ } } - protected void walkState(Node x, FrameState state) { + protected void walkState(final Node x, FrameState state) { if (state == null) { return; } - walkState(x, state.outerFrameState()); - - for (int index = 0; index < state.stackSize(); index++) { - Value value = state.stackAt(index); - if (value != x) { - walkStateValue(value); - } - } - for (int index = 0; index < state.localsSize(); index++) { - final Value value = state.localAt(index); - if (value != null) { - if (!(value instanceof Phi && ((Phi) value).isDead())) { - walkStateValue(value); + state.forEachLiveStateValue(new ValueProcedure() { + public void doValue(Value value) { + if (value == x) { + // nothing to do, will be visited shortly + } else if (value instanceof Phi && ((Phi) value).type() == PhiType.Value) { + // phi's are special + operandForPhi((Phi) value); + } else if (value.operand().isIllegal()) { + // instruction doesn't have an operand yet + CiValue operand = makeOperand(value); + assert operand.isLegal() : "must be evaluated now"; } } - } - } - - private void walkStateValue(Value value) { - if (value != null) { - if (value instanceof VirtualObject) { - walkVirtualObject((VirtualObject) value); - } else if (value instanceof Phi && !((Phi) value).isDead()) { - // phi's are special - operandForPhi((Phi) value); - } else if (value.operand().isIllegal()) { - // instruction doesn't have an operand yet - CiValue operand = makeOperand(value); - assert operand.isLegal() : "must be evaluated now"; - } - } - } - - private void walkVirtualObject(VirtualObject value) { - if (value.input() instanceof Phi) { - assert !((Phi) value.input()).isDead(); - } - HashSet fields = new HashSet(); - VirtualObject obj = value; - do { - if (!fields.contains(obj.field().representation())) { - fields.add(obj.field().representation()); - walkStateValue(obj.input()); - } - obj = obj.object(); - } while (obj != null); + }); } protected LIRDebugInfo stateFor(Value x) { diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java Fri Jul 08 15:00:16 2011 +0200 @@ -62,9 +62,6 @@ } else if (visited.isMarked(phi)) { // break cycles in phis return phi; - } else if (phi.isDead()) { - // don't bother with illegals - return phi; } else { // attempt to simplify the phi by recursively simplifying its operands visited.mark(phi); @@ -74,20 +71,20 @@ for (int i = 0; i < max; i++) { Value oldInstr = phi.valueAt(i); - if (oldInstr == null || (oldInstr instanceof Phi && ((Phi) oldInstr).isDead())) { + if (oldInstr == null) { // if one operand is illegal, make the entire phi illegal - phi.makeDead(); visited.clear(phi); - return phi; + phi.replaceAndDelete(null); + return null; } Value newInstr = simplify(oldInstr); - if (newInstr == null || (newInstr instanceof Phi && ((Phi) newInstr).isDead())) { + if (newInstr == null) { // if the subst instruction is illegal, make the entire phi illegal - phi.makeDead(); visited.clear(phi); - return phi; + phi.replaceAndDelete(null); + return null; } // attempt to simplify this operand diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java Fri Jul 08 15:00:16 2011 +0200 @@ -126,7 +126,7 @@ final HashSet successors = new LinkedHashSet(); private boolean visited; private boolean active; - private int loops; + private long loops; } public static class ExceptionBlock extends Block { @@ -485,7 +485,7 @@ } private void computeBlockOrder() { - int loop = computeBlockOrder(blockMap[0]); + long loop = computeBlockOrder(blockMap[0]); if (loop != 0) { // There is a path from a loop end to the method entry that does not pass the loop header. @@ -501,7 +501,7 @@ /** * The next available loop number. */ - private int nextLoop = 0; + private int nextLoop; /** * Mark the block as a loop header, using the next available loop number. @@ -516,17 +516,17 @@ // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. throw new CiBailout("Loop formed by an exception handler"); } - if (nextLoop >= Integer.SIZE) { + if (nextLoop >= Long.SIZE) { // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. throw new CiBailout("Too many loops in method"); } assert block.loops == 0; - block.loops = 1 << nextLoop; + block.loops = (long) 1 << (long) nextLoop; nextLoop++; } - assert Integer.bitCount(block.loops) == 1; + assert Long.bitCount(block.loops) == 1; } /** @@ -534,7 +534,7 @@ * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward * edges). */ - private int computeBlockOrder(Block block) { + private long computeBlockOrder(Block block) { if (block.visited) { if (block.active) { // Reached block via backward branch. @@ -557,7 +557,7 @@ processLoopBlock(block); } if (block.isLoopHeader) { - assert Integer.bitCount(block.loops) == 1; + assert Long.bitCount(block.loops) == 1; loops &= ~block.loops; } @@ -694,6 +694,6 @@ } out.println(); - out.print("loop_depth ").println(Integer.bitCount(block.loops)); + out.print("loop_depth ").println(Long.bitCount(block.loops)); } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Fri Jul 08 15:00:16 2011 +0200 @@ -31,6 +31,7 @@ import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.value.*; +import com.oracle.max.graal.extensions.*; import com.oracle.max.graal.graph.*; /** @@ -52,7 +53,12 @@ /** * The linear-scan ordered list of blocks. */ - private List orderedBlocks; + private List linearScanOrder; + + /** + * The order in which the code is emitted. + */ + private List codeEmittingOrder; /** * Creates a new IR instance for the specified compilation. @@ -76,18 +82,15 @@ // replacements.put(duplicate.start(), compilation.graph.start()); // compilation.graph.addDuplicate(duplicate.getNodes(), replacements); // } else { - new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph); + new GraphBuilderPhase(compilation, compilation.method, false).apply(compilation.graph); // } - //printGraph("After GraphBuilding", compilation.graph); if (GraalOptions.TestGraphDuplication) { new DuplicationPhase().apply(compilation.graph); - //printGraph("After Duplication", compilation.graph); } new DeadCodeEliminationPhase().apply(compilation.graph); - //printGraph("After DeadCodeElimination", compilation.graph); if (GraalOptions.Inline) { new InliningPhase(compilation, this, null).apply(compilation.graph); @@ -100,6 +103,10 @@ new DeadCodeEliminationPhase().apply(graph); } + if (GraalOptions.Extend) { + extensionOptimizations(graph); + } + if (GraalOptions.OptLoops) { new LoopPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { @@ -108,9 +115,8 @@ } } - if (GraalOptions.EscapeAnalysis /*&& compilation.method.toString().contains("simplify")*/) { + if (GraalOptions.EscapeAnalysis) { new EscapeAnalysisPhase(compilation, this).apply(graph); - // new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); } @@ -119,17 +125,20 @@ new GlobalValueNumberingPhase().apply(graph); } + new LoweringPhase(compilation.runtime).apply(graph); if (GraalOptions.Lower) { - new LoweringPhase(compilation.runtime).apply(graph); new MemoryPhase().apply(graph); if (GraalOptions.OptGVN) { new GlobalValueNumberingPhase().apply(graph); } - new ReadEliminationPhase().apply(graph); + if (GraalOptions.OptReadElimination) { + new ReadEliminationPhase().apply(graph); + } } IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true); schedule.apply(graph); + compilation.stats.loopCount = schedule.loopCount(); List blocks = schedule.getBlocks(); @@ -140,6 +149,16 @@ map.put(b, block); block.setInstructions(b.getInstructions()); block.setLinearScanNumber(b.blockID()); + block.setLoopDepth(b.loopDepth()); + block.setLoopIndex(b.loopIndex()); + + if (b.isLoopEnd()) { + block.setLinearScanLoopEnd(); + } + + if (b.isLoopHeader()) { + block.setLinearScanLoopHeader(); + } block.setFirstInstruction(b.firstNode()); block.setLastInstruction(b.lastNode()); @@ -156,9 +175,8 @@ } } - orderedBlocks = lirBlocks; valueToBlock = new HashMap(); - for (LIRBlock b : orderedBlocks) { + for (LIRBlock b : lirBlocks) { for (Node i : b.getInstructions()) { valueToBlock.put(i, b); } @@ -172,12 +190,12 @@ GraalTimers.COMPUTE_LINEAR_SCAN_ORDER.start(); } - ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), startBlock); - orderedBlocks = clso.linearScanOrder(); - this.compilation.stats.loopCount = clso.numLoops(); + ComputeLinearScanOrder clso = new ComputeLinearScanOrder(lirBlocks.size(), compilation.stats.loopCount, startBlock); + linearScanOrder = clso.linearScanOrder(); + codeEmittingOrder = clso.codeEmittingOrder(); int z = 0; - for (LIRBlock b : orderedBlocks) { + for (LIRBlock b : linearScanOrder) { b.setLinearScanNumber(z++); } @@ -189,12 +207,33 @@ } + + + public static ThreadLocal> optimizerLoader = new ThreadLocal>(); + + private void extensionOptimizations(Graph graph) { + + ServiceLoader serviceLoader = optimizerLoader.get(); + if (serviceLoader == null) { + serviceLoader = ServiceLoader.load(Optimizer.class); + optimizerLoader.set(serviceLoader); + } + + for (Optimizer o : serviceLoader) { + o.optimize(compilation.runtime, graph); + } + } + /** * Gets the linear scan ordering of blocks as a list. * @return the blocks in linear scan order */ public List linearScanOrder() { - return orderedBlocks; + return linearScanOrder; + } + + public List codeEmittingOrder() { + return codeEmittingOrder; } public void printGraph(String phase, Graph graph) { diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -49,6 +49,6 @@ } public List mergedNodes() { - return inputs().variablePart(); + return variableInputs(); } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -28,7 +28,7 @@ import com.sun.cri.ci.*; -public abstract class AbstractVectorNode extends FixedNodeWithNext { +public abstract class AbstractVectorNode extends StateSplit { private static final int INPUT_COUNT = 1; private static final int INPUT_VECTOR = 0; diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.ir; +import java.util.*; + import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -72,6 +74,14 @@ setObject(object); } + public void addDependency(Node x) { + variableInputs().add(x); + } + + public List dependencies() { + return variableInputs(); + } + @Override public void print(LogStream out) { out.print("mem read from ").print(object()); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java Fri Jul 08 15:00:16 2011 +0200 @@ -44,6 +44,10 @@ super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); } + public void addGuard(GuardNode x) { + variableInputs().add(x); + } + @Override public void accept(ValueVisitor v) { v.visitAnchor(this); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Fri Jul 08 15:00:16 2011 +0200 @@ -95,8 +95,7 @@ @Override public Node copy(Graph into) { - ArrayLength x = new ArrayLength(null, into); - return x; + return new ArrayLength(null, into); } @SuppressWarnings("unchecked") diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -31,9 +31,4 @@ public BooleanNode(CiKind kind, int inputCount, int successorCount, Graph graph) { super(kind, inputCount, successorCount, graph); } - - - public BooleanNode negate() { - throw new IllegalStateException(); - } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class CastNode extends FloatingNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_NODE = 0; + + private static final int SUCCESSOR_COUNT = 0; + + /** + * The instruction that produces the object tested against null. + */ + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_NODE); + } + + public void setValue(Value n) { + inputs().set(super.inputCount() + INPUT_NODE, n); + } + + public CastNode(CiKind kind, Value n, Graph graph) { + super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setValue(n); + } + + @Override + public void accept(ValueVisitor v) { + } + + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + CastNode conv = (CastNode) n; + conv.setOperand(generator.load(conv.value())); + } + }; + } + return super.lookup(clazz); + } + + @Override + public void print(LogStream out) { + out.print("cast node ").print(value().toString()); + } + + @Override + public Node copy(Graph into) { + return new CastNode(kind, null, into); + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java Fri Jul 08 15:00:16 2011 +0200 @@ -23,6 +23,7 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; @@ -42,7 +43,7 @@ * @param object the instruction producing the object * @param graph */ - public CheckCast(Constant targetClassInstruction, Value object, Graph graph) { + public CheckCast(Value targetClassInstruction, Value object, Graph graph) { super(targetClassInstruction, object, CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph); } @@ -91,7 +92,29 @@ @Override public Node copy(Graph into) { - CheckCast x = new CheckCast(null, null, into); - return x; + return new CheckCast(null, null, into); } + + private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + @Override + public Node canonical(Node node) { + CheckCast checkCast = (CheckCast) node; + Value object = checkCast.object(); + RiType exactType = object.exactType(); + if (exactType != null) { + return Constant.forBoolean(exactType.isSubtypeOf(checkCast.targetClass()), node.graph()); + } + CiConstant constant = object.asConstant(); + if (constant != null) { + assert constant.kind == CiKind.Object; + if (constant.isNull()) { + return Constant.forBoolean(true, node.graph()); + } else { + // this should never happen - non-null constants are always expected to provide an exactType + assert false; + } + } + return checkCast; + } + }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Fri Jul 08 15:00:16 2011 +0200 @@ -95,6 +95,15 @@ setY(y); } + @Override + public boolean valueEqual(Node i) { + if (i instanceof Compare) { + Compare compare = (Compare) i; + return compare.condition == condition && compare.unorderedIsTrue == unorderedIsTrue; + } + return super.valueEqual(i); + } + /** * Gets the condition (comparison operation) for this instruction. * @return the condition @@ -157,11 +166,6 @@ return x; } - @Override - public BooleanNode negate() { - return new Compare(x(), condition.negate(), y(), graph()); - } - private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override public Node canonical(Node node) { @@ -195,9 +199,9 @@ if (compare.condition == Condition.NE) { isFalseCheck = !isFalseCheck; } - BooleanNode result = materializeNode.value(); + Value result = materializeNode.value(); if (isFalseCheck) { - result = result.negate(); + result = new NegateBooleanNode(result, compare.graph()); } if (GraalOptions.TraceCanonicalizer) { TTY.println("Removed materialize replacing with " + result); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java Fri Jul 08 15:00:16 2011 +0200 @@ -28,26 +28,22 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; -import com.sun.cri.ci.*; public final class ComputeLinearScanOrder { private final int maxBlockId; // the highest blockId of a block private int numBlocks; // total number of blocks (smaller than maxBlockId) - private int numLoops; // total number of loops - private boolean iterativeDominators; // method requires iterative computation of dominators List linearScanOrder; // the resulting list of blocks in correct order + List codeEmittingOrder; final BitMap visitedBlocks; // used for recursive processing of blocks final BitMap activeBlocks; // used for recursive processing of blocks final BitMap dominatorBlocks; // temporary BitMap used for computation of dominator final int[] forwardBranches; // number of incoming forward branches for each block - final List loopEndBlocks; // list of all loop end blocks collected during countEdges - BitMap2D loopMap; // two-dimensional bit set: a bit is set if a block is contained in a loop final List workList; // temporary list (used in markLoops and computeOrder) + final LIRBlock[] loopHeaders; // accessors for visitedBlocks and activeBlocks void initVisited() { @@ -87,56 +83,24 @@ return --forwardBranches[b.blockID()]; } - // accessors for loopMap - boolean isBlockInLoop(int loopIdx, LIRBlock b) { - return loopMap.at(loopIdx, b.blockID()); - } - - void setBlockInLoop(int loopIdx, LIRBlock b) { - loopMap.setBit(loopIdx, b.blockID()); - } - - void clearBlockInLoop(int loopIdx, int blockId) { - loopMap.clearBit(loopIdx, blockId); - } - // accessors for final result public List linearScanOrder() { return linearScanOrder; } - public int numLoops() { - return numLoops; - } - - public ComputeLinearScanOrder(int maxBlockId, LIRBlock startBlock) { + public ComputeLinearScanOrder(int maxBlockId, int loopCount, LIRBlock startBlock) { + loopHeaders = new LIRBlock[loopCount]; this.maxBlockId = maxBlockId; visitedBlocks = new BitMap(maxBlockId); activeBlocks = new BitMap(maxBlockId); dominatorBlocks = new BitMap(maxBlockId); forwardBranches = new int[maxBlockId]; - loopEndBlocks = new ArrayList(8); workList = new ArrayList(8); - splitCriticalEdges(); - countEdges(startBlock, null); - - if (numLoops > 0) { - markLoops(); - clearNonNaturalLoops(startBlock); - assignLoopDepth(startBlock); - } - computeOrder(startBlock); - printBlocks(); - assert verify(); - } - - void splitCriticalEdges() { - // TODO: move critical edge splitting from IR to here } /** @@ -153,16 +117,6 @@ } if (isActive(cur)) { - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("backward branch"); - } - assert isVisited(cur) : "block must be visited when block is active"; - assert parent != null : "must have parent"; - - cur.setLinearScanLoopHeader(); - parent.setLinearScanLoopEnd(); - - loopEndBlocks.add(parent); return; } @@ -188,137 +142,11 @@ clearActive(cur); - // Each loop has a unique number. - // When multiple loops are nested, assignLoopDepth assumes that the - // innermost loop has the lowest number. This is guaranteed by setting - // the loop number after the recursive calls for the successors above - // have returned. - if (cur.isLinearScanLoopHeader()) { - assert cur.loopIndex() == -1 : "cannot set loop-index twice"; - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("Block B%d is loop header of loop %d", cur.blockID(), numLoops); - } - - cur.setLoopIndex(numLoops); - numLoops++; - } - if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("Finished counting edges for block B%d", cur.blockID()); } } - void markLoops() { - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("----- marking loops"); - } - - loopMap = new BitMap2D(numLoops, maxBlockId); - - for (int i = loopEndBlocks.size() - 1; i >= 0; i--) { - LIRBlock loopEnd = loopEndBlocks.get(i); - LIRBlock loopStart = loopEnd.suxAt(0); - int loopIdx = loopStart.loopIndex(); - - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("Processing loop from B%d to B%d (loop %d):", loopStart.blockID(), loopEnd.blockID(), loopIdx); - } - assert loopEnd.isLinearScanLoopEnd() : "loop end flag must be set"; -// assert loopEnd.numberOfSux() == 1 : "incorrect number of successors"; - assert loopStart.isLinearScanLoopHeader() : "loop header flag must be set"; - assert loopIdx >= 0 && loopIdx < numLoops : "loop index not set"; - assert workList.isEmpty() : "work list must be empty before processing"; - - // add the end-block of the loop to the working list - workList.add(loopEnd); - setBlockInLoop(loopIdx, loopEnd); - do { - LIRBlock cur = workList.remove(workList.size() - 1); - - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println(" processing B%d", cur.blockID()); - } - assert isBlockInLoop(loopIdx, cur) : "bit in loop map must be set when block is in work list"; - - // recursive processing of all predecessors ends when start block of loop is reached - if (cur != loopStart) { - for (int j = cur.numberOfPreds() - 1; j >= 0; j--) { - LIRBlock pred = cur.predAt(j); - - if (!isBlockInLoop(loopIdx, pred)) { - // this predecessor has not been processed yet, so add it to work list - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println(" pushing B%d", pred.blockID()); - } - workList.add(pred); - setBlockInLoop(loopIdx, pred); - } - } - } - } while (!workList.isEmpty()); - } - } - - // check for non-natural loops (loops where the loop header does not dominate - // all other loop blocks = loops with multiple entries). - // such loops are ignored - void clearNonNaturalLoops(LIRBlock startBlock) { - for (int i = numLoops - 1; i >= 0; i--) { - if (isBlockInLoop(i, startBlock)) { - // loop i contains the entry block of the method. - // this is not a natural loop, so ignore it - if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("Loop %d is non-natural, so it is ignored", i); - } - - for (int blockId = maxBlockId - 1; blockId >= 0; blockId--) { - clearBlockInLoop(i, blockId); - } - iterativeDominators = true; - } - } - } - - void assignLoopDepth(LIRBlock startBlock) { - if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("----- computing loop-depth and weight"); - } - initVisited(); - - assert workList.isEmpty() : "work list must be empty before processing"; - workList.add(startBlock); - - do { - LIRBlock cur = workList.remove(workList.size() - 1); - - if (!isVisited(cur)) { - setVisited(cur); - if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("Computing loop depth for block B%d", cur.blockID()); - } - - // compute loop-depth and loop-index for the block - assert cur.loopDepth() == 0 : "cannot set loop-depth twice"; - int i; - int loopDepth = 0; - int minLoopIdx = -1; - for (i = numLoops - 1; i >= 0; i--) { - if (isBlockInLoop(i, cur)) { - loopDepth++; - minLoopIdx = i; - } - } - cur.setLoopDepth(loopDepth); - cur.setLoopIndex(minLoopIdx); - - // append all unvisited successors to work list - for (i = cur.numberOfSux() - 1; i >= 0; i--) { - workList.add(cur.suxAt(i)); - } - } - } while (!workList.isEmpty()); - } - int computeWeight(LIRBlock cur) { // limit loop-depth to 15 bit (only for security reason, it will never be so big) @@ -329,10 +157,10 @@ // this is necessary for the (very rare) case that two successive blocks have // the same loop depth, but a different loop index (can happen for endless loops // with exception handlers) - if (!cur.isLinearScanLoopHeader()) { - weight |= 1 << curBit; - } - curBit--; +// if (!cur.isLinearScanLoopHeader()) { +// weight |= 1 << curBit; +// } +// curBit--; // loop end blocks (blocks that end with a backward branch) are added // after all other blocks of the loop. @@ -360,10 +188,10 @@ // curBit--; // exceptions handlers are added as late as possible -// if (!cur.isExceptionEntry()) { -// weight |= 1 << curBit; -// } -// curBit--; + if (!cur.isExceptionEntry()) { + weight |= 1 << curBit; + } + curBit--; // guarantee that weight is > 0 weight |= 1; @@ -374,7 +202,7 @@ return weight; } - boolean readyForProcessing(LIRBlock cur) { + private boolean readyForProcessing(LIRBlock cur) { // Discount the edge just traveled. // When the number drops to zero, all forward branches were processed if (decForwardBranches(cur) != 0) { @@ -386,7 +214,7 @@ return true; } - void sortIntoWorkList(LIRBlock cur) { + private void sortIntoWorkList(LIRBlock cur) { assert !workList.contains(cur) : "block already in work list"; int curWeight = computeWeight(cur); @@ -421,7 +249,7 @@ } } - void appendBlock(LIRBlock cur) { + private void appendBlock(LIRBlock cur) { if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber()); } @@ -432,31 +260,44 @@ // be equal. cur.setLinearScanNumber(linearScanOrder.size()); linearScanOrder.add(cur); + + if (!cur.isLinearScanLoopHeader() || !GraalOptions.OptReorderLoops) { + codeEmittingOrder.add(cur); + + if (cur.isLinearScanLoopEnd() && GraalOptions.OptReorderLoops) { + LIRBlock loopHeader = loopHeaders[cur.loopIndex()]; + assert loopHeader != null; + codeEmittingOrder.add(loopHeader); + + for (LIRBlock succ : loopHeader.blockSuccessors()) { + if (succ.loopDepth() == loopHeader.loopDepth()) { + succ.setAlign(true); + } + } + } + } else { + loopHeaders[cur.loopIndex()] = cur; + } } - void computeOrder(LIRBlock startBlock) { + private void computeOrder(LIRBlock startBlock) { if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("----- computing final block order"); } // the start block is always the first block in the linear scan order linearScanOrder = new ArrayList(numBlocks); -// appendBlock(startBlock); - LIRBlock stdEntry = startBlock; //.suxAt(0); + codeEmittingOrder = new ArrayList(numBlocks); // start processing with standard entry block assert workList.isEmpty() : "list must be empty before processing"; - if (readyForProcessing(stdEntry)) { - sortIntoWorkList(stdEntry); - } else { - throw new CiBailout("the stdEntry must be ready for processing (otherwise, the method has no start block)"); - } + assert readyForProcessing(startBlock); + sortIntoWorkList(startBlock); do { LIRBlock cur = workList.remove(workList.size() - 1); - appendBlock(cur); int i; @@ -476,9 +317,6 @@ TTY.println("----- loop information:"); for (LIRBlock cur : linearScanOrder) { TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID())); - for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) { - TTY.print(String.format("%d = %b ", loopIdx, isBlockInLoop(loopIdx, cur))); - } TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth())); } } @@ -513,75 +351,7 @@ } } - boolean verify() { - /* assert linearScanOrder.size() == numBlocks : "wrong number of blocks in list"; - - if (GraalOptions.StressLinearScan) { - // blocks are scrambled when StressLinearScan is used - return true; - } - - // check that all successors of a block have a higher linear-scan-number - // and that all predecessors of a block have a lower linear-scan-number - // (only backward branches of loops are ignored) - int i; - for (i = 0; i < linearScanOrder.size(); i++) { - BlockBegin cur = linearScanOrder.get(i); - - assert cur.linearScanNumber() == i : "incorrect linearScanNumber"; - assert cur.linearScanNumber() >= 0 && cur.linearScanNumber() == linearScanOrder.indexOf(cur) : "incorrect linearScanNumber"; - - for (BlockBegin sux : cur.end().successors()) { - assert sux.linearScanNumber() >= 0 && sux.linearScanNumber() == linearScanOrder.indexOf(sux) : "incorrect linearScanNumber"; - if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) { - assert cur.linearScanNumber() < sux.linearScanNumber() : "invalid order"; - } - if (cur.loopDepth() == sux.loopDepth()) { - assert cur.loopIndex() == sux.loopIndex() || sux.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index"; - } - } - - for (BlockBegin pred : cur.predecessors()) { - assert pred.linearScanNumber() >= 0 && pred.linearScanNumber() == linearScanOrder.indexOf(pred) : "incorrect linearScanNumber"; - if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) { - assert cur.linearScanNumber() > pred.linearScanNumber() : "invalid order"; - } - if (cur.loopDepth() == pred.loopDepth()) { - assert cur.loopIndex() == pred.loopIndex() || cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index"; - } - - assert cur.dominator().linearScanNumber() <= pred.linearScanNumber() : "dominator must be before predecessors"; - } - - // check dominator - if (i == 0) { - assert cur.dominator() == null : "first block has no dominator"; - } else { - assert cur.dominator() != null : "all but first block must have dominator"; - } - assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0) || cur.isExceptionEntry() : "Single predecessor must also be dominator"; - } - - // check that all loops are continuous - for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) { - int blockIdx = 0; - assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "the first block must not be present in any loop"; - - // skip blocks before the loop - while (blockIdx < numBlocks && !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) { - blockIdx++; - } - // skip blocks of loop - while (blockIdx < numBlocks && isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) { - blockIdx++; - } - // after the first non-loop block : there must not be another loop-block - while (blockIdx < numBlocks) { - assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "loop not continuous in linear-scan order"; - blockIdx++; - } - } -*/ - return true; + public List codeEmittingOrder() { + return codeEmittingOrder; } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java Fri Jul 08 15:00:16 2011 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.max.graal.compiler.ir; -import com.sun.cri.bytecode.Bytecodes.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -80,6 +79,16 @@ */ BT("|<|"), + /** + * Operation produced an overflow. + */ + OF("overflow"), + + /** + * Operation did not produce an overflow. + */ + NOF("noOverflow"), + TRUE("TRUE"); public final String operator; diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java Fri Jul 08 15:00:16 2011 +0200 @@ -55,14 +55,6 @@ v.visitConstant(this); } - @Override - public BooleanNode negate() { - if (kind != CiKind.Boolean) { - throw new IllegalStateException(); - } - return Constant.forBoolean(!value.asBoolean(), graph()); - } - /** * Creates an instruction for a double constant. * @param d the double value for which to create the instruction diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -26,6 +26,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; import com.oracle.max.graal.compiler.phases.LoweringPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -98,7 +99,7 @@ EndNode end = new EndNode(graph()); LoopBegin loopBegin = new LoopBegin(graph()); loopBegin.addEnd(end); - Phi loopVariable = new Phi(CiKind.Int, loopBegin, graph()); + Phi loopVariable = new Phi(CiKind.Int, loopBegin, PhiType.Value, graph()); if (reversed) { IntegerSub add = new IntegerSub(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph()); @@ -112,6 +113,7 @@ LoopEnd loopEnd = new LoopEnd(graph()); loopEnd.setLoopBegin(loopBegin); + loopBegin.setStateAfter(stateAfter()); Compare condition; if (reversed) { condition = new Compare(loopVariable, Condition.GE, Constant.forInt(0, graph()), graph()); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -66,7 +66,7 @@ assertTrue(inputs().size() == 0, "inputs empty"); assertTrue(successors().size() == 0, "successors empty"); assertTrue(usages().size() <= 1, "at most one usage"); - assertTrue(predecessors().size() <= 1, "at most one predecessor"); + assertTrue(predecessors().size() <= 1, "at most one predecessor " + predecessors()); return true; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java Fri Jul 08 14:49:01 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.ir; - -import com.oracle.max.graal.compiler.debug.*; -import com.oracle.max.graal.graph.*; -import com.sun.cri.ci.*; -import com.sun.cri.ri.*; - -/** - * This instruction takes an exception object and has two successors: - * The catchSuccessor is called whenever the exception matches the given type, otherwise otherSuccessor is called. - */ -public final class ExceptionDispatch extends ControlSplit { - - private static final int INPUT_COUNT = 1; - private static final int INPUT_EXCEPTION = 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; - } - - /** - * The instruction producing the exception object. - */ - public Value exception() { - return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION); - } - - public Value setException(Value n) { - return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n); - } - - private final RiType catchType; - - /** - * Constructs a new ExceptionDispatch instruction. - */ - public ExceptionDispatch(Value exception, FixedNode catchSuccessor, FixedNode otherSuccessor, RiType catchType, Graph graph) { - super(CiKind.Int, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph); - setException(exception); - setBlockSuccessor(0, otherSuccessor); - setBlockSuccessor(1, catchSuccessor); - this.catchType = catchType; - } - - public RiType catchType() { - return catchType; - } - - /** - * Gets the block corresponding to the catch block. - * @return the true successor - */ - public FixedNode catchSuccessor() { - return blockSuccessor(1); - } - - /** - * Gets the block corresponding to the rest of the dispatch chain. - * @return the false successor - */ - public FixedNode otherSuccessor() { - return blockSuccessor(0); - } - - /** - * Gets the block corresponding to the specified outcome of the branch. - * @param istrue {@code true} if the true successor is requested, {@code false} otherwise - * @return the corresponding successor - */ - public FixedNode successor(boolean istrue) { - return blockSuccessor(istrue ? 1 : 0); - } - - @Override - public void accept(ValueVisitor v) { - v.visitExceptionDispatch(this); - } - - @Override - public void print(LogStream out) { - out.print("exception_dispatch "). - print(exception()). - print(' '). - print("instanceof"). - print(' '). - print(catchType().name()). - print(" then "). - print(catchSuccessor().toString()). - print(" else B"). - print(otherSuccessor().toString()); - } - - @Override - public String shortName() { - return "Dispatch " + catchType().name(); - } - - @Override - public Node copy(Graph into) { - ExceptionDispatch x = new ExceptionDispatch(null, null, null, catchType, into); - return x; - } -} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java Fri Jul 08 15:00:16 2011 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.ir; +import java.util.*; + import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction; @@ -54,7 +56,7 @@ } public void addNode(BooleanNode node) { - inputs().add(node); + variableInputs().add(node); } @Override @@ -75,14 +77,16 @@ @Override public Node canonical(Node node) { FixedGuard fixedGuard = (FixedGuard) node; - for (Node n : fixedGuard.inputs()) { + Iterator iter = fixedGuard.variableInputs().iterator(); + while (iter.hasNext()) { + Node n = iter.next(); if (n instanceof Constant) { Constant c = (Constant) n; if (c.asConstant().asBoolean()) { if (GraalOptions.TraceCanonicalizer) { TTY.println("Removing redundant fixed guard " + fixedGuard); } - fixedGuard.inputs().remove(c); + iter.remove(); } else { if (GraalOptions.TraceCanonicalizer) { TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node"); @@ -92,7 +96,7 @@ } } - if (fixedGuard.inputs().size() == 0) { + if (fixedGuard.variableInputs().size() == 0) { return fixedGuard.next(); } return fixedGuard; diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -55,8 +55,9 @@ inputs().set(super.inputCount() + INPUT_NODE, n); } - public GuardNode(Graph graph) { + public GuardNode(BooleanNode node, Graph graph) { super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setNode(node); } @Override @@ -71,7 +72,12 @@ @Override public Node copy(Graph into) { - return new GuardNode(into); + return new GuardNode(null, into); + } + + @Override + public boolean valueEqual(Node i) { + return i instanceof GuardNode; } @SuppressWarnings("unchecked") diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java Fri Jul 08 15:00:16 2011 +0200 @@ -23,10 +23,12 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; +import com.sun.cri.ri.*; /** * The {@code InstanceOf} instruction represents an instanceof test. @@ -36,13 +38,15 @@ private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; + private boolean nullIsTrue; + /** * Constructs a new InstanceOf instruction. * @param targetClass the target class of the instanceof check * @param object the instruction producing the object input to this instruction * @param graph */ - public InstanceOf(Constant targetClassInstruction, Value object, Graph graph) { + public InstanceOf(Constant targetClassInstruction, Value object, boolean nullIsTrue, Graph graph) { super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); } @@ -66,12 +70,39 @@ } @Override - public BooleanNode negate() { - return new NotInstanceOf(targetClassInstruction(), object(), graph()); + public Node copy(Graph into) { + return new InstanceOf(null, null, nullIsTrue, into); + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); } - @Override - public Node copy(Graph into) { - return new InstanceOf(null, null, into); - } + private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + @Override + public Node canonical(Node node) { + InstanceOf isInstance = (InstanceOf) node; + Value object = isInstance.object(); + RiType exactType = object.exactType(); + if (exactType != null) { + return Constant.forBoolean(exactType.isSubtypeOf(isInstance.targetClass()), node.graph()); + } + CiConstant constant = object.asConstant(); + if (constant != null) { + assert constant.kind == CiKind.Object; + if (constant.isNull()) { + return Constant.forBoolean(false, node.graph()); + } else { + // this should never happen - non-null constants are always expected to provide an exactType + assert false; + } + } + return isInstance; + } + }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Fri Jul 08 15:00:16 2011 +0200 @@ -41,11 +41,21 @@ private static final int SUCCESSOR_COUNT = 1; private static final int SUCCESSOR_EXCEPTION_EDGE = 0; + private boolean canInline = true; + @Override protected int inputCount() { return super.inputCount() + argumentCount; } + public boolean canInline() { + return canInline; + } + + public void setCanInline(boolean b) { + canInline = b; + } + @Override protected int successorCount() { return super.successorCount() + SUCCESSOR_COUNT; @@ -204,6 +214,7 @@ @Override public Node copy(Graph into) { Invoke x = new Invoke(bci, opcode, kind, new Value[argumentCount], target, returnType, into); + x.setCanInline(canInline); return x; } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java Fri Jul 08 15:00:16 2011 +0200 @@ -23,6 +23,7 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -67,7 +68,7 @@ */ public IsNonNull(Value object, Graph graph) { super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph); - assert object == null || object.kind == CiKind.Object; + assert object == null || object.kind == CiKind.Object : object; setObject(object); } @@ -107,4 +108,30 @@ public Node copy(Graph into) { return new IsNonNull(null, into); } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + @Override + public Node canonical(Node node) { + IsNonNull isNonNull = (IsNonNull) node; + Value object = isNonNull.object(); + if (object instanceof NewInstance || object instanceof NewArray) { + return Constant.forBoolean(true, node.graph()); + } + CiConstant constant = object.asConstant(); + if (constant != null) { + assert constant.kind == CiKind.Object; + return Constant.forBoolean(constant.isNonNull(), node.graph()); + } + return isNonNull; + } + }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java Fri Jul 08 15:00:16 2011 +0200 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -127,4 +128,27 @@ public Node copy(Graph into) { return new IsType(null, type, into); } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + @Override + public Node canonical(Node node) { + IsType isType = (IsType) node; + Value object = isType.object(); + RiType exactType = object.exactType(); + if (exactType != null) { + return Constant.forBoolean(exactType == isType.type, node.graph()); + } + // constants return the correct exactType, so they are handled by the code above + return isType; + } + }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java Fri Jul 08 15:00:16 2011 +0200 @@ -23,6 +23,8 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -85,6 +87,16 @@ return false; } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LoweringOp.class) { + return (T) LoweringPhase.DELEGATE_TO_RUNTIME; + } + return super.lookup(clazz); + } + @Override public Node copy(Graph into) { LoadIndexed x = new LoadIndexed(null, null, null, elementKind(), into); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -52,11 +52,11 @@ /** * The instruction which produces the input value to this instruction. */ - public BooleanNode value() { - return (BooleanNode) inputs().get(super.inputCount() + INPUT_VALUE); + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_VALUE); } - public void setValue(BooleanNode n) { + public void setValue(Value n) { inputs().set(super.inputCount() + INPUT_VALUE, n); } @@ -67,7 +67,7 @@ * @param kind the result type of this instruction * @param graph */ - public MaterializeNode(BooleanNode value, Graph graph) { + public MaterializeNode(Value value, Graph graph) { super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph); setValue(value); } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java Fri Jul 08 15:00:16 2011 +0200 @@ -76,20 +76,20 @@ } public int endIndex(EndNode end) { - assert inputs().variablePart().contains(end); - return inputs().variablePart().indexOf(end); + assert variableInputs().contains(end); + return variableInputs().indexOf(end); } public void addEnd(EndNode end) { - inputs().variablePart().add(end); + variableInputs().add(end); } public int endCount() { - return inputs().variablePart().size(); + return variableInputs().size(); } public EndNode endAt(int index) { - return (EndNode) inputs().variablePart().get(index); + return (EndNode) variableInputs().get(index); } @Override @@ -197,7 +197,7 @@ while (!hasPhisOnStack && i < state.stackSize()) { Value value = state.stackAt(i); hasPhisOnStack = isPhiAtBlock(value); - if (value != null && !(value instanceof Phi && ((Phi) value).isDead())) { + if (value != null) { i += value.kind.sizeInSlots(); } else { i++; @@ -208,7 +208,7 @@ Value value = state.localAt(i); hasPhisInLocals = isPhiAtBlock(value); // also ignore illegal HiWords - if (value != null && !(value instanceof Phi && ((Phi) value).isDead())) { + if (value != null) { i += value.kind.sizeInSlots(); } else { i++; @@ -227,11 +227,7 @@ if (value != null) { out.println(stateString(j, value)); // also ignore illegal HiWords - if (value instanceof Phi && ((Phi) value).isDead()) { - j += 1; - } else { - j += value.kind.sizeInSlots(); - } + j += value.kind.sizeInSlots(); } else { j++; } @@ -314,16 +310,13 @@ } public void removeEnd(EndNode pred) { - int predIndex = inputs().variablePart().indexOf(pred); + int predIndex = variableInputs().indexOf(pred); assert predIndex != -1; - inputs().variablePart().remove(predIndex); + variableInputs().remove(predIndex); for (Node usage : usages()) { if (usage instanceof Phi) { - Phi phi = (Phi) usage; - if (!phi.isDead()) { - phi.removeInput(predIndex); - } + ((Phi) usage).removeInput(predIndex); } } } @@ -346,6 +339,6 @@ } public List phiPredecessors() { - return Collections.unmodifiableList(inputs().variablePart()); + return Collections.unmodifiableList(variableInputs()); } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + +/** + * The {@code ArrayLength} instruction gets the length of an array. + */ +public final class NegateBooleanNode extends BooleanNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_NODE = 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; + } + + /** + * The instruction that produces the array object. + */ + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_NODE); + } + + public Value setValue(Value n) { + return (Value) inputs().set(super.inputCount() + INPUT_NODE, n); + } + + /** + * Constructs a new ArrayLength instruction. + * @param array the instruction producing the array + * @param newFrameState the state after executing this instruction + */ + public NegateBooleanNode(Value value, Graph graph) { + super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setValue(value); + } + + @Override + public void accept(ValueVisitor v) { + } + + @Override + public boolean valueEqual(Node i) { + return i instanceof NegateBooleanNode; + } + + @Override + public void print(LogStream out) { + out.print(value()).print("!"); + } + + @Override + public Node copy(Graph into) { + return new NegateBooleanNode(null, into); + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + @Override + public Node canonical(Node node) { + NegateBooleanNode negateNode = (NegateBooleanNode) node; + Value value = negateNode.value(); + if (value instanceof NegateBooleanNode) { + return ((NegateBooleanNode) value).value(); + } else if (value instanceof Constant) { + return Constant.forBoolean(!value.asConstant().asBoolean(), node.graph()); + } + return negateNode; + } + }; +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java Fri Jul 08 15:00:16 2011 +0200 @@ -27,7 +27,6 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField; import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeOp; -import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -36,8 +35,6 @@ */ public abstract class NewArray extends FixedNodeWithNext { - private static final EscapeOp ESCAPE = new NewArrayEscapeOp(); - private static final int INPUT_COUNT = 1; private static final int INPUT_LENGTH = 0; @@ -109,7 +106,7 @@ return super.lookup(clazz); } - private static class NewArrayEscapeOp implements EscapeOp { + private static final EscapeOp ESCAPE = new EscapeOp() { @Override public boolean canAnalyze(Node node) { @@ -120,19 +117,7 @@ @Override public boolean escape(Node node, Node usage) { - if (usage instanceof IsNonNull) { - IsNonNull x = (IsNonNull) usage; - assert x.object() == node; - return false; - } else if (usage instanceof IsType) { - IsType x = (IsType) usage; - assert x.object() == node; - return false; - } else if (usage instanceof FrameState) { - FrameState x = (FrameState) usage; - assert x.inputs().contains(node); - return true; - } else if (usage instanceof LoadIndexed) { + if (usage instanceof LoadIndexed) { LoadIndexed x = (LoadIndexed) usage; assert x.array() == node; CiConstant index = x.index().asConstant(); @@ -152,19 +137,15 @@ if (index == null || length == null || index.asInt() < 0 || index.asInt() >= length.asInt()) { return true; } - return x.value() == node; - } else if (usage instanceof AccessMonitor) { - AccessMonitor x = (AccessMonitor) usage; - assert x.object() == node; - return false; + return x.value() == node && x.array() != node; } else if (usage instanceof ArrayLength) { ArrayLength x = (ArrayLength) usage; assert x.array() == node; return false; - } else if (usage instanceof VirtualObject) { + } else if (usage instanceof VirtualObjectField) { return false; } else { - return true; + return super.escape(node, usage); } } @@ -182,56 +163,33 @@ @Override public void beforeUpdate(Node node, Node usage) { - if (usage instanceof IsNonNull) { - IsNonNull x = (IsNonNull) usage; - if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) { - FixedGuard guard = (FixedGuard) x.usages().get(0); - guard.replaceAndDelete(guard.next()); - } - x.delete(); - } else if (usage instanceof IsType) { - IsType x = (IsType) usage; - assert x.type() == ((NewArray) node).exactType(); - if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) { - FixedGuard guard = (FixedGuard) x.usages().get(0); - guard.replaceAndDelete(guard.next()); - } - x.delete(); - } else if (usage instanceof AccessMonitor) { - AccessMonitor x = (AccessMonitor) usage; - x.replaceAndDelete(x.next()); - } else if (usage instanceof ArrayLength) { + if (usage instanceof ArrayLength) { ArrayLength x = (ArrayLength) usage; x.replaceAndDelete(((NewArray) node).dimension(0)); + } else { + super.beforeUpdate(node, usage); } } @Override - public EscapeField updateState(Node node, Node current, Map fields, Map fieldState) { + public int updateState(Node node, Node current, Map fieldIndex, Value[] fieldState) { if (current instanceof AccessIndexed) { - int index = ((AccessIndexed) current).index().asConstant().asInt(); - EscapeField field = fields.get(index); - if (current instanceof LoadIndexed) { - LoadIndexed x = (LoadIndexed) current; - if (x.array() == node) { - x.replaceAtUsages(fieldState.get(field)); + AccessIndexed x = (AccessIndexed) current; + if (x.array() == node) { + int index = ((AccessIndexed) current).index().asConstant().asInt(); + if (current instanceof LoadIndexed) { + x.replaceAtUsages(fieldState[index]); assert x.usages().size() == 0; x.replaceAndDelete(x.next()); - } - } else if (current instanceof StoreIndexed) { - StoreIndexed x = (StoreIndexed) current; - if (x.array() == node) { - fieldState.put(field, x.value()); + } else if (current instanceof StoreIndexed) { + fieldState[index] = ((StoreIndexed) x).value(); assert x.usages().size() == 0; - WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(x.graph()); - checkpoint.setStateAfter(x.stateAfter()); - checkpoint.setNext(x.next()); - x.replaceAndDelete(checkpoint); - return field; + x.replaceAndDelete(x.next()); + return index; } } } - return null; + return -1; } - } + }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java Fri Jul 08 15:00:16 2011 +0200 @@ -27,7 +27,6 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeField; import com.oracle.max.graal.compiler.phases.EscapeAnalysisPhase.EscapeOp; -import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -36,7 +35,6 @@ * The {@code NewInstance} instruction represents the allocation of an instance class object. */ public final class NewInstance extends FixedNodeWithNext { - private static final EscapeOp ESCAPE = new NewInstanceEscapeOp(); private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; @@ -109,7 +107,7 @@ return super.lookup(clazz); } - private static class NewInstanceEscapeOp implements EscapeOp { + private static final EscapeOp ESCAPE = new EscapeOp() { @Override public boolean canAnalyze(Node node) { @@ -118,41 +116,25 @@ @Override public boolean escape(Node node, Node usage) { - if (usage instanceof IsNonNull) { - IsNonNull x = (IsNonNull) usage; - assert x.object() == node; - return false; - } else if (usage instanceof IsType) { - IsType x = (IsType) usage; - assert x.object() == node; - return false; - } else if (usage instanceof FrameState) { - FrameState x = (FrameState) usage; - assert x.inputs().contains(node); - return true; - } else if (usage instanceof LoadField) { + if (usage instanceof LoadField) { LoadField x = (LoadField) usage; assert x.object() == node; return x.field().isResolved() == false; } else if (usage instanceof StoreField) { StoreField x = (StoreField) usage; - return x.value() == node; + return x.value() == node && x.object() != node; } else if (usage instanceof StoreIndexed) { StoreIndexed x = (StoreIndexed) usage; assert x.value() == node; return true; - } else if (usage instanceof AccessMonitor) { - AccessMonitor x = (AccessMonitor) usage; - assert x.object() == node; - return false; - } else if (usage instanceof VirtualObject) { + } else if (usage instanceof VirtualObjectField) { return false; } else if (usage instanceof RegisterFinalizer) { RegisterFinalizer x = (RegisterFinalizer) usage; assert x.object() == node; return false; } else { - return true; + return super.escape(node, usage); } } @@ -170,56 +152,34 @@ @Override public void beforeUpdate(Node node, Node usage) { - if (usage instanceof IsNonNull) { - IsNonNull x = (IsNonNull) usage; - if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) { - FixedGuard guard = (FixedGuard) x.usages().get(0); - guard.replaceAndDelete(guard.next()); - } - x.delete(); - } else if (usage instanceof IsType) { - IsType x = (IsType) usage; - assert x.type() == ((NewInstance) node).instanceClass(); - if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) { - FixedGuard guard = (FixedGuard) x.usages().get(0); - guard.replaceAndDelete(guard.next()); - } - x.delete(); - } else if (usage instanceof AccessMonitor) { - AccessMonitor x = (AccessMonitor) usage; - x.replaceAndDelete(x.next()); - } else if (usage instanceof RegisterFinalizer) { + if (usage instanceof RegisterFinalizer) { RegisterFinalizer x = (RegisterFinalizer) usage; x.replaceAndDelete(x.next()); + } else { + super.beforeUpdate(node, usage); } } @Override - public EscapeField updateState(Node node, Node current, Map fields, Map fieldState) { + public int updateState(Node node, Node current, Map fieldIndex, Value[] fieldState) { if (current instanceof AccessField) { - EscapeField field = fields.get(((AccessField) current).field()); - if (current instanceof LoadField) { - LoadField x = (LoadField) current; - if (x.object() == node) { - assert fieldState.get(field) != null : field + ", " + ((AccessField) current).field() + ((AccessField) current).field().hashCode(); - x.replaceAtUsages(fieldState.get(field)); + AccessField x = (AccessField) current; + if (x.object() == node) { + int field = fieldIndex.get(((AccessField) current).field()); + if (current instanceof LoadField) { + assert fieldState[field] != null : field + ", " + ((AccessField) current).field(); + x.replaceAtUsages(fieldState[field]); assert x.usages().size() == 0; x.replaceAndDelete(x.next()); - } - } else if (current instanceof StoreField) { - StoreField x = (StoreField) current; - if (x.object() == node) { - fieldState.put(field, x.value()); + } else if (current instanceof StoreField) { + fieldState[field] = ((StoreField) x).value(); assert x.usages().size() == 0; - WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(x.graph()); - checkpoint.setStateAfter(x.stateAfter()); - checkpoint.setNext(x.next()); - x.replaceAndDelete(checkpoint); + x.replaceAndDelete(x.next()); return field; } } } - return null; + return -1; } - } + }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NotInstanceOf.java Fri Jul 08 14:49:01 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.ir; - -import com.oracle.max.graal.compiler.debug.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.graph.*; -import com.sun.cri.bytecode.*; -import com.sun.cri.ci.*; - -/** - * The {@code InstanceOf} instruction represents an instanceof test. - */ -public final class NotInstanceOf extends TypeCheck { - - private static final int INPUT_COUNT = 0; - private static final int SUCCESSOR_COUNT = 0; - - /** - * Constructs a new InstanceOf instruction. - * @param targetClass the target class of the instanceof check - * @param object the instruction producing the object input to this instruction - * @param graph - */ - public NotInstanceOf(Constant targetClassInstruction, Value object, Graph graph) { - super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); - } - - @Override - public void accept(ValueVisitor v) { - } - - @Override - public int valueNumber() { - return Util.hash1(Bytecodes.INSTANCEOF, object()); - } - - @Override - public boolean valueEqual(Node i) { - return i instanceof NotInstanceOf; - } - - @Override - public void print(LogStream out) { - out.print("instanceof(").print(object()).print(") ").print(CiUtil.toJavaName(targetClass())); - } - - @Override - public BooleanNode negate() { - return new InstanceOf(targetClassInstruction(), object(), graph()); - } - - @Override - public Node copy(Graph into) { - return new NotInstanceOf(null, null, into); - } -} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java Fri Jul 08 15:00:16 2011 +0200 @@ -26,6 +26,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.StateSplit.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -42,7 +43,7 @@ private static final int SUCCESSOR_COUNT = 0; - private boolean isDead; + private final PhiType type; @Override protected int inputCount() { @@ -66,21 +67,31 @@ inputs().set(super.inputCount() + INPUT_MERGE, n); } - public Phi(CiKind kind, Merge merge, Graph graph) { + public static enum PhiType { + Value, // normal value phis + Memory, // memory phis + Virtual // phis used for VirtualObjectField merges + } + + public Phi(CiKind kind, Merge merge, PhiType type, Graph graph) { super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.type = type; setMerge(merge); } - Phi(CiKind kind, Graph graph) { + private Phi(CiKind kind, PhiType type, Graph graph) { super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.type = type; + } + + public PhiType type() { + return type; } @Override public boolean verify() { assertTrue(merge() != null); - if (!isDead()) { - assertTrue(merge().phiPredecessorCount() == valueCount()); - } + assertTrue(merge().phiPredecessorCount() == valueCount(), merge().phiPredecessorCount() + "==" + valueCount()); return true; } @@ -91,7 +102,7 @@ * @return the instruction that produced the value in the i'th predecessor */ public Value valueAt(int i) { - return (Value) inputs().variablePart().get(i); + return (Value) variableInputs().get(i); } public void setValueAt(int i, Value x) { @@ -103,7 +114,7 @@ * @return the number of inputs in this phi */ public int valueCount() { - return inputs().variablePart().size(); + return variableInputs().size(); } @Override @@ -111,17 +122,6 @@ v.visitPhi(this); } - /** - * Make this phi illegal if types were not merged correctly. - */ - public void makeDead() { - isDead = true; - } - - public boolean isDead() { - return isDead; - } - @Override public void print(LogStream out) { out.print("phi function ("); @@ -143,25 +143,24 @@ } str.append(valueAt(i) == null ? "-" : valueAt(i).id()); } - if (isDead()) { - return "Phi: dead (" + str + ")"; + if (type == PhiType.Value) { + return "Phi: (" + str + ")"; } else { - return "Phi: (" + str + ")"; + return type + "Phi: (" + str + ")"; } } public void addInput(Node y) { - inputs().variablePart().add(y); + variableInputs().add(y); } public void removeInput(int index) { - inputs().variablePart().remove(index); + variableInputs().remove(index); } @Override public Node copy(Graph into) { - Phi x = new Phi(kind, into); - x.isDead = isDead; + Phi x = new Phi(kind, type, into); return x; } @@ -176,4 +175,62 @@ } }; } + + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + return super.lookup(clazz); + } + + private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + + @Override + public Node canonical(Node node) { + Phi phiNode = (Phi) node; +// if (phiNode.valueCount() != 2 || phiNode.merge().endCount() != 2 || phiNode.merge().phis().size() != 1) { +// return phiNode; +// } +// if (!(phiNode.valueAt(0) instanceof Constant && phiNode.valueAt(1) instanceof Constant)) { +// return phiNode; +// } +// Merge merge = phiNode.merge(); +// Node end0 = merge.endAt(0); +// Node end1 = merge.endAt(1); +// if (end0.predecessors().size() != 1 || end1.predecessors().size() != 1) { +// return phiNode; +// } +// Node endPred0 = end0.predecessors().get(0); +// Node endPred1 = end1.predecessors().get(0); +// if (endPred0 != endPred1 || !(endPred0 instanceof If)) { +// return phiNode; +// } +// If ifNode = (If) endPred0; +// if (ifNode.predecessors().size() != 1) { +// return phiNode; +// } +// boolean inverted = ((If) endPred0).trueSuccessor() == end1; +// CiConstant trueValue = phiNode.valueAt(inverted ? 1 : 0).asConstant(); +// CiConstant falseValue = phiNode.valueAt(inverted ? 0 : 1).asConstant(); +// if (trueValue.kind != CiKind.Int || falseValue.kind != CiKind.Int) { +// return phiNode; +// } +// if ((trueValue.asInt() == 0 || trueValue.asInt() == 1) && (falseValue.asInt() == 0 || falseValue.asInt() == 1) && (trueValue.asInt() != falseValue.asInt())) { +// MaterializeNode result; +// if (trueValue.asInt() == 1) { +// result = new MaterializeNode(ifNode.compare(), phiNode.graph()); +// } else { +// result = new MaterializeNode(new NegateBooleanNode(ifNode.compare(), phiNode.graph()), phiNode.graph()); +// } +// Node next = merge.next(); +// merge.setNext(null); +// ifNode.predecessors().get(0).successors().replace(ifNode, next); +// return result; +// } + return phiNode; + } + }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java Fri Jul 08 15:00:16 2011 +0200 @@ -107,11 +107,11 @@ } if (needsCheck) { - if (GraalOptions.TraceGVN) { + if (GraalOptions.TraceCanonicalizer) { TTY.println("Could not canonicalize finalizer " + object + " (declaredType=" + declaredType + ", exactType=" + exactType + ")"); } } else { - if (GraalOptions.TraceGVN) { + if (GraalOptions.TraceCanonicalizer) { TTY.println("Canonicalized finalizer for object " + object); } return finalizer.next(); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java Fri Jul 08 15:00:16 2011 +0200 @@ -56,8 +56,8 @@ return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER); } - public FrameState setStateAfter(FrameState n) { - return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n); + public void setStateAfter(FrameState n) { + inputs().set(super.inputCount() + INPUT_STATE_AFTER, n); } /** diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java Fri Jul 08 15:00:16 2011 +0200 @@ -23,6 +23,8 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.phases.LoweringPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -82,6 +84,15 @@ out.print(array()).print('[').print(index()).print("] := ").print(value()).print(" (").print(kind.typeChar).print(')'); } + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LoweringOp.class) { + return (T) LoweringPhase.DELEGATE_TO_RUNTIME; + } + return super.lookup(clazz); + } + @Override public Node copy(Graph into) { StoreIndexed x = new StoreIndexed(null, null, null, elementKind(), null, into); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java Fri Jul 08 15:00:16 2011 +0200 @@ -61,11 +61,11 @@ /** * The instruction that loads the target class object that is used by this checkcast. */ - public Constant targetClassInstruction() { - return (Constant) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION); + public Value targetClassInstruction() { + return (Value) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION); } - private void setTargetClassInstruction(Constant n) { + private void setTargetClassInstruction(Value n) { inputs().set(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION, n); } @@ -75,7 +75,7 @@ * @return the target class */ public RiType targetClass() { - return (RiType) targetClassInstruction().asConstant().asObject(); + return targetClassInstruction() instanceof Constant ? (RiType) targetClassInstruction().asConstant().asObject() : null; } /** @@ -87,7 +87,7 @@ * @param successorCount * @param graph */ - public TypeCheck(Constant targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) { + public TypeCheck(Value targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) { super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph); setObject(object); setTargetClassInstruction(targetClassInstruction); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java Fri Jul 08 15:00:16 2011 +0200 @@ -69,7 +69,6 @@ public abstract void visitStoreIndexed(StoreIndexed i); public abstract void visitTableSwitch(TableSwitch i); public abstract void visitDeoptimize(Deoptimize deoptimize); - public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch); public abstract void visitUnwind(Unwind unwind); public abstract void visitLoopBegin(LoopBegin loopBegin); public abstract void visitLoopEnd(LoopEnd loopEnd); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java Fri Jul 08 15:00:16 2011 +0200 @@ -33,9 +33,7 @@ public class VirtualObject extends FloatingNode { - private static final int INPUT_COUNT = 2; - private static final int INPUT_OBJECT = 0; - private static final int INPUT_INPUT = 1; + private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 0; @@ -49,48 +47,13 @@ return super.successorCount() + SUCCESSOR_COUNT; } - /** - * The instruction that specifies the old state of the virtual object. - */ - public VirtualObject object() { - return (VirtualObject) inputs().get(super.inputCount() + INPUT_OBJECT); - } - - private VirtualObject setObject(VirtualObject n) { - return (VirtualObject) inputs().set(super.inputCount() + INPUT_OBJECT, n); - } - - /** - * The instruction that contains the new state of the specified field. - */ - public Value input() { - return (Value) inputs().get(super.inputCount() + INPUT_INPUT); - } - - public Value setInput(Value n) { - return (Value) inputs().set(super.inputCount() + INPUT_INPUT, n); - } - - private EscapeField field; private EscapeField[] fields; private RiType type; - /** - * Constructs a new ArrayLength instruction. - * @param array the instruction producing the array - * @param newFrameState the state after executing this instruction - */ - public VirtualObject(VirtualObject object, Value input, EscapeField field, RiType type, EscapeField[] fields, Graph graph) { + public VirtualObject(RiType type, EscapeField[] fields, Graph graph) { super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph); - this.field = field; this.type = type; this.fields = fields; - setObject(object); - setInput(input); - } - - public EscapeField field() { - return field; } public RiType type() { @@ -110,23 +73,22 @@ public Map getDebugProperties() { Map properties = super.getDebugProperties(); properties.put("type", type); - properties.put("field", field); return properties; } @Override public String shortName() { - return "VirtualObject " + field.name(); + return "VirtualObject " + type.name(); } @Override public void print(LogStream out) { - out.print(object()).print(".").print(field.name()).print("=").print(input()); + out.print("virtualobject ").print(type.name()); } @Override public Node copy(Graph into) { - VirtualObject x = new VirtualObject(null, null, field, type, fields, into); + VirtualObject x = new VirtualObject(type, fields, into); return x; } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObjectField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObjectField.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.ir; + +import java.util.*; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public class VirtualObjectField extends FloatingNode { + + private static final int INPUT_COUNT = 3; + private static final int INPUT_OBJECT = 0; + private static final int INPUT_LAST_STATE = 1; + private static final int INPUT_INPUT = 2; + + 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; + } + + /** + * The instruction that specifies the virtual object instance. + */ + public VirtualObject object() { + return (VirtualObject) inputs().get(super.inputCount() + INPUT_OBJECT); + } + + private VirtualObject setObject(VirtualObject n) { + return (VirtualObject) inputs().set(super.inputCount() + INPUT_OBJECT, n); + } + + /** + * The instruction that specifies the old state of the virtual object. + */ + public FloatingNode lastState() { + return (FloatingNode) inputs().get(super.inputCount() + INPUT_LAST_STATE); + } + + private FloatingNode setLastState(FloatingNode n) { + return (FloatingNode) inputs().set(super.inputCount() + INPUT_LAST_STATE, n); + } + + /** + * The instruction that contains the new state of the specified field. + */ + public Value input() { + return (Value) inputs().get(super.inputCount() + INPUT_INPUT); + } + + public Value setInput(Value n) { + return (Value) inputs().set(super.inputCount() + INPUT_INPUT, n); + } + + private int index; + + /** + * Constructs a new ArrayLength instruction. + * @param array the instruction producing the array + * @param newFrameState the state after executing this instruction + */ + public VirtualObjectField(VirtualObject object, FloatingNode lastState, Value input, int index, Graph graph) { + super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.index = index; + setObject(object); + setLastState(lastState); + setInput(input); + } + + public int index() { + return index; + } + + @Override + public void accept(ValueVisitor v) { + // nothing to do... + } + + @Override + public Map getDebugProperties() { + Map properties = super.getDebugProperties(); + properties.put("index", index); + return properties; + } + + @Override + public String shortName() { + return "VirtualObjectField " + object().fields()[index].name(); + } + + @Override + public void print(LogStream out) { + out.print(object()).print(".").print(object().fields()[index].name()).print("=").print(input()); + } + + @Override + public Node copy(Graph into) { + VirtualObjectField x = new VirtualObjectField(null, null, null, index, into); + return x; + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java Fri Jul 08 15:00:16 2011 +0200 @@ -30,12 +30,12 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.ir.*; -import com.oracle.max.graal.compiler.lir.FrameMap.*; +import com.oracle.max.graal.compiler.lir.FrameMap.StackBlock; import com.oracle.max.graal.compiler.util.*; import com.sun.cri.ci.*; -import com.sun.cri.ci.CiTargetMethod.*; +import com.sun.cri.ci.CiTargetMethod.Mark; import com.sun.cri.ri.*; -import com.sun.cri.xir.CiXirAssembler.*; +import com.sun.cri.xir.CiXirAssembler.XirMark; /** * The {@code LIRAssembler} class definition. @@ -108,6 +108,10 @@ void emitBlock(LIRBlock block) { + if (block.align()) { + emitAlignment(); + } + block.setBlockEntryPco(codePos()); if (GraalOptions.PrintLIRWithAssembly) { diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Fri Jul 08 15:00:16 2011 +0200 @@ -27,6 +27,7 @@ import com.oracle.max.asm.*; import com.oracle.max.graal.compiler.alloc.*; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; @@ -44,6 +45,7 @@ private List predecessors = new ArrayList(4); private List successors = new ArrayList(4); private LIRDebugInfo debugInfo; + private boolean align; /** * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block. @@ -106,6 +108,14 @@ return firstLirInstructionID; } + public boolean align() { + return align; + } + + public void setAlign(boolean b) { + align = b; + } + public void setFirstLirInstructionId(int firstLirInstructionId) { this.firstLirInstructionID = firstLirInstructionId; } @@ -174,8 +184,7 @@ } public int loopDepth() { - // TODO(tw): Set correct loop depth. - return 0; + return loopDepth; } public int loopIndex() { @@ -284,4 +293,8 @@ LIROpcode code = lirInstruction.code; return code == LIROpcode.Branch || code == LIROpcode.TableSwitch; } + + public boolean isExceptionEntry() { + return firstInstruction() instanceof ExceptionObject; + } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -42,7 +42,7 @@ Node canonical = op.canonical(node); if (canonical != node) { node.replaceAndDelete(canonical); - nodeWorkList.replaced(canonical, node, EdgeType.USAGES); + nodeWorkList.replaced(canonical, node, true, EdgeType.USAGES); //System.out.println("-->" + n + " canonicalized to " + canonical); GraalMetrics.NodesCanonicalized++; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -28,7 +28,6 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.ir.*; -import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; @@ -77,8 +76,8 @@ if (current instanceof AbstractVectorNode) { for (Node usage : current.usages()) { flood.add(usage); - } - } + } + } } } @@ -105,29 +104,6 @@ endNode.replaceAndDelete(loop.next()); loop.delete(); } - } else if (node instanceof Merge) { - for (Node n : node.usages()) { - if (n instanceof Phi) { - Phi phi = (Phi) n; - if (phi.usages().size() == 1 && phi.usages().get(0) instanceof VirtualObject) { - // (tw) This VirtualObject instance is implicitely dead, because the CFG to it (i.e. the store that produced it) is dead! => fix this in escape analysis - VirtualObject virtualObject = (VirtualObject) phi.usages().get(0); - virtualObject.replaceAndDelete(virtualObject.object()); - } - } - } - } - - - if (IdentifyBlocksPhase.isFixed(node)) { - for (Node n : new ArrayList(node.usages())) { - if (n instanceof VirtualObject) { - // (tw) This VirtualObject instance is implicitely dead, because the CFG to it (i.e. the - // store that produced it) is dead! => fix this in Escape analysis - VirtualObject virtualObject = (VirtualObject) n; - virtualObject.replaceAndDelete(virtualObject.object()); - } - } } } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -23,43 +23,294 @@ package com.oracle.max.graal.compiler.phases; import java.util.*; -import java.util.Map.Entry; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; -import com.sun.cri.ri.*; public class EscapeAnalysisPhase extends Phase { + public interface MergeableState { + T clone(); + void merge(Merge merge, Collection withStates); + void loopBegin(LoopBegin loopBegin); + void loopEnd(LoopEnd loopEnd, T loopEndState); + } - public static class BlockExitState { - public final Map fieldState; - public VirtualObject obj; + public abstract static class PostOrderNodeIterator> { + + private final NodeBitMap visitedEnds; + private final Deque nodeQueue; + private final HashMap nodeStates; + private final FixedNode start; + + protected T state; + + public PostOrderNodeIterator(FixedNode start, T initialState) { + visitedEnds = start.graph().createNodeBitMap(); + nodeQueue = new ArrayDeque(); + nodeStates = new HashMap(); + this.start = start; + this.state = initialState; + } + + public void apply() { + FixedNode current = start; + + do { + if (current instanceof Invoke) { + invoke((Invoke) current); + queueSuccessors(current); + current = nextQueuedNode(); + } else if (current instanceof LoopBegin) { + state.loopBegin((LoopBegin) current); + nodeStates.put(current, state.clone()); + loopBegin((LoopBegin) current); + current = ((LoopBegin) current).next(); + assert current != null; + } else if (current instanceof LoopEnd) { + T loopBeginState = nodeStates.get(((LoopEnd) current).loopBegin()); + if (loopBeginState != null) { + loopBeginState.loopEnd((LoopEnd) current, state); + } + loopEnd((LoopEnd) current); + current = nextQueuedNode(); + } else if (current instanceof Merge) { + merge((Merge) current); + current = ((Merge) current).next(); + assert current != null; + } else if (current instanceof FixedNodeWithNext) { + FixedNode next = ((FixedNodeWithNext) current).next(); + node(current); + current = next; + assert current != null; + } else if (current instanceof EndNode) { + end((EndNode) current); + queueMerge((EndNode) current); + current = nextQueuedNode(); + } else if (current instanceof Deoptimize) { + deoptimize((Deoptimize) current); + current = nextQueuedNode(); + } else if (current instanceof Return) { + returnNode((Return) current); + current = nextQueuedNode(); + } else if (current instanceof Unwind) { + unwind((Unwind) current); + current = nextQueuedNode(); + } else if (current instanceof ControlSplit) { + controlSplit((ControlSplit) current); + queueSuccessors(current); + current = nextQueuedNode(); + } else { + assert false : current.shortName(); + } + } while(current != null); + } + + private void queueSuccessors(FixedNode x) { + nodeStates.put(x, state); + for (Node node : x.successors()) { + if (node != null) { + nodeQueue.addFirst((FixedNode) node); + } + } + } - public BlockExitState() { - this.fieldState = new HashMap(); + private FixedNode nextQueuedNode() { + int maxIterations = nodeQueue.size(); + while (maxIterations-- > 0) { + FixedNode node = nodeQueue.removeFirst(); + if (node instanceof Merge) { + Merge merge = (Merge) node; + state = nodeStates.get(merge.endAt(0)).clone(); + ArrayList states = new ArrayList(merge.endCount() - 1); + for (int i = 1; i < merge.endCount(); i++) { + T other = nodeStates.get(merge.endAt(i)); + assert other != null; + states.add(other); + } + state.merge(merge, states); + return merge; + } else { + assert node.predecessors().size() == 1; + state = nodeStates.get(node.predecessors().get(0)).clone(); + return node; + } + } + return null; + } + + private void queueMerge(EndNode end) { + assert !visitedEnds.isMarked(end); + assert !nodeStates.containsKey(end); + nodeStates.put(end, state); + visitedEnds.mark(end); + Merge merge = end.merge(); + boolean endsVisited = true; + for (int i = 0; i < merge.endCount(); i++) { + if (!visitedEnds.isMarked(merge.endAt(i))) { + endsVisited = false; + break; + } + } + if (endsVisited) { + nodeQueue.add(merge); + } + } + + protected abstract void node(FixedNode node); + + protected void end(EndNode endNode) { + node(endNode); + } + + protected void merge(Merge merge) { + node(merge); + } + + protected void loopBegin(LoopBegin loopBegin) { + node(loopBegin); + } + + protected void loopEnd(LoopEnd loopEnd) { + node(loopEnd); + } + + protected void deoptimize(Deoptimize deoptimize) { + node(deoptimize); + } + + protected void controlSplit(ControlSplit controlSplit) { + node(controlSplit); + } + + protected void returnNode(Return returnNode) { + node(returnNode); + } + + protected void invoke(Invoke invoke) { + node(invoke); + } + + protected void unwind(Unwind unwind) { + node(unwind); } } + public static class BlockExitState implements MergeableState { + public final Value[] fieldState; + public final VirtualObject virtualObject; + public FloatingNode virtualObjectField; + + public BlockExitState(EscapeField[] fields, VirtualObject virtualObject) { + this.fieldState = new Value[fields.length]; + this.virtualObject = virtualObject; + this.virtualObjectField = null; + for (int i = 0; i < fields.length; i++) { + fieldState[i] = Constant.defaultForKind(fields[i].kind(), virtualObject.graph()); + virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, fieldState[i], i, virtualObject.graph()); + } + } + + public BlockExitState(BlockExitState state) { + this.fieldState = state.fieldState.clone(); + this.virtualObject = state.virtualObject; + this.virtualObjectField = state.virtualObjectField; + } + + public void updateField(int fieldIndex) { + virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, fieldState[fieldIndex], fieldIndex, virtualObject.graph()); + } + + @Override + public BlockExitState clone() { + return new BlockExitState(this); + } + + @Override + public void merge(Merge merge, Collection withStates) { + Phi vobjPhi = null; + Phi[] valuePhis = new Phi[fieldState.length]; + for (BlockExitState other : withStates) { + if (virtualObjectField != other.virtualObjectField && vobjPhi == null) { + vobjPhi = new Phi(CiKind.Illegal, merge, PhiType.Virtual, virtualObject.graph()); + vobjPhi.addInput(virtualObjectField); + virtualObjectField = vobjPhi; + } + for (int i2 = 0; i2 < fieldState.length; i2++) { + if (fieldState[i2] != other.fieldState[i2] && valuePhis[i2] == null) { + valuePhis[i2] = new Phi(fieldState[i2].kind, merge, PhiType.Value, virtualObject.graph()); + valuePhis[i2].addInput(fieldState[i2]); + fieldState[i2] = valuePhis[i2]; + } + } + } + for (BlockExitState other : withStates) { + if (vobjPhi != null) { + vobjPhi.addInput(other.virtualObjectField); + } + for (int i2 = 0; i2 < fieldState.length; i2++) { + if (valuePhis[i2] != null) { + valuePhis[i2].addInput(other.fieldState[i2]); + } + } + } + assert vobjPhi == null || vobjPhi.valueCount() == withStates.size() + 1; + for (int i2 = 0; i2 < fieldState.length; i2++) { + if (valuePhis[i2] != null) { + virtualObjectField = new VirtualObjectField(virtualObject, virtualObjectField, valuePhis[i2], i2, virtualObject.graph()); + assert valuePhis[i2].valueCount() == withStates.size() + 1; + } + } + } + + @Override + public void loopBegin(LoopBegin loopBegin) { + Phi vobjPhi = null; + vobjPhi = new Phi(CiKind.Illegal, loopBegin, PhiType.Virtual, virtualObject.graph()); + vobjPhi.addInput(virtualObjectField); + virtualObjectField = vobjPhi; + for (int i2 = 0; i2 < fieldState.length; i2++) { + Phi valuePhi = new Phi(fieldState[i2].kind, loopBegin, PhiType.Value, virtualObject.graph()); + valuePhi.addInput(fieldState[i2]); + fieldState[i2] = valuePhi; + updateField(i2); + } + } + + @Override + public void loopEnd(LoopEnd x, BlockExitState loopEndState) { + while (!(virtualObjectField instanceof Phi)) { + virtualObjectField = ((VirtualObjectField) virtualObjectField).lastState(); + } + ((Phi) virtualObjectField).addInput(loopEndState.virtualObjectField); + assert ((Phi) virtualObjectField).valueCount() == 2; + for (int i2 = 0; i2 < fieldState.length; i2++) { + ((Phi) fieldState[i2]).addInput(loopEndState.fieldState[i2]); + assert ((Phi) fieldState[i2]).valueCount() == 2; + } + } + } + + public class EscapementFixup { private List blocks; - private final Map fields = new HashMap(); + private final Map fields = new HashMap(); private final Map exitStates = new HashMap(); private final EscapeOp op; - private Graph graph; + private final Graph graph; private final Node node; - private RiType type; private EscapeField[] escapeFields; public EscapementFixup(EscapeOp op, Graph graph, Node node) { @@ -74,217 +325,36 @@ } public void removeAllocation() { - final IdentifyBlocksPhase identifyBlocksPhase = new IdentifyBlocksPhase(true); - identifyBlocksPhase.apply(graph); - blocks = identifyBlocksPhase.getBlocks(); - - final HashMap phis = new HashMap(); - final Block startBlock = identifyBlocksPhase.getNodeToBlock().get(node); - assert startBlock != null; - type = ((Value) node).exactType(); - escapeFields = op.fields(node); - for (EscapeField field : escapeFields) { - fields.put(field.representation(), field); - } - - Block.iteratePostOrder(blocks, new BlockClosure() { - - public void apply(Block block) { - if (GraalOptions.TraceEscapeAnalysis) { - TTY.println("Block %d", block.blockID()); - } -// for (Node n : block.getInstructions()) { -// TTY.println(" %d %s", n.id(), n.shortName()); -// } -// for (Block b : block.getSuccessors()) { -// TTY.print(" %d", b.blockID()); -// } -// TTY.println(); - - BlockExitState state = new BlockExitState(); - if (/*block == startBlock ||*/ block.getPredecessors().size() == 0) { - state.obj = null; - } else { - List predecessors = block.getPredecessors(); - Set mergedFields = new HashSet(); - - BlockExitState predState = exitStates.get(predecessors.get(0)); - state.obj = predState == null ? null : predState.obj; - - for (int i = 0; i < predecessors.size(); i++) { - BlockExitState exitState = exitStates.get(predecessors.get(i)); - if (exitState == null) { - // (tw) What about an object that is allocated in a loop. We are merging in the values of the old allocation?; Now solved by "if" below. - mergedFields.addAll(fields.values()); - state.obj = null; - break; - } else { - for (EscapeField field : fields.values()) { - if (state.fieldState.get(field) == null) { - state.fieldState.put(field, exitState.fieldState.get(field)); - if (i != 0) { - // We need to merge this field too! - mergedFields.add(field); - } - } else if (state.fieldState.get(field) != exitState.fieldState.get(field)) { - mergedFields.add(field); - } - } - } - } - if (block.firstNode() instanceof LoopBegin) { - if (predState.obj == null) { - state.obj = null; - mergedFields.clear(); - } - } + assert node instanceof FixedNodeWithNext; - if (!mergedFields.isEmpty()) { - assert block.firstNode() instanceof Merge : "unexpected: " + block.firstNode().shortName() + " " + block.firstNode().id(); - for (EscapeField field : mergedFields) { - Phi phi = new Phi(field.kind().stackKind(), (Merge) block.firstNode(), graph); - state.fieldState.put(field, phi); - phis.put(phi, field); - state.obj = new VirtualObject(state.obj, phi, field, type, escapeFields, graph); - } - } - } - - Node current; - if (block.firstNode() instanceof StartNode) { - current = ((StartNode) block.firstNode()).next(); - } else { - current = block.firstNode(); - } - while (current != block.lastNode()) { - Node next = ((FixedNodeWithNext) current).next(); - FrameState stateAfter = null; - if (current instanceof StateSplit) { - stateAfter = ((StateSplit) current).stateAfter(); - } - if (current == node) { - for (EscapeField field : fields.values()) { - Constant value = Constant.defaultForKind(field.kind(), graph); - state.fieldState.put(field, value); - state.obj = new VirtualObject(state.obj, value, field, type, escapeFields, graph); - } - } else { - EscapeField changedField = op.updateState(node, current, fields, state.fieldState); - if (changedField != null) { - state.obj = new VirtualObject(state.obj, state.fieldState.get(changedField), changedField, type, escapeFields, graph); - } - } - if (stateAfter != null) { - updateFrameState(stateAfter, state.obj); - } - current = next; - } + escapeFields = op.fields(node); + for (int i = 0; i < escapeFields.length; i++) { + fields.put(escapeFields[i].representation(), i); + } + final VirtualObject virtual = new VirtualObject(((Value) node).exactType(), escapeFields, graph); + if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) { + TTY.println("new virtual object: " + virtual); + } + node.replaceAtUsages(virtual); + final FixedNode next = ((FixedNodeWithNext) node).next(); + node.replaceAndDelete(next); - if (GraalOptions.TraceEscapeAnalysis) { - TTY.print(" block end state: "); - for (Entry entry : state.fieldState.entrySet()) { - TTY.print("%s->%s ", entry.getKey().name(), entry.getValue()); - } - TTY.println(); + final BlockExitState startState = new BlockExitState(escapeFields, virtual); + final PostOrderNodeIterator iterator = new PostOrderNodeIterator(next, startState) { + @Override + protected void node(FixedNode node) { + int changedField = op.updateState(virtual, node, fields, state.fieldState); + if (changedField != -1) { + state.updateField(changedField); } - exitStates.put(block, state); - } - }); - - for (Entry entry : phis.entrySet()) { - Phi phi = entry.getKey(); - EscapeField field = entry.getValue(); - Block block = identifyBlocksPhase.getNodeToBlock().get(entry.getKey().merge()); - - List predecessors = block.getPredecessors(); - assert predecessors.size() > 0; - Node simple = exitStates.get(predecessors.get(0)).fieldState.get(field); - for (int i = 1; i < predecessors.size(); i++) { - BlockExitState exitState = exitStates.get(predecessors.get(i)); - if (exitState.fieldState.get(field) != simple) { - simple = null; - break; - } - } - if (simple != null) { - // (tw) Should never be reached, because Phi verification fails here.. - phi.replaceAndDelete(simple); - } else { - for (int i = 0; i < predecessors.size(); i++) { - BlockExitState exitState = exitStates.get(predecessors.get(i)); - assert exitState != null; - Node value = exitState.fieldState.get(field); - if (GraalOptions.TraceEscapeAnalysis) { - TTY.println("fixing phi %d with %s", phi.id(), value); - } - if (value == null) { - phi.addInput(Constant.defaultForKind(field.kind(), graph)); - } else { - phi.addInput(value); + if (!node.isDeleted() && node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) { + if (state.virtualObjectField != null) { + ((StateSplit) node).stateAfter().addVirtualObjectMapping(state.virtualObjectField); } } } - } - // the rest of the usages should be dead frame states... - for (Node usage : new ArrayList(node.usages())) { - if (usage instanceof IsNonNull) { - usage.replaceAndDelete(Constant.forBoolean(true, graph)); - } else if (usage instanceof RegisterFinalizer) { - usage.replaceAndDelete(((RegisterFinalizer) usage).next()); - } else { - assert usage instanceof FrameState || usage instanceof VirtualObject : "usage: " + usage; - usage.inputs().replace(node, Node.Null); - } - } - - if (node instanceof FixedNodeWithNext) { - node.replaceAndDelete(((FixedNodeWithNext) node).next()); - } else { - node.delete(); - } - } - - private void updateFrameState(FrameState frameState, VirtualObject current) { - for (int i = 0; i < frameState.inputs().size(); i++) { - if (frameState.inputs().get(i) == node) { - frameState.inputs().set(i, current); - } else if (frameState.inputs().get(i) instanceof VirtualObject) { - VirtualObject obj = (VirtualObject) frameState.inputs().get(i); - do { - updateVirtualObject(obj, current); - obj = obj.object(); - } while (obj != null); - } - } - FrameState outer = frameState.outerFrameState(); - if (outer != null) { - boolean duplicate = false; - for (int i = 0; i < outer.inputs().size(); i++) { - if (outer.inputs().get(i) == node) { - duplicate = true; - } - } - // (tw) need to fully duplicate also if there is a reference to "node" in an outer framestate? - duplicate = true; - if (duplicate) { - outer = outer.duplicate(outer.bci); - frameState.setOuterFrameState(outer); - } - updateFrameState(outer, current); - } - } - - private void updateVirtualObject(VirtualObject obj, VirtualObject current) { - if (obj.input() == node) { - // (tw) don't we have similar issues here like in framestate dup? We are updating a shared data structure here.. - obj.setInput(current); - } else if (obj.input() instanceof VirtualObject) { - VirtualObject obj2 = (VirtualObject) obj.input(); - do { - updateVirtualObject(obj2, current); - obj2 = obj2.object(); - } while (obj2 != null); - } + }; + iterator.apply(); } private void process() { @@ -305,9 +375,6 @@ @Override protected void run(Graph graph) { - if (compilation.method.name().contains("removeEnd") || compilation.method.name().contains("emitCode")) { - return; - } for (Node node : graph.getNodes()) { EscapeOp op = node.lookup(EscapeOp.class); if (op != null && op.canAnalyze(node)) { @@ -344,10 +411,10 @@ TTY.println("%n!!!!!!!! non-escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method); } new EscapementFixup(op, graph, node).apply(); + if (compilation.compiler.isObserved()) { + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After escape", graph, true, false)); + } new PhiSimplifier(graph); - if (compilation.compiler.isObserved()) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After escape " + node.id(), graph, true, false)); - } break; } if (weight < minimumWeight) { @@ -364,6 +431,12 @@ } new InliningPhase(compilation, ir, invokes).apply(graph); new DeadCodeEliminationPhase().apply(graph); + if (node.isDeleted()) { + if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) { + TTY.println("%n!!!!!!!! object died while performing escape analysis: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method); + } + break; + } exits.clear(); invokes.clear(); } while (iterations++ < 3); @@ -423,17 +496,57 @@ } } - public static interface EscapeOp extends Op { + public abstract static class EscapeOp implements Op { + + public abstract boolean canAnalyze(Node node); - boolean canAnalyze(Node node); - - boolean escape(Node node, Node usage); + public boolean escape(Node node, Node usage) { + if (usage instanceof IsNonNull) { + IsNonNull x = (IsNonNull) usage; + assert x.object() == node; + return false; + } else if (usage instanceof IsType) { + IsType x = (IsType) usage; + assert x.object() == node; + return false; + } else if (usage instanceof FrameState) { + FrameState x = (FrameState) usage; + assert x.inputs().contains(node); + return true; + } else if (usage instanceof AccessMonitor) { + AccessMonitor x = (AccessMonitor) usage; + assert x.object() == node; + return false; + } else { + return true; + } + } - EscapeField[] fields(Node node); + public abstract EscapeField[] fields(Node node); - void beforeUpdate(Node node, Node usage); + public void beforeUpdate(Node node, Node usage) { + if (usage instanceof IsNonNull) { + IsNonNull x = (IsNonNull) usage; + if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) { + FixedGuard guard = (FixedGuard) x.usages().get(0); + guard.replaceAndDelete(guard.next()); + } + x.delete(); + } else if (usage instanceof IsType) { + IsType x = (IsType) usage; + assert x.type() == ((Value) node).exactType(); + if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) { + FixedGuard guard = (FixedGuard) x.usages().get(0); + guard.replaceAndDelete(guard.next()); + } + x.delete(); + } else if (usage instanceof AccessMonitor) { + AccessMonitor x = (AccessMonitor) usage; + x.replaceAndDelete(x.next()); + } + } - EscapeField updateState(Node node, Node current, Map fields, Map fieldState); + public abstract int updateState(Node node, Node current, Map fieldIndex, Value[] fieldState); } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -106,8 +106,6 @@ private final Set blocksOnWorklist = new HashSet(); private final Set blocksVisited = new HashSet(); - private final boolean createUnwind; - public static final Map cachedGraphs = new WeakHashMap(); /** @@ -117,10 +115,12 @@ * @param ir the IR to build the graph into * @param graph */ - public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean createUnwind, boolean inline) { + public GraphBuilderPhase(GraalCompilation compilation, RiMethod method, boolean inline) { super(inline ? "BuildInlineGraph" : "BuildGraph"); this.compilation = compilation; + setDetailedName(getName() + " " + method.holder().name() + "." + method.name() + method.signature().asString()); + this.runtime = compilation.runtime; this.method = method; this.stats = compilation.stats; @@ -128,7 +128,6 @@ this.stream = new BytecodeStream(method.code()); this.constantPool = runtime.getConstantPool(method); - this.createUnwind = createUnwind; this.storeResultGraph = GraalOptions.CacheGraphs; } @@ -178,19 +177,11 @@ // 4A.1 add a monitor enter to the start block methodSynchronizedObject = synchronizedObject(frameState, method); genMonitorEnter(methodSynchronizedObject, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI); - // 4A.2 finish the start block - finishStartBlock(startBlock); + } - // 4A.3 setup an exception handler to unlock the root method synchronized object - unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null); - } else { - // 4B.1 simply finish the start block - finishStartBlock(startBlock); - - if (createUnwind) { - unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null); - } - } + // 4B.1 simply finish the start block + finishStartBlock(startBlock); + unwindHandler = new CiExceptionHandler(0, method.code().length, FixedNodeWithNext.SYNCHRONIZATION_ENTRY_BCI, 0, null); // 5. SKIPPED: look for intrinsics @@ -732,21 +723,22 @@ if (entry != null) { append(entry); } else { - frameState.clearStack(); - frameState.apush(exception); - appendGoto(createTarget(unwindBlock(bci), frameState)); + appendGoto(createTarget(unwindBlock(bci), frameState.duplicateWithException(bci, exception))); } } private void genCheckCast() { int cpi = stream().readCPI(); RiType type = constantPool.lookupType(cpi, CHECKCAST); - boolean isInitialized = type.isResolved(); - Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); + Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved()); Value object = frameState.apop(); if (typeInstruction != null) { -// append(new FixedGuard(new InstanceOf(typeInstruction, object, graph), graph)); -// frameState.apush(object); +// InstanceOf instanceOf = new InstanceOf(typeInstruction, object, true, graph); +// FixedGuard fixedGuard = new FixedGuard(instanceOf, graph); +// append(fixedGuard); +// CastNode castNode = new CastNode(object.kind, object, graph); +// castNode.inputs().add(fixedGuard); +// frameState.apush(castNode); frameState.apush(new CheckCast(typeInstruction, object, graph)); } else { frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); @@ -756,11 +748,10 @@ private void genInstanceOf() { int cpi = stream().readCPI(); RiType type = constantPool.lookupType(cpi, INSTANCEOF); - boolean isInitialized = type.isResolved(); - Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, isInitialized, cpi); + Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved()); Value object = frameState.apop(); if (typeInstruction != null) { - frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, graph), graph))); + frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, false, graph), graph))); } else { frameState.ipush(appendConstant(CiConstant.INT_0)); } @@ -851,7 +842,7 @@ if (constantValue != null) { frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue)); } else { - Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi); + Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized); CiKind kind = field.kind(); if (container != null) { LoadField load = new LoadField(container, field, graph); @@ -865,7 +856,7 @@ private void genPutStatic(int cpi, RiField field) { RiType holder = field.holder(); - Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized(), cpi); + Value container = genTypeOrDeopt(RiType.Representation.StaticFields, holder, field.isResolved() && field.holder().isInitialized()); Value value = frameState.pop(field.kind().stackKind()); if (container != null) { StoreField store = new StoreField(container, field, value, graph); @@ -875,7 +866,7 @@ } } - private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized, int cpi) { + private Constant genTypeOrDeopt(RiType.Representation representation, RiType holder, boolean initialized) { if (initialized) { return appendConstant(holder.getEncoding(representation)); } else { @@ -902,7 +893,7 @@ // Re-use the same resolution code as for accessing a static field. Even though // the result of resolution is not used by the invocation (only the side effect // of initialization is required), it can be commoned with static field accesses. - genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized, cpi); + genTypeOrDeopt(RiType.Representation.StaticFields, holder, isInitialized); } Value[] args = frameState.popArguments(target.signature().argumentSlots(false)); appendInvoke(INVOKESTATIC, target, args, cpi, constantPool); @@ -972,6 +963,9 @@ 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())); + if (invoke.exceptionEdge() == null) { + TTY.println("no exception edge" + unwindHandler); + } frameState.pushReturn(resultType, result); } } @@ -1256,6 +1250,7 @@ } else if (block instanceof DeoptBlock) { createDeoptBlock((DeoptBlock) block); } else { + frameState.setRethrowException(false); iterateBytecodesForBlock(block); } } @@ -1334,14 +1329,18 @@ assert frameState.stackSize() == 1 : frameState; Block nextBlock = block.next == null ? unwindBlock(block.deoptBci) : block.next; - if (block.handler.catchType().isResolved()) { + + + RiType catchType = block.handler.catchType(); + Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, catchType, catchType.isResolved()); + if (typeInstruction != null) { FixedNode catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState); FixedNode nextDispatch = createTarget(nextBlock, frameState); - append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph)); - } else { - Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph); - deopt.setMessage("unresolved " + block.handler.catchType().name()); - append(deopt); + Value exception = frameState.stackAt(0); + If ifNode = new If(new InstanceOf(typeInstruction, exception, false, graph), graph); + append(ifNode); + ifNode.setTrueSuccessor(catchSuccessor); + ifNode.setFalseSuccessor(nextDispatch); } } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -31,6 +31,7 @@ import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction; import com.oracle.max.graal.compiler.value.*; +import com.oracle.max.graal.extensions.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; @@ -41,6 +42,8 @@ public static final HashMap methodCount = new HashMap(); + private static final int MAX_ITERATIONS = 1000; + private final GraalCompilation compilation; private final IR ir; @@ -71,7 +74,7 @@ } } - for (int iterations = 0; iterations < GraalOptions.MaximumInlineLevel; iterations++) { + for (int iterations = 0; iterations < MAX_ITERATIONS; iterations++) { Queue queue = newInvokes; newInvokes = new ArrayDeque(); for (Invoke invoke : queue) { @@ -118,15 +121,20 @@ private RiMethod inlineInvoke(Invoke invoke, int iterations, float ratio) { RiMethod parent = invoke.stateAfter().method(); RiTypeProfile profile = parent.typeProfile(invoke.bci); - if (GraalOptions.Intrinsify && compilation.runtime.intrinsicGraph(invoke.target, invoke.arguments()) != null) { - // Always intrinsify. - return invoke.target; + if (GraalOptions.Intrinsify) { + if (GraalOptions.Extend && intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) { + return invoke.target; + } + if (compilation.runtime.intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) { + // Always intrinsify. + return invoke.target; + } } if (!checkInvokeConditions(invoke)) { return null; } if (invoke.opcode() == Bytecodes.INVOKESPECIAL || invoke.target.canBeStaticallyBound()) { - if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(invoke.target, invoke, profile, ratio)) { + if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(parent, iterations, invoke.target, invoke, profile, ratio)) { return invoke.target; } return null; @@ -135,7 +143,7 @@ RiType exact = invoke.receiver().exactType(); assert exact.isSubtypeOf(invoke.target().holder()) : exact + " subtype of " + invoke.target().holder(); RiMethod resolved = exact.resolveMethodImpl(invoke.target()); - if (checkTargetConditions(resolved, iterations) && checkSizeConditions(resolved, invoke, profile, ratio)) { + if (checkTargetConditions(resolved, iterations) && checkSizeConditions(parent, iterations, resolved, invoke, profile, ratio)) { return resolved; } return null; @@ -153,7 +161,7 @@ RiMethod concrete = holder.uniqueConcreteMethod(invoke.target); if (concrete != null) { - if (checkTargetConditions(concrete, iterations) && checkSizeConditions(concrete, invoke, profile, ratio)) { + if (checkTargetConditions(concrete, iterations) && checkSizeConditions(parent, iterations, concrete, invoke, profile, ratio)) { if (GraalOptions.TraceInlining) { String targetName = CiUtil.format("%H.%n(%p):%r", invoke.target, false); String concreteName = CiUtil.format("%H.%n(%p):%r", concrete, false); @@ -168,7 +176,7 @@ if (GraalOptions.InlineWithTypeCheck) { // type check and inlining... concrete = profile.types[0].resolveMethodImpl(invoke.target); - if (concrete != null && checkTargetConditions(concrete, iterations) && checkSizeConditions(concrete, invoke, profile, ratio)) { + if (concrete != null && checkTargetConditions(concrete, iterations) && checkSizeConditions(parent, iterations, concrete, invoke, profile, ratio)) { IsType isType = new IsType(invoke.receiver(), profile.types[0], compilation.graph); FixedGuard guard = new FixedGuard(isType, graph); assert invoke.predecessors().size() == 1; @@ -209,6 +217,12 @@ } private boolean checkInvokeConditions(Invoke invoke) { + if (!invoke.canInline()) { + if (GraalOptions.TraceInlining) { + TTY.println("not inlining %s because the invoke is manually set to be non-inlinable", methodName(invoke.target, invoke)); + } + return false; + } if (invoke.stateAfter() == null) { if (GraalOptions.TraceInlining) { TTY.println("not inlining %s because the invoke has no after state", methodName(invoke.target, invoke)); @@ -266,12 +280,6 @@ } return false; } - if (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel) { - if (GraalOptions.TraceInlining) { - TTY.println("not inlining %s because of recursive inlining limit", methodName(method)); - } - return false; - } return true; } @@ -289,7 +297,7 @@ return true; } - private boolean checkSizeConditions(RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) { + private boolean checkSizeConditions(RiMethod caller, int iterations, RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) { int maximumSize = GraalOptions.MaximumTrivialSize; float ratio = 0; if (profile != null && profile.count > 0) { @@ -304,19 +312,86 @@ if (hints != null && hints.contains(invoke)) { maximumSize = GraalOptions.MaximumFreqInlineSize; } - if (method.codeSize() > maximumSize) { + if (method.codeSize() > maximumSize || iterations >= GraalOptions.MaximumInlineLevel || (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel)) { if (GraalOptions.TraceInlining) { - TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s)", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile); + TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s) or inling level", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile); + } + if (GraalOptions.Extend) { + boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, false); + if (GraalOptions.TraceInlining && newResult) { + TTY.println("overridden inlining decision"); + } + return newResult; } return false; } if (GraalOptions.TraceInlining) { TTY.println("inlining %s (size: %d, max size: %d, ratio %5.3f, %s)", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile); } + if (GraalOptions.Extend) { + boolean newResult = overrideInliningDecision(iterations, caller, invoke.bci, method, true); + if (GraalOptions.TraceInlining && !newResult) { + TTY.println("overridden inlining decision"); + } + return newResult; + } return true; } + public static ThreadLocal> guideLoader = new ThreadLocal>(); + + private boolean overrideInliningDecision(int iteration, RiMethod caller, int bci, RiMethod target, boolean previousDecision) { + ServiceLoader serviceLoader = guideLoader.get(); + if (serviceLoader == null) { + serviceLoader = ServiceLoader.load(InliningGuide.class); + guideLoader.set(serviceLoader); + } + + boolean neverInline = false; + boolean alwaysInline = false; + for (InliningGuide guide : serviceLoader) { + InliningHint hint = guide.getHint(iteration, caller, bci, target); + + if (hint == InliningHint.ALWAYS_INLINE) { + alwaysInline = true; + } else if (hint == InliningHint.NEVER_INLINE) { + neverInline = true; + } + } + + if (neverInline && alwaysInline) { + if (GraalOptions.TraceInlining) { + TTY.println("conflicting inlining hints"); + } + } else if (neverInline) { + return false; + } else if (alwaysInline) { + return true; + } + return previousDecision; + } + + + public static ThreadLocal> intrinsicLoader = new ThreadLocal>(); + + private Graph intrinsicGraph(RiMethod parent, int bci, RiMethod target, List arguments) { + ServiceLoader serviceLoader = intrinsicLoader.get(); + if (serviceLoader == null) { + serviceLoader = ServiceLoader.load(Intrinsifier.class); + intrinsicLoader.set(serviceLoader); + } + + for (Intrinsifier intrinsifier : serviceLoader) { + Graph result = intrinsifier.intrinsicGraph(compilation.runtime, parent, bci, target, arguments); + if (result != null) { + return result; + } + } + return null; + } + private void inlineMethod(Invoke invoke, RiMethod method) { + RiMethod parent = invoke.stateAfter().method(); FrameState stateAfter = invoke.stateAfter(); FixedNode exceptionEdge = invoke.exceptionEdge(); if (exceptionEdge instanceof Placeholder) { @@ -339,12 +414,11 @@ CompilerGraph graph = null; if (GraalOptions.Intrinsify) { - graph = (CompilerGraph) compilation.runtime.intrinsicGraph(method, invoke.arguments()); - if (graph != null && graph.getNodes(Merge.class).iterator().hasNext()) { - WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(invoke.graph()); - checkpoint.setStateAfter(invoke.stateAfter()); - checkpoint.setNext(invoke.next()); - invoke.setNext(checkpoint); + if (GraalOptions.Extend) { + graph = (CompilerGraph) intrinsicGraph(parent, invoke.bci, method, invoke.arguments()); + } + if (graph == null) { + graph = (CompilerGraph) compilation.runtime.intrinsicGraph(parent, invoke.bci, method, invoke.arguments()); } } if (graph != null) { @@ -364,7 +438,7 @@ TTY.println("Building graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize()); } graph = new CompilerGraph(null); - new GraphBuilderPhase(compilation, method, true, true).apply(graph); + new GraphBuilderPhase(compilation, method, true).apply(graph); } invoke.inputs().clearAll(); @@ -404,14 +478,25 @@ } else { pred = new Placeholder(compilation.graph); } - invoke.predecessors().get(0).successors().replace(invoke, pred); + invoke.replaceAtPredecessors(pred); replacements.put(startNode, pred); Map duplicates = compilation.graph.addDuplicate(nodes, replacements); + FrameState stateBefore = null; for (Node node : duplicates.values()) { - if (node instanceof Invoke) { + if (node instanceof Invoke && ((Invoke) node).canInline()) { newInvokes.add((Invoke) node); + } else if (node instanceof FrameState) { + FrameState frameState = (FrameState) node; + if (frameState.bci == FrameState.BEFORE_BCI) { + if (stateBefore == null) { + stateBefore = stateAfter.duplicateModified(invoke.bci, false, invoke.kind, parameters); + } + frameState.replaceAndDelete(stateBefore); + } else if (frameState.bci == FrameState.AFTER_BCI) { + frameState.replaceAndDelete(stateAfter); + } } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -26,6 +26,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.util.LoopUtil.Loop; @@ -103,7 +104,7 @@ IntegerSub sub = new IntegerSub(kind, c2.init(), c1.init(), graph); IntegerAdd addStride = new IntegerAdd(kind, sub, c1.stride(), graph); IntegerAdd add = new IntegerAdd(kind, c1, addStride, graph); - Phi phi = new Phi(kind, loopBegin, graph); // (gd) assumes order on loopBegin preds - works in collab with graph builder + Phi phi = new Phi(kind, loopBegin, PhiType.Value, graph); // (gd) assumes order on loopBegin preds - works in collab with graph builder phi.addInput(c2.init()); phi.addInput(add); c2.replaceAndDelete(phi); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -57,11 +57,13 @@ } private void process(final Block b) { + + final Node anchor = b.javaBlock().createAnchor(); final CiLoweringTool loweringTool = new CiLoweringTool() { @Override public Node getGuardAnchor() { - return b.createAnchor(); + return anchor; } @Override @@ -72,19 +74,13 @@ @Override public Node createGuard(Node condition) { Anchor anchor = (Anchor) getGuardAnchor(); - for (GuardNode guard : anchor.happensAfterGuards()) { - if (guard.node().valueEqual(condition)) { - condition.delete(); - return guard; - } - } - GuardNode newGuard = new GuardNode(anchor.graph()); + GuardNode newGuard = new GuardNode((BooleanNode) condition, anchor.graph()); newGuard.setAnchor(anchor); - newGuard.setNode((BooleanNode) condition); return newGuard; } }; + // Lower the instructions of this block. for (final Node n : b.getInstructions()) { if (n instanceof FixedNode) { diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -28,6 +28,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -155,8 +156,7 @@ assert phi.valueCount() <= phi.merge().endCount(); return original; } else { - Phi phi = new Phi(CiKind.Illegal, m, m.graph()); - phi.makeDead(); // Phi does not produce a value, it is only a memory phi. + Phi phi = new Phi(CiKind.Illegal, m, PhiType.Memory, m.graph()); for (int i = 0; i < mergeOperationCount + 1; ++i) { phi.addInput(original); } @@ -198,7 +198,7 @@ } // Create dependency on previous write to same location. - node.inputs().variablePart().add(getLocationForWrite(node)); + node.addDependency(getLocationForWrite(node)); locationForWrite.put(location, node); locationForRead.put(location, node); @@ -220,7 +220,7 @@ } // Create dependency on previous node that creates the memory state for this location. - node.inputs().variablePart().add(getLocationForRead(node)); + node.addDependency(getLocationForRead(node)); } public Node getLocationForRead(ReadNode node) { @@ -315,6 +315,8 @@ LoopBegin begin = end.loopBegin(); Block beginBlock = nodeMap.get(begin); MemoryMap memoryMap = memoryMaps[beginBlock.blockID()]; + assert memoryMap != null : beginBlock.name(); + assert memoryMap.getLoopEntryMap() != null; memoryMap.getLoopEntryMap().resetMergeOperationCount(); memoryMap.getLoopEntryMap().mergeWith(map, beginBlock); Node loopCheckPoint = memoryMap.getLoopCheckPoint(); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java Fri Jul 08 15:00:16 2011 +0200 @@ -30,12 +30,14 @@ public abstract class Phase { private final String name; + private String detailedName; private static final ThreadLocal currentPhase = new ThreadLocal(); private final boolean shouldVerify; public Phase() { this.name = this.getClass().getSimpleName(); this.shouldVerify = true; + this.detailedName = name; } public Phase(String name) { @@ -45,6 +47,11 @@ public Phase(String name, boolean shouldVerify) { this.name = name; this.shouldVerify = shouldVerify; + this.detailedName = name; + } + + protected void setDetailedName(String detailedName) { + this.detailedName = detailedName; } public final void apply(Graph graph) { @@ -71,13 +78,13 @@ } catch (AssertionError t) { GraalCompilation compilation = GraalCompilation.compilation(); if (compilation.compiler.isObserved() && plotOnError) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + getName(), graph, true, false, true)); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + detailedName, graph, true, false, true)); } throw t; } catch (RuntimeException t) { GraalCompilation compilation = GraalCompilation.compilation(); if (compilation.compiler.isObserved() && plotOnError) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + getName(), graph, true, false, true)); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + detailedName, graph, true, false, true)); } throw t; } @@ -98,7 +105,7 @@ } GraalCompilation compilation = GraalCompilation.compilation(); if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + getName(), graph, true, false)); + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + detailedName, graph, true, false)); } assert !shouldVerify || graph.verify(); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -35,8 +35,8 @@ @Override protected void run(Graph graph) { for (ReadNode n : graph.getNodes(ReadNode.class)) { - if (n.inputs().variablePart().size() > 0) { - Node memoryInput = n.inputs().variablePart().get(0); + if (n.dependencies().size() > 0) { + Node memoryInput = n.dependencies().get(0); if (memoryInput instanceof WriteNode) { WriteNode other = (WriteNode) memoryInput; if (other.object() == n.object() && other.location() == n.location()) { diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Fri Jul 08 15:00:16 2011 +0200 @@ -38,6 +38,8 @@ private Block javaBlock; private final List dominators = new ArrayList(); private Anchor anchor; + private int loopDepth = 0; + private int loopIndex = -1; private Node firstNode; private Node lastNode; @@ -63,6 +65,22 @@ return lastNode; } + public int loopDepth() { + return loopDepth; + } + + public void setLoopDepth(int i) { + loopDepth = i; + } + + public int loopIndex() { + return loopIndex; + } + + public void setLoopIndex(int i) { + loopIndex = i; + } + public Anchor createAnchor() { if (anchor == null) { if (firstNode instanceof Anchor) { @@ -77,14 +95,14 @@ firstNode.graph().start().setNext(a); this.anchor = a; } - } else if (firstNode instanceof Merge) { - Merge merge = (Merge) firstNode; - if (merge.next() instanceof Anchor) { - this.anchor = (Anchor) merge.next(); + } else if (firstNode instanceof Merge || firstNode instanceof ExceptionObject) { + FixedNodeWithNext fixedNode = (FixedNodeWithNext) firstNode; + if (fixedNode.next() instanceof Anchor) { + this.anchor = (Anchor) fixedNode.next(); } else { Anchor a = new Anchor(firstNode.graph()); - a.setNext(merge.next()); - merge.setNext(a); + a.setNext(fixedNode.next()); + fixedNode.setNext(a); this.anchor = a; } } else { @@ -175,6 +193,10 @@ return firstNode instanceof LoopBegin; } + public boolean isLoopEnd() { + return lastNode instanceof LoopEnd; + } + public Block dominator() { return dominator; } @@ -224,4 +246,8 @@ } } } + + public String name() { + return "B" + blockID; + } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Fri Jul 08 15:00:16 2011 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.phases.*; @@ -36,6 +37,7 @@ private NodeMap nodeToBlock; private Graph graph; private boolean scheduleAllNodes; + private int loopCount; public IdentifyBlocksPhase(boolean scheduleAllNodes) { super(scheduleAllNodes ? "FullSchedule" : "PartSchedule", false); @@ -64,6 +66,10 @@ return b; } + public int loopCount() { + return loopCount; + } + private Block assignBlockNew(Node n, Block b) { if (b == null) { b = createBlock(); @@ -71,6 +77,20 @@ assert nodeToBlock.get(n) == null; nodeToBlock.set(n, b); + + if (n instanceof Merge) { + for (Node usage : n.usages()) { + + if (usage instanceof Phi) { + nodeToBlock.set(usage, b); + } + + if (usage instanceof LoopCounter) { + nodeToBlock.set(usage, b); + } + + } + } if (b.lastNode() == null) { b.setFirstNode(n); b.setLastNode(n); @@ -154,17 +174,7 @@ if (scheduleAllNodes) { - - // Add successors of loop end nodes. Makes the graph cyclic. - for (Block block : blocks) { - Node n = block.lastNode(); - if (n instanceof LoopEnd) { - LoopEnd loopEnd = (LoopEnd) n; - assert loopEnd.loopBegin() != null; - block.addSuccessor(nodeToBlock.get(loopEnd.loopBegin())); - } - } - + computeLoopInformation(); // Will make the graph cyclic. assignLatestPossibleBlockToNodes(); sortNodesWithinBlocks(); } else { @@ -172,6 +182,52 @@ } } + private void computeLoopInformation() { + + // Add successors of loop end nodes. Makes the graph cyclic. + for (Block block : blocks) { + Node n = block.lastNode(); + if (n instanceof LoopEnd) { + LoopEnd loopEnd = (LoopEnd) n; + assert loopEnd.loopBegin() != null; + Block loopBeginBlock = nodeToBlock.get(loopEnd.loopBegin()); + block.addSuccessor(loopBeginBlock); + BitMap map = new BitMap(blocks.size()); + markBlocks(block, loopBeginBlock, map, loopCount++, block.loopDepth()); + assert loopBeginBlock.loopDepth() == block.loopDepth() && loopBeginBlock.loopIndex() == block.loopIndex(); + } + } + +// for (Block block : blocks) { +// TTY.println("Block B" + block.blockID() + " loopIndex=" + block.loopIndex() + ", loopDepth=" + block.loopDepth()); +// } + } + + private void markBlocks(Block block, Block endBlock, BitMap map, int loopIndex, int initialDepth) { + if (map.get(block.blockID())) { + return; + } + + map.set(block.blockID()); + if (block.loopDepth() <= initialDepth) { + assert block.loopDepth() == initialDepth; + block.setLoopIndex(loopIndex); + } + block.setLoopDepth(block.loopDepth() + 1); + + if (block == endBlock) { + return; + } + + for (Block pred : block.getPredecessors()) { + markBlocks(pred, endBlock, map, loopIndex, initialDepth); + } + + if (block.isLoopHeader()) { + markBlocks(nodeToBlock.get(((LoopBegin) block.firstNode()).loopEnd()), endBlock, map, loopIndex, initialDepth); + } + } + private void computeJavaBlocks() { for (Block b : blocks) { @@ -240,16 +296,6 @@ assert !n.isDeleted(); - if (n instanceof Phi) { - Block block = nodeToBlock.get(((Phi) n).merge()); - nodeToBlock.set(n, block); - } - - if (n instanceof LoopCounter) { - Block block = nodeToBlock.get(((LoopCounter) n).loopBegin()); - nodeToBlock.set(n, block); - } - Block prevBlock = nodeToBlock.get(n); if (prevBlock != null) { return prevBlock; @@ -267,10 +313,11 @@ assert mergeBlock != null : "no block for merge " + merge.id(); for (int i = 0; i < phi.valueCount(); ++i) { if (phi.valueAt(i) == n) { - if (mergeBlock.getPredecessors().size() == 0) { + if (mergeBlock.getPredecessors().size() <= i) { TTY.println(merge.toString()); TTY.println(phi.toString()); TTY.println(merge.phiPredecessors().toString()); + TTY.println(phi.inputs().toString()); TTY.println("value count: " + phi.valueCount()); } block = getCommonDominator(block, mergeBlock.getPredecessors().get(i)); @@ -295,13 +342,76 @@ } } - nodeToBlock.set(n, block); + if (block != null) { + if (GraalOptions.OptOptimisticSchedule) { + block = scheduleOutOfLoops(n, block); + } + nodeToBlock.set(n, block); block.getInstructions().add(n); } return block; } + private Block scheduleOutOfLoops(Node n, Block latestBlock) { + Block cur = latestBlock; + while (cur.loopDepth() != 0) { + if (cur.isLoopHeader()) { + assert cur.getPredecessors().size() == 2 : cur.getPredecessors().size(); + if (canSchedule(n, cur.getPredecessors().get(0))) { + // TTY.println("can schedule out of loop!" + n); + return scheduleOutOfLoops(n, cur.getPredecessors().get(0)); + } else { + break; + } + } + Block prev = cur; + cur = cur.dominator(); + + // This must be a loop exit. + if (cur.loopDepth() > prev.loopDepth()) { +// TTY.println("break out because of different loop depth"); + break; + } + } + return latestBlock; + } + + private boolean canSchedule(Node n, Block block) { + Set allowedBlocks = new HashSet(); + Block cur = block; + while (cur != null) { + allowedBlocks.add(cur); + cur = cur.dominator(); + } + // Now we know the allowed blocks for inputs and predecessors. + return checkNodesAbove(allowedBlocks, n); + } + + private boolean checkNodesAbove(Set allowedBlocks, Node n) { + if (n == null) { + return true; + } + + if (nodeToBlock.get(n) != null) { + return allowedBlocks.contains(nodeToBlock.get(n)); + } else { + assert !(n instanceof Phi) : ((Phi) n).merge(); + for (Node input : n.inputs()) { + if (!checkNodesAbove(allowedBlocks, input)) { + return false; + } + } + for (Node pred : n.predecessors()) { + if (!checkNodesAbove(allowedBlocks, pred)) { + return false; + } + } + return true; + } + } + + private Block getCommonDominator(Block a, Block b) { if (a == null) { return b; @@ -324,15 +434,11 @@ List sortedInstructions = new ArrayList(instructions.size() + 2); assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b; -// assert !instructions.contains(b.firstNode()); -// assert !instructions.contains(b.lastNode()); assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b; - //addToSorting(b, b.firstNode(), sortedInstructions, map); for (Node i : instructions) { addToSorting(b, i, sortedInstructions, map); } - //addToSorting(b, b.lastNode(), sortedInstructions, map); // Make sure that last node gets really last (i.e. when a frame state successor hangs off it). Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1); @@ -367,10 +473,10 @@ } if (i instanceof WriteNode) { - // Make sure every ReadNode that is connected to the same memory state is executed before every write node. + // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node. WriteNode wn = (WriteNode) i; // TODO: Iterate over variablePart. - wn.inputs().variablePart(); +// wn.variableInputs(); } FrameState state = null; diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Fri Jul 08 15:00:16 2011 +0200 @@ -556,6 +556,8 @@ case AE : acond = ConditionFlag.aboveEqual; break; case AT : acond = ConditionFlag.above; break; case BT : acond = ConditionFlag.below; break; + case OF : acond = ConditionFlag.overflow; break; + case NOF : acond = ConditionFlag.noOverflow; break; default : throw Util.shouldNotReachHere(); } // Checkstyle: on @@ -1300,11 +1302,11 @@ default : throw Util.shouldNotReachHere(); } } else { - throw Util.shouldNotReachHere(); + throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2); } } else { - throw Util.shouldNotReachHere(opr1.toString() + " opr2 = " + opr2); + throw Util.shouldNotReachHere("opr1=" + opr1.toString() + " opr2=" + opr2); } // Checkstyle: on } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Fri Jul 08 15:00:16 2011 +0200 @@ -33,9 +33,6 @@ import com.oracle.max.graal.compiler.util.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; -import com.sun.cri.ri.*; -import com.sun.cri.ri.RiType.*; -import com.sun.cri.xir.*; /** * This class implements the X86-specific portion of the LIR generator. @@ -367,7 +364,7 @@ return; } - assert Util.archKindsEqual(x.x().kind, x.kind) && Util.archKindsEqual(x.y().kind, x.kind) : "wrong parameter types: " + Bytecodes.nameOf(x.opcode); + assert Util.archKindsEqual(x.x().kind, x.kind) && Util.archKindsEqual(x.y().kind, x.kind) : "wrong parameter types: " + Bytecodes.nameOf(x.opcode) + ", x: " + x.x() + ", y: " + x.y() + ", kind: " + x.kind; switch (x.kind) { case Float: case Double: @@ -466,30 +463,11 @@ } @Override - public void visitExceptionDispatch(ExceptionDispatch x) { - // TODO ls: this needs some more work... - - RiType riType = x.catchType(); - assert riType.isResolved(); - - XirArgument obj = toXirArgument(x.exception()); - XirArgument clazz = toXirArgument(riType.getEncoding(Representation.ObjectHub)); - XirSnippet snippet = xir.genInstanceOf(site(x), obj, clazz, riType); - emitXir(snippet, x, stateFor(x), null, false); - - LIRXirInstruction instr = (LIRXirInstruction) lir.instructionsList().get(lir.instructionsList().size() - 1); - instr.setTrueSuccessor(getLIRBlock(x.catchSuccessor())); - lir.jump(getLIRBlock(x.otherSuccessor())); - } - - @Override public void visitLoopBegin(LoopBegin x) { - } @Override public void visitValueAnchor(ValueAnchor valueAnchor) { // nothing to do for ValueAnchors } - } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java Fri Jul 08 15:00:16 2011 +0200 @@ -27,6 +27,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; @@ -232,7 +233,7 @@ colorQueue.offer(color); continue; } - Phi phi = new Phi(((Value) node).kind, lambda.merge(color), node.graph()); + Phi phi = new Phi(((Value) node).kind, lambda.merge(color), PhiType.Value, node.graph()); for (T parentColor : parentColors) { Node input = newNodes.get(parentColor); phi.addInput(input); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java Fri Jul 08 15:00:16 2011 +0200 @@ -27,6 +27,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.*; import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.GraphUtil.ColorSplitingLambda; @@ -185,7 +186,7 @@ for (Node usage : n.dataUsages()) { if (usage instanceof Phi) { // filter out data graph cycles Phi phi = (Phi) usage; - if (!phi.isDead()) { + if (phi.type() == PhiType.Value) { Merge merge = phi.merge(); if (merge instanceof LoopBegin) { LoopBegin phiLoop = (LoopBegin) merge; @@ -205,7 +206,7 @@ inOrBefore.mark(n); if (n instanceof Phi) { // filter out data graph cycles Phi phi = (Phi) n; - if (!phi.isDead()) { + if (phi.type() == PhiType.Value) { int backIndex = -1; Merge merge = phi.merge(); if (!loopNodes.isMarked(merge) && merge instanceof LoopBegin) { @@ -524,7 +525,7 @@ values.add(valueAt); } if (createPhi) { - Phi phi = new Phi(kind, merge, merge.graph()); + Phi phi = new Phi(kind, merge, PhiType.Value, merge.graph()); valueMap.set(point, phi); for (EndNode end : merge.cfgPredecessors()) { phi.addInput(getValueAt(colors.get(end), valueMap, kind)); @@ -759,14 +760,12 @@ for (Node usage : n.usages()) { if (usage instanceof Phi) { // filter out data graph cycles Phi phi = (Phi) usage; - if (!phi.isDead()) { - Merge merge = phi.merge(); - if (merge instanceof LoopBegin) { - LoopBegin phiLoop = (LoopBegin) merge; - int backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd()); - if (phi.valueAt(backIndex) == n) { - continue; - } + Merge merge = phi.merge(); + if (merge instanceof LoopBegin) { + LoopBegin phiLoop = (LoopBegin) merge; + int backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd()); + if (phi.valueAt(backIndex) == n) { + continue; } } } @@ -789,7 +788,7 @@ } if (n instanceof Phi) { // filter out data graph cycles Phi phi = (Phi) n; - if (!phi.isDead()) { + if (phi.type() == PhiType.Value) { int backIndex = -1; Merge merge = phi.merge(); if (!loopNodes.isNew(merge) && !loopNodes.isMarked(merge) && merge instanceof LoopBegin) { diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Fri Jul 08 15:00:16 2011 +0200 @@ -29,6 +29,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -49,10 +50,13 @@ protected final int locksSize; - private final boolean rethrowException; + private boolean rethrowException; private static final int SUCCESSOR_COUNT = 0; + public static final int BEFORE_BCI = -2; + public static final int AFTER_BCI = -3; + @Override protected int inputCount() { return super.inputCount() + localsSize + stackSize + locksSize; @@ -125,6 +129,23 @@ return method; } + public void addVirtualObjectMapping(Node virtualObject) { + assert virtualObject instanceof VirtualObjectField || virtualObject instanceof Phi : virtualObject; + variableInputs().add(virtualObject); + } + + public int virtualObjectMappingCount() { + return variableInputs().size(); + } + + public Node virtualObjectMappingAt(int i) { + return variableInputs().get(i); + } + + public List virtualObjectMappings() { + return variableInputs(); + } + /** * Gets a copy of this frame state. */ @@ -135,6 +156,7 @@ public FrameState duplicate(int bci, boolean duplicateOuter) { FrameState other = new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, graph()); other.inputs().setAll(inputs()); + other.variableInputs().addAll(variableInputs()); FrameState outerFrameState = outerFrameState(); if (duplicateOuter && outerFrameState != null) { outerFrameState = outerFrameState.duplicate(outerFrameState.bci, duplicateOuter); @@ -170,6 +192,7 @@ for (int i = 0; i < locksSize; i++) { other.setValueAt(localsSize + other.stackSize + i, lockAt(i)); } + other.variableInputs().addAll(variableInputs()); other.setOuterFrameState(outerFrameState()); return other; } @@ -322,7 +345,7 @@ return phi; } } - Phi phi = new Phi(p.kind, block, graph()); + Phi phi = new Phi(p.kind, block, PhiType.Value, graph()); setValueAt(localsSize + i, phi); return phi; } @@ -342,7 +365,7 @@ return phi; } } - Phi phi = new Phi(p.kind, block, graph()); + Phi phi = new Phi(p.kind, block, PhiType.Value, graph()); storeLocal(i, phi); return phi; } @@ -390,11 +413,9 @@ Value y = other.valueAt(i); if (x != y || ((x instanceof Phi) && ((Phi) x).merge() == block)) { if (typeMismatch(x, y)) { - if (x instanceof Phi) { - Phi phi = (Phi) x; - if (phi.merge() == block) { - phi.makeDead(); - } + if ((x instanceof Phi) && ((Phi) x).merge() == block) { + x.replaceAtUsages(null); + x.delete(); } setValueAt(i, null); continue; @@ -512,30 +533,83 @@ * @param proc the call back called to process each live value traversed */ public void forEachLiveStateValue(ValueProcedure proc) { - for (int i = 0; i < valuesSize(); i++) { - Value value = valueAt(i); - visitLiveStateValue(value, proc); - } - if (outerFrameState() != null) { - outerFrameState().forEachLiveStateValue(proc); - } - } + HashSet vobjs = null; + FrameState current = this; + do { + for (int i = 0; i < current.valuesSize(); i++) { + Value value = current.valueAt(i); + if (value instanceof VirtualObject) { + if (vobjs == null) { + vobjs = new HashSet(); + } + vobjs.add((VirtualObject) value); + } else if (value != null) { + proc.doValue(value); + } + } + current = current.outerFrameState(); + } while (current != null); + + if (vobjs != null) { + // collect all VirtualObjectField instances: + HashMap objectStates = new HashMap(); + current = this; + do { + for (int i = 0; i < current.virtualObjectMappingCount(); i++) { + VirtualObjectField field = (VirtualObjectField) current.virtualObjectMappingAt(i); + // null states occur for objects with 0 fields + if (field != null && !objectStates.containsKey(field.object())) { + objectStates.put(field.object(), field); + } + } + current = current.outerFrameState(); + } while (current != null); - private void visitLiveStateValue(Value value, ValueProcedure proc) { - if (value != null) { - if (value instanceof VirtualObject) { - HashSet fields = new HashSet(); - VirtualObject obj = (VirtualObject) value; - do { - if (!fields.contains(obj.field().representation())) { - fields.add(obj.field().representation()); - visitLiveStateValue(obj.input(), proc); + do { + HashSet vobjsCopy = new HashSet(vobjs); + for (VirtualObject vobj : vobjsCopy) { + if (vobj.fields().length > 0) { + boolean[] fieldState = new boolean[vobj.fields().length]; + FloatingNode currentField = objectStates.get(vobj); + assert currentField != null : this; + do { + if (currentField instanceof VirtualObjectField) { + int index = ((VirtualObjectField) currentField).index(); + Value value = ((VirtualObjectField) currentField).input(); + if (!fieldState[index]) { + fieldState[index] = true; + if (value instanceof VirtualObject) { + vobjs.add((VirtualObject) value); + } else { + proc.doValue(value); + } + } + currentField = ((VirtualObjectField) currentField).lastState(); + } else { + assert currentField instanceof Phi : currentField; + currentField = (FloatingNode) ((Phi) currentField).valueAt(0); + } + } while (currentField != null); } - obj = obj.object(); - } while (obj != null); - } else { - proc.doValue(value); + vobjs.remove(vobj); + } + } while (!vobjs.isEmpty()); + if (!vobjs.isEmpty()) { + for (VirtualObject obj : vobjs) { + TTY.println("+" + obj); + } + for (Node vobj : variableInputs()) { + if (vobj instanceof VirtualObjectField) { + TTY.println("-" + ((VirtualObjectField) vobj).object()); + } else { + TTY.println("-" + vobj); + } + } + for (Node n : this.usages()) { + TTY.println("usage: " + n); + } } + assert vobjs.isEmpty() : "at FrameState " + this; } } @@ -620,6 +694,11 @@ } @Override + public void setRethrowException(boolean b) { + rethrowException = b; + } + + @Override public Node copy(Graph into) { return new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, into); } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateAccess.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateAccess.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateAccess.java Fri Jul 08 15:00:16 2011 +0200 @@ -34,6 +34,8 @@ int locksSize(); + boolean rethrowException(); + Value valueAt(int i); Value localAt(int i); @@ -44,6 +46,8 @@ void setValueAt(int j, Value v); + void setRethrowException(boolean b); + Value outerFrameState(); FrameState duplicateWithException(int bci, Value exceptionObject); diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Fri Jul 08 15:00:16 2011 +0200 @@ -28,6 +28,7 @@ import java.util.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -42,6 +43,7 @@ private final ArrayList locks; private int stackIndex; + private boolean rethrowException; private final RiMethod method; @@ -101,10 +103,11 @@ for (int i = 0; i < other.locksSize(); i++) { locks.add(other.lockAt(i)); } + this.rethrowException = other.rethrowException(); } public FrameState create(int bci) { - return new FrameState(method, bci, locals, stack, stackIndex, locks, false, graph); + return new FrameState(method, bci, locals, stack, stackIndex, locks, rethrowException, graph); } public FrameState duplicateWithException(int bci, Value exceptionObject) { @@ -332,8 +335,11 @@ public Value loadLocal(int i) { Value x = locals[i]; if (x != null) { - if (x instanceof Phi && ((Phi) x).isDead()) { - return null; + if (x instanceof Phi) { + assert ((Phi) x).type() == PhiType.Value; + if (x.isDeleted()) { + return null; + } } assert x.kind.isSingleWord() || locals[i + 1] == null || locals[i + 1] instanceof Phi; } @@ -513,4 +519,14 @@ frameState.setOuterFrameState(outerFrameState()); return frameState; } + + @Override + public boolean rethrowException() { + return rethrowException; + } + + @Override + public void setRethrowException(boolean b) { + rethrowException = b; + } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/FrameModifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/FrameModifier.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.extensions; + +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; + + +public interface FrameModifier { + CiFrame getFrame(RiRuntime runtime, CiFrame frame); +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningExample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningExample.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.extensions; + + +public class InliningExample { + + public static void run() { + System.out.println(test()); + long start = System.currentTimeMillis(); + System.out.println(testFib()); + System.out.println(System.currentTimeMillis() - start); + } + + private static int test() { + return alwaysInline(30); + } + + public static int testFib() { + int sum = 0; + for (int i = 0; i < 10000000; ++i) { + sum += fib(5); + } + return sum; + } + + public static int alwaysInline(int value) { + if (value == 0) { + return neverInline(value); + } + return alwaysInline(value - 1); + } + + public static int neverInline(int value) { + if (value == 0) { + return 0; + } + return neverInline(value - 1); + } + + public static int fib(int val) { + if (val == 0 || val == 1) { + return 1; + } + return fib(val - 1) + fib(val - 2); + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningGuide.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningGuide.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.extensions; + +import com.sun.cri.ri.*; + + +public interface InliningGuide { + InliningHint getHint(int depth, RiMethod caller, int bci, RiMethod target); +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningHint.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/InliningHint.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.extensions; + + +public enum InliningHint { + NONE, + ALWAYS_INLINE, + NEVER_INLINE +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Intrinsifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Intrinsifier.java Fri Jul 08 15:00:16 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.max.graal.extensions; + +import java.util.*; + +import com.oracle.max.graal.graph.*; +import com.sun.cri.ri.*; + + +public interface Intrinsifier { + Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List parameters); +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Optimizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Optimizer.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.extensions; + +import com.oracle.max.graal.graph.*; +import com.sun.cri.ri.*; + + +public interface Optimizer { + void optimize(RiRuntime runtime, Graph graph); +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/.checkstyle --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/.checkstyle Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,10 @@ + + + + + + + + + + diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/.checkstyle_checks.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/.checkstyle_checks.xml Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/.classpath --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/.classpath Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/.project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/.project Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,29 @@ + + + com.oracle.max.graal.examples + + + + + + org.eclipse.jdt.core.javabuilder + + + + + net.sourceforge.metrics.builder + + + + + net.sf.eclipsecs.core.CheckstyleBuilder + + + + + + org.eclipse.jdt.core.javanature + net.sourceforge.metrics.nature + net.sf.eclipsecs.core.CheckstyleNature + + diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.core.prefs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.core.prefs Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,384 @@ +#Sat Jan 22 17:02:08 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=ignore +org.eclipse.jdt.core.compiler.problem.deadCode=ignore +org.eclipse.jdt.core.compiler.problem.deprecation=error +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=error +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=ignore +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled +org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL +org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=200 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.incompatibleJDKLevel=error +org.eclipse.jdt.core.incompleteClasspath=error diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.ui.prefs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/.settings/org.eclipse.jdt.ui.prefs Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,75 @@ +#Fri Jul 23 17:15:05 PDT 2010 +comment_clear_blank_lines=false +comment_format_comments=true +comment_format_header=true +comment_format_html=true +comment_format_source_code=true +comment_indent_parameter_description=true +comment_indent_root_tags=true +comment_line_length=120 +comment_new_line_for_parameter=true +comment_separate_root_tags=true +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_MaxineJavaCodeStyle2 +formatter_settings_version=11 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=false +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=0 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=0 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=false +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=false +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=false +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.InliningGuide --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.InliningGuide Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,1 @@ +com.oracle.max.graal.examples.inlining.InliningGuideImpl \ No newline at end of file diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,1 @@ +com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl \ No newline at end of file diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Optimizer --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Optimizer Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,1 @@ +com.oracle.max.graal.examples.opt.OptimizerImpl \ No newline at end of file diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.FrameModifier --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.FrameModifier Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,1 @@ +com.oracle.max.graal.examples.deopt.FrameModifierImpl \ No newline at end of file diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.InliningGuide --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.InliningGuide Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,1 @@ +com.oracle.max.graal.examples.inlining.InliningGuideImpl \ No newline at end of file diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,1 @@ +com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl \ No newline at end of file diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Optimizer --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Optimizer Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,1 @@ +com.oracle.max.graal.examples.opt.OptimizerImpl \ No newline at end of file diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/Main.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/Main.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples; + +import com.oracle.max.graal.examples.deopt.*; +import com.oracle.max.graal.examples.inlining.*; +import com.oracle.max.graal.examples.intrinsics.*; +import com.oracle.max.graal.examples.opt.*; + + +public class Main { + + public static void main(String[] args) { +// InliningExample.run(); +// SafeAddExample.run(); +// OptimizationExample.run(); + DeoptExample.run(); + } + +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptExample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptExample.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.deopt; + +import com.oracle.max.graal.examples.intrinsics.*; + + +public class DeoptExample { + + public static void run() { + System.out.println(); + System.out.println(); + System.out.println("Running Deopt Example"); + long start = System.currentTimeMillis(); + System.out.println("result1=" + test()); + System.out.println("time=" + (System.currentTimeMillis() - start) + "ms"); + } + + private static int test() { + try { + return testDeopt(3000000); + } catch (IllegalStateException e) { + System.out.println(e.getMessage()); + return 0; + } + } + + private static int testDeopt(int n) { + int sum = 0; + for (int i = 0; i < n; i = SafeAddExample.safeAdd(i, 1)) { + sum = SafeAddExample.safeAdd(sum, i); + } + return sum; + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/DeoptHandler.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.deopt; + + +public class DeoptHandler { + + + public static int test(int bci, Object[] values) { + System.out.println("values at bci " + bci + ": "); + for (Object value : values) { + System.out.print(value + " "); + } + System.out.println(); + return 2; + } + +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/FrameModifierImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/deopt/FrameModifierImpl.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.deopt; + +import com.oracle.max.graal.extensions.*; +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; + + +public class FrameModifierImpl implements FrameModifier { + + @Override + public CiFrame getFrame(RiRuntime runtime, CiFrame frame) { + try { + DeoptHandler.class.getMethod("test", Integer.TYPE, Object[].class); + } catch (Exception e) { + e.printStackTrace(); + return frame; + } + if (frame.method.name().equals("testDeopt")) { + RiType type = runtime.getType(DeoptHandler.class); + RiMethod method = type.getMethod("test", "(I[Ljava/lang/Object;)I"); + System.out.println("Size: " + method.maxLocals() + " " + method.maxStackSize()); + RiType arrayType = runtime.getType(Object.class).arrayOf(); + CiValue[] values = new CiValue[frame.values.length]; + for (int i = 0; i < values.length; i++) { + values[i] = CiVirtualObject.proxy(runtime, frame.values[i], i + 2); + } + CiVirtualObject local = CiVirtualObject.get(arrayType, values, 0); + CiValue[] values2 = new CiValue[method.maxLocals()]; + values2[0] = CiConstant.forInt(frame.bci); + values2[1] = local; + for (int i = 2; i < values2.length; i++) { + values2[i] = CiValue.IllegalValue; + } + return new CiFrame((CiFrame) frame.caller, method, 0, false, values2, method.maxLocals(), 0, 0); + } + return frame; + } + +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningExample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningExample.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.inlining; + + +public class InliningExample { + + public static void run() { + System.out.println(); + System.out.println(); + System.out.println("Running Inlining Example"); + long start = System.currentTimeMillis(); + System.out.println("result1=" + test()); + System.out.println("result2=" + testFib()); + System.out.println("time=" + (System.currentTimeMillis() - start) + "ms"); + } + + private static int test() { + return alwaysInline(30); + } + + public static int testFib() { + int sum = 0; + for (int i = 0; i < 100000000; ++i) { + sum += fib(5); + } + return sum; + } + + public static int alwaysInline(int value) { + if (value == 0) { + return neverInline(value); + } + return alwaysInline(value - 1); + } + + public static int neverInline(int value) { + if (value == 0) { + return 0; + } + return neverInline(value - 1); + } + + public static int fib(int val) { + if (val == 0 || val == 1) { + return 1; + } + return fib(val - 1) + fib(val - 2); + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningGuideImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/inlining/InliningGuideImpl.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.inlining; + +import com.oracle.max.graal.extensions.*; +import com.sun.cri.ri.*; + + +public class InliningGuideImpl implements InliningGuide { + + @Override + public InliningHint getHint(int depth, RiMethod caller, int bci, RiMethod target) { + if (target.name().equals("neverInline")) { + return InliningHint.NEVER_INLINE; + } else if (target.name().equals("alwaysInline") && depth < 50) { + return InliningHint.ALWAYS_INLINE; + } else if (target.name().equals("fib") && depth < 5) { + return InliningHint.ALWAYS_INLINE; + } + return InliningHint.NONE; + } + +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/IntrinsifierImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/IntrinsifierImpl.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.intrinsics; + +import java.util.*; + +import com.oracle.max.graal.compiler.graph.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.extensions.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; + + +public class IntrinsifierImpl implements Intrinsifier { + + @Override + public Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List parameters) { + if (method.holder().name().equals("Lcom/oracle/max/graal/examples/intrinsics/SafeAddExample;") && method.name().equals("safeAdd")) { + CompilerGraph graph = new CompilerGraph(runtime); + Return returnNode = new Return(new SafeAdd(new Local(CiKind.Long, 0, graph), new Local(CiKind.Long, 1, graph), graph), graph); + graph.start().setNext(returnNode); + graph.setReturn(returnNode); + return graph; + } + return null; + } + +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAdd.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAdd.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.intrinsics; + +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.bytecode.*; +import com.sun.cri.ci.*; + + +public final class SafeAdd extends IntegerArithmetic { + public SafeAdd(Value x, Value y, Graph graph) { + super(CiKind.Int, Bytecodes.LADD, x, y, graph); + } + + @Override + public Node copy(Graph into) { + return new SafeAdd(null, null, into); + } + + @Override + public String shortName() { + return "[+]"; + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) GENERATOR_OP; + } + return super.lookup(clazz); + } + + private static final LIRGenerator.LIRGeneratorOp GENERATOR_OP = new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + SafeAdd add = (SafeAdd) n; + generator.arithmeticOpInt(Bytecodes.IADD, generator.createResultVariable(add), generator.load(add.x()), generator.load(add.y()), CiValue.IllegalValue); + generator.deoptimizeOn(Condition.OF); + } + }; +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAddExample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAddExample.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.intrinsics; + + +public class SafeAddExample { + + public static final int N = 100000000; + + public static void run() { + System.out.println(); + System.out.println(); + System.out.println("Running SafeAdd Example"); + long start = System.currentTimeMillis(); + System.out.println("result=" + testSafeAdd()); + System.out.println("time=" + (System.currentTimeMillis() - start) + "ms"); + } + + private static int testSafeAdd() { + int sum = 0; + int j = N; + for (int i = -N; i < N; ++i) { + sum = safeAdd(sum, i); + sum = safeAdd(sum, j); + --j; + } + return sum; + } + + public static int safeAdd(int a, int b) { + int result = a + b; + if (b < 0 && result > a) { + throw new IllegalStateException("underflow when adding " + a + " and " + b); + } else if (b > 0 && result < a) { + throw new IllegalStateException("overflow when adding " + a + " and " + b); + } + return result; + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizationExample.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizationExample.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.opt; + +import com.oracle.max.graal.examples.intrinsics.*; + + +public class OptimizationExample { + + public static void run() { + System.out.println(); + System.out.println(); + System.out.println("Running Optimization Example"); + long start = System.currentTimeMillis(); + System.out.println("result=" + test(1000000000)); + System.out.println("time=" + (System.currentTimeMillis() - start) + "ms"); + } + + private static long test(int n) { + long sum = 0; + for (int i = 0; i < n; i = SafeAddExample.safeAdd(i, 1)) { + sum = sum + i; + } + return sum; + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.examples.opt; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.examples.intrinsics.*; +import com.oracle.max.graal.extensions.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; +import com.sun.cri.ri.*; + + +public class OptimizerImpl implements Optimizer { + + @Override + public void optimize(RiRuntime runtime, Graph graph) { + for (SafeAdd safeAdd : graph.getNodes(SafeAdd.class)) { + if (safeAdd.y().isConstant() && safeAdd.y().asConstant().asLong() == 1) { + if (safeAdd.x() instanceof Phi) { + Phi phi = (Phi) safeAdd.x(); + if (phi.merge() instanceof LoopBegin && phi.valueAt(1) == safeAdd) { + LoopBegin loopBegin = (LoopBegin) phi.merge(); + if (!canOverflow(phi, loopBegin)) { + IntegerAdd add = new IntegerAdd(CiKind.Int, safeAdd.x(), safeAdd.y(), graph); + safeAdd.replaceAndDelete(add); + } + } + } + } + } + } + + private boolean canOverflow(Phi phi, LoopBegin loopBegin) { + + NodeBitMap nodes = LoopUtil.computeLoopNodes(loopBegin); + NodeBitMap exits = LoopUtil.computeLoopExits(loopBegin, nodes); + for (Node exit : exits) { + TTY.println("exit: " + exit); + Node pred = exit.predecessors().get(0); + if (pred instanceof If) { + If ifNode = (If) pred; + if (ifNode.compare() instanceof Compare) { + Compare compare = (Compare) ifNode.compare(); + Condition cond = compare.condition(); + Value x = compare.x(); + Value y = compare.y(); + if (ifNode.trueSuccessor() == pred) { + cond = cond.negate(); + } + if (cond == Condition.LT && x == phi) { + return false; + } + if (cond == Condition.GT && y == phi) { + return false; + } + } + + } + } + TTY.println("can overflow"); + return true; + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/README.txt --- a/graal/com.oracle.max.graal.runtime/README.txt Fri Jul 08 14:49:01 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -The classes from the projects C1X, CRI, and HotSpotVM have to be on the classpath. The classes of the HotSpotVM project have to be on the bootclasspath -Example command line arguments for HotSpot: --XX:+UseC1X -XX:TraceC1X=5 -Xbootclasspath/a:THIS_DIRECTORY/bin;MAXINE_DIR/C1X/bin;MAXINE_DIR/CRI/bin SomeClass - diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java Fri Jul 08 15:00:16 2011 +0200 @@ -27,16 +27,18 @@ import java.util.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.runtime.nodes.*; +import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; import com.sun.cri.ci.CiTargetMethod.Call; import com.sun.cri.ci.CiTargetMethod.DataPatch; import com.sun.cri.ci.CiTargetMethod.Safepoint; import com.sun.cri.ri.*; +import com.sun.cri.ri.RiType.Representation; import com.sun.max.asm.dis.*; import com.sun.max.lang.*; @@ -247,6 +249,10 @@ @Override public void lower(Node n, CiLoweringTool tool) { + if (!GraalOptions.Lower) { + return; + } + if (n instanceof LoadField) { LoadField field = (LoadField) n; if (field.isVolatile()) { @@ -278,11 +284,78 @@ memoryWrite.setNext(field.next()); } field.replaceAndDelete(memoryWrite); + } else if (n instanceof LoadIndexed) { + LoadIndexed loadIndexed = (LoadIndexed) n; + Graph graph = loadIndexed.graph(); + GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool); + + CiKind elementKind = loadIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind); + arrayLocation.setIndex(loadIndexed.index()); + ReadNode memoryRead = new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation, graph); + memoryRead.setGuard(boundsCheck); + memoryRead.setNext(loadIndexed.next()); + loadIndexed.replaceAndDelete(memoryRead); + } else if (n instanceof StoreIndexed) { + StoreIndexed storeIndexed = (StoreIndexed) n; + Graph graph = storeIndexed.graph(); + Anchor anchor = new Anchor(graph); + GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool); + anchor.addGuard(boundsCheck); + + + CiKind elementKind = storeIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind); + arrayLocation.setIndex(storeIndexed.index()); + Value value = storeIndexed.value(); + Value array = storeIndexed.array(); + if (elementKind == CiKind.Object && !value.isNullConstant()) { + // Store check! + if (array.exactType() != null) { + RiType elementType = array.exactType().componentType(); + if (elementType.superType() != null) { + Constant type = new Constant(elementType.getEncoding(Representation.ObjectHub), graph); + value = new CheckCast(type, value, graph); + } else { + assert elementType.name().equals("Ljava/lang/Object;") : elementType.name(); + } + } else { + ReadNode arrayElementKlass = readArrayElementKlass(graph, array); + value = new CheckCast(arrayElementKlass, value, graph); + } + } + WriteNode memoryWrite = new WriteNode(elementKind.stackKind(), array, value, arrayLocation, graph); + memoryWrite.setGuard(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + anchor.setNext(memoryWrite); + if (elementKind == CiKind.Object && !value.isNullConstant()) { + ArrayWriteBarrier writeBarrier = new ArrayWriteBarrier(array, arrayLocation, graph); + memoryWrite.setNext(writeBarrier); + writeBarrier.setNext(storeIndexed.next()); + } else { + memoryWrite.setNext(storeIndexed.next()); + } + storeIndexed.replaceAtPredecessors(anchor); + storeIndexed.delete(); } } + private ReadNode readArrayElementKlass(Graph graph, Value array) { + ReadNode arrayKlass = readHub(graph, array); + ReadNode arrayElementKlass = new ReadNode(CiKind.Object, arrayKlass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph), graph); + return arrayElementKlass; + } + + private LocationNode createArrayLocation(Graph graph, CiKind elementKind) { + return LocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), graph); + } + + private GuardNode createBoundsCheck(AccessIndexed n, CiLoweringTool tool) { + return (GuardNode) tool.createGuard(new Compare(n.index(), Condition.BT, n.length(), n.graph())); + } + @Override - public Graph intrinsicGraph(RiMethod method, List parameters) { + public Graph intrinsicGraph(RiMethod caller, int bci, RiMethod method, List parameters) { if (!intrinsicGraphs.containsKey(method)) { RiType holder = method.holder(); String fullName = method.name() + method.signature().asString(); @@ -291,7 +364,7 @@ if (fullName.equals("getClass()Ljava/lang/Class;")) { CompilerGraph graph = new CompilerGraph(this); Local receiver = new Local(CiKind.Object, 0, graph); - ReadNode klassOop = new ReadNode(CiKind.Object, receiver, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph); + ReadNode klassOop = readHub(graph, receiver); Return ret = new Return(new ReadNode(CiKind.Object, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), graph), graph); graph.start().setNext(ret); graph.setReturn(ret); @@ -304,7 +377,7 @@ Local srcPos = new Local(CiKind.Int, 1, graph); Local dest = new Local(CiKind.Object, 2, graph); Local destPos = new Local(CiKind.Int, 3, graph); - Local length = new Local(CiKind.Int, 4, graph); + Value length = new Local(CiKind.Int, 4, graph); src.setDeclaredType(((Value) parameters.get(0)).declaredType()); dest.setDeclaredType(((Value) parameters.get(2)).declaredType()); @@ -321,11 +394,13 @@ } CiKind componentType = src.declaredType().componentType().kind(); - if (componentType == CiKind.Object) { return null; } + FrameState stateBefore = new FrameState(method, FrameState.BEFORE_BCI, 0, 0, 0, false, graph); + FrameState stateAfter = new FrameState(method, FrameState.AFTER_BCI, 0, 0, 0, false, graph); + // Add preconditions. FixedGuard guard = new FixedGuard(graph); ArrayLength srcLength = new ArrayLength(src, graph); @@ -345,11 +420,13 @@ CreateVectorNode normalVector = new CreateVectorNode(false, length, graph); ReadVectorNode values = new ReadVectorNode(new IntegerAddVectorNode(normalVector, srcPos, graph), src, location, graph); new WriteVectorNode(new IntegerAddVectorNode(normalVector, destPos, graph), dest, location, values, graph); + normalVector.setStateAfter(stateAfter); // Build reverse vector instruction. CreateVectorNode reverseVector = new CreateVectorNode(true, length, graph); ReadVectorNode reverseValues = new ReadVectorNode(new IntegerAddVectorNode(reverseVector, srcPos, graph), src, location, graph); new WriteVectorNode(new IntegerAddVectorNode(reverseVector, destPos, graph), dest, location, reverseValues, graph); + reverseVector.setStateAfter(stateAfter); If ifNode = new If(new Compare(src, Condition.EQ, dest, graph), graph); guard.setNext(ifNode); @@ -362,23 +439,81 @@ Merge merge1 = new Merge(graph); merge1.addEnd(new EndNode(graph)); merge1.addEnd(new EndNode(graph)); + merge1.setStateAfter(stateBefore); - ifNode.setFalseSuccessor(merge1.endAt(0)); + + Invoke newInvoke = null; + if (componentType == CiKind.Object) { + Value srcClass = readHub(graph, src); + Value destClass = readHub(graph, dest); + If elementClassIf = new If(new Compare(srcClass, Condition.EQ, destClass, graph), graph); + ifNode.setFalseSuccessor(elementClassIf); + newInvoke = new Invoke(bci, Bytecodes.INVOKESTATIC, CiKind.Void, new Value[]{src, srcPos, dest, destPos, length}, method, method.signature().returnType(method.holder()), graph); + newInvoke.setCanInline(false); + newInvoke.setStateAfter(stateAfter); + elementClassIf.setFalseSuccessor(newInvoke); + elementClassIf.setTrueSuccessor(merge1.endAt(0)); + } else { + ifNode.setFalseSuccessor(merge1.endAt(0)); + } + secondIf.setFalseSuccessor(merge1.endAt(1)); merge1.setNext(normalVector); Merge merge2 = new Merge(graph); merge2.addEnd(new EndNode(graph)); merge2.addEnd(new EndNode(graph)); + merge2.setStateAfter(stateAfter); normalVector.setNext(merge2.endAt(0)); reverseVector.setNext(merge2.endAt(1)); + if (newInvoke != null) { + merge2.addEnd(new EndNode(graph)); + newInvoke.setNext(merge2.endAt(2)); + } + Return ret = new Return(null, graph); merge2.setNext(ret); graph.setReturn(ret); return graph; } + } else if (holderName.equals("Ljava/lang/Float;")) { + if (fullName.equals("floatToRawIntBits(F)I") || fullName.equals("floatToIntBits(F)I")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Int, new Local(CiKind.Float, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } else if (fullName.equals("intBitsToFloat(I)F")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Float, new Local(CiKind.Int, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } + } else if (holderName.equals("Ljava/lang/Double;")) { + if (fullName.equals("doubleToRawLongBits(D)J") || fullName.equals("doubleToLongBits(D)J")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Long, new Local(CiKind.Double, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } else if (fullName.equals("longBitsToDouble(J)D")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new FPConversionNode(CiKind.Double, new Local(CiKind.Long, 0, graph), graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } + } else if (holderName.equals("Ljava/lang/Thread;")) { + if (fullName.equals("currentThread()Ljava/lang/Thread;")) { + CompilerGraph graph = new CompilerGraph(this); + Return ret = new Return(new CurrentThread(config.threadObjectOffset, graph), graph); + graph.start().setNext(ret); + graph.setReturn(ret); + intrinsicGraphs.put(method, graph); + } } if (!intrinsicGraphs.containsKey(method)) { @@ -387,4 +522,13 @@ } return intrinsicGraphs.get(method); } + + private ReadNode readHub(Graph graph, Value value) { + return new ReadNode(CiKind.Object, value, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), graph); + } + + @Override + public RiType getType(Class clazz) { + return compiler.getVMEntries().getType(clazz); + } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypePrimitive.java Fri Jul 08 15:00:16 2011 +0200 @@ -154,4 +154,9 @@ public RiField[] fields() { return null; } + + @Override + public RiMethod getMethod(String name, String signature) { + return null; + } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeResolvedImpl.java Fri Jul 08 15:00:16 2011 +0200 @@ -230,4 +230,9 @@ } return fields; } + + @Override + public RiMethod getMethod(String name, String signature) { + return compiler.getVMEntries().RiType_resolveMethodImpl(this, name, signature); + } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java Fri Jul 08 15:00:16 2011 +0200 @@ -205,4 +205,9 @@ public RiField[] fields() { return null; } + + @Override + public RiMethod getMethod(String name, String signature) { + return null; + } } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotXirGenerator.java Fri Jul 08 15:00:16 2011 +0200 @@ -164,8 +164,8 @@ protected XirTemplate create(CiXirAssembler asm, long flags) { asm.restart(CiKind.Void); - // XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); - // asm.pload(CiKind.Word, temp, asm.w(config.safepointPollingAddress), true); + XirOperand temp = asm.createRegister("temp", CiKind.Word, AMD64.rax); + asm.pload(CiKind.Word, temp, asm.w(config.safepointPollingAddress), true); return asm.finishTemplate("safepoint"); } @@ -1179,7 +1179,6 @@ @Override public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { - assert type.isResolved(); return new XirSnippet(checkCastTemplates.get(site), receiver, hub); } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class ArrayWriteBarrier extends WriteBarrier { + private static final int INPUT_COUNT = 2; + private static final int INPUT_OBJECT = 0; + private static final int INPUT_LOCATION = 1; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + /** + * The instruction that produces the object tested against null. + */ + public Value object() { + return (Value) inputs().get(super.inputCount() + INPUT_OBJECT); + } + + public void setObject(Value n) { + inputs().set(super.inputCount() + INPUT_OBJECT, n); + } + + /** + * The instruction that produces the object tested against null. + */ + public LocationNode location() { + return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION); + } + + public void setLocation(LocationNode n) { + inputs().set(super.inputCount() + INPUT_LOCATION, n); + } + + public ArrayWriteBarrier(Value object, LocationNode index, Graph graph) { + super(INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.setObject(object); + this.setLocation(index); + } + + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + assert n == ArrayWriteBarrier.this; + CiVariable temp = generator.newVariable(CiKind.Word); + generator.lir().lea(location().createAddress(generator, object()), temp); + ArrayWriteBarrier.this.generateBarrier(temp, generator); + } + }; + } + return super.lookup(clazz); + } + + @Override + public void print(LogStream out) { + out.print("field write barrier ").print(object()); + } + + @Override + public Node copy(Graph into) { + return new ArrayWriteBarrier(null, null, into); + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class CurrentThread extends FloatingNode { + private static final int INPUT_COUNT = 0; + private static final int SUCCESSOR_COUNT = 0; + private int threadObjectOffset; + + public CurrentThread(int threadObjectOffset, Graph graph) { + super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.threadObjectOffset = threadObjectOffset; + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + CurrentThread conv = (CurrentThread) n; + CiValue result = generator.createResultVariable(conv); + generator.lir().move(new CiAddress(CiKind.Object, AMD64.r15.asValue(CiKind.Word), threadObjectOffset), result); + } + }; + } + return super.lookup(clazz); + } + + @Override + public boolean valueEqual(Node i) { + return i instanceof CurrentThread; + } + + @Override + public void print(LogStream out) { + out.print("currentThread"); + } + + @Override + public Node copy(Graph into) { + return new CurrentThread(threadObjectOffset, into); + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class FPConversionNode extends FloatingNode { + private static final int INPUT_COUNT = 1; + private static final int INPUT_OBJECT = 0; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + /** + * The instruction that produces the object tested against null. + */ + public Value value() { + return (Value) inputs().get(super.inputCount() + INPUT_OBJECT); + } + + public void setValue(Value n) { + inputs().set(super.inputCount() + INPUT_OBJECT, n); + } + + public FPConversionNode(CiKind kind, Value value, Graph graph) { + super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); + this.setValue(value); + } + + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == LIRGenerator.LIRGeneratorOp.class) { + return (T) new LIRGenerator.LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + FPConversionNode conv = (FPConversionNode) n; + CiValue reg = generator.createResultVariable(conv); + CiValue value = generator.load(conv.value()); + CiValue tmp = generator.forceToSpill(value, conv.kind, false); + generator.lir().move(tmp, reg); + } + }; + } + return super.lookup(clazz); + } + + @Override + public boolean valueEqual(Node i) { + return i instanceof FPConversionNode && ((FPConversionNode) i).kind == kind; + } + + @Override + public void print(LogStream out) { + out.print("fp conversion node ").print(value()); + } + + @Override + public Node copy(Graph into) { + return new FPConversionNode(kind, null, into); + } +} diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java Fri Jul 08 14:49:01 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java Fri Jul 08 15:00:16 2011 +0200 @@ -25,13 +25,11 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.ir.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.runtime.*; import com.sun.cri.ci.*; -public final class FieldWriteBarrier extends FixedNodeWithNext { +public final class FieldWriteBarrier extends WriteBarrier { private static final int INPUT_COUNT = 1; private static final int INPUT_OBJECT = 0; @@ -54,7 +52,7 @@ } public FieldWriteBarrier(Value object, Graph graph) { - super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); + super(INPUT_COUNT, SUCCESSOR_COUNT, graph); this.setObject(object); } @@ -68,18 +66,8 @@ public void generate(Node n, LIRGenerator generator) { assert n == FieldWriteBarrier.this; CiVariable temp = generator.newVariable(CiKind.Word); - HotSpotVMConfig config = CompilerImpl.getInstance().getConfig(); generator.lir().move(generator.makeOperand(object()), temp); - generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue); - - long startAddress = config.cardtableStartAddress; - int displacement = 0; - if (((int) startAddress) == startAddress) { - displacement = (int) startAddress; - } else { - generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp); - } - generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null); + FieldWriteBarrier.this.generateBarrier(temp, generator); } }; } diff -r 536b02e3cd2b -r 38792f959479 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.runtime.nodes; + +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.runtime.*; +import com.sun.cri.ci.*; + + +public abstract class WriteBarrier extends FixedNodeWithNext { + private static final int INPUT_COUNT = 0; + private static final int SUCCESSOR_COUNT = 0; + + public WriteBarrier(int inputCount, int successorCount, Graph graph) { + super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph); + } + + + protected void generateBarrier(CiValue temp, LIRGenerator generator) { + HotSpotVMConfig config = CompilerImpl.getInstance().getConfig(); + generator.lir().unsignedShiftRight(temp, CiConstant.forInt(config.cardtableShift), temp, CiValue.IllegalValue); + + long startAddress = config.cardtableStartAddress; + int displacement = 0; + if (((int) startAddress) == startAddress) { + displacement = (int) startAddress; + } else { + generator.lir().add(temp, CiConstant.forLong(config.cardtableStartAddress), temp); + } + generator.lir().move(CiConstant.FALSE, new CiAddress(CiKind.Boolean, temp, displacement), (LIRDebugInfo) null); + } +} diff -r 536b02e3cd2b -r 38792f959479 perf/benchmarktool.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/perf/benchmarktool.sh Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,156 @@ +#!/usr/bin/python + +import subprocess +import os +import re +import sys +import argparse + +DEFAULT_DACAPO_OPTS = " -XX:MaxPermSize=512m -Xms1g -Xmx2g " +DEFAULT_SCIMARK_OPTS = " -Xms32m -Xmx100m " + +def runBash(cmd): + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + return p.stdout + +def s2msString(floatString): + return str(round(float(floatString)*1000)) + +# Raw String Notation (r"") : \ instead of \\ +graalTime = re.compile(r"Total compilation time\s+:\s+([0-9]+\.[0-9]+) s") +graalSubTime = re.compile(r"([a-zA-Z0-9_ ]+)\s+:\s+([0-9]+\.[0-9]+) s \([0-9 ][0-9]\.[0-9]{2}%\)") + +def matchGraalTime(string, csvOutput, csvOutputLine, writeHeaderAt): + match1 = graalTime.search(string) + match2 = graalSubTime.search(string) + if match1: + if csvOutputLine == writeHeaderAt: + csvOutput[0].append('graal total') + print('Graal total time: '+ s2msString(match1.group(1))) + csvOutput[csvOutputLine].append(s2msString(match1.group(1))) + elif match2: + if csvOutputLine == writeHeaderAt: + csvOutput[0].append(match2.group(1).strip()) + print('Graal specific time: '+match2.group(1)+': '+s2msString(match2.group(2))) + csvOutput[csvOutputLine].append(s2msString(match2.group(2))) + else: + print('# '+string) + +def writeout(outputFile, csvOutput): + for csvLine in csvOutput : + outputFile.write(';'.join(csvLine)+';'+os.linesep) + +def main(): + # Check for environment variables + if os.getenv('JDK7') is None: + print('Environment variable JDK7 is not defined.') + return 1 + if os.getenv('DACAPO') is None: + print('Environment variable DACAPO is not defined. It must point to a directory with the DaCapo benchmark jar.') + return 1 + if os.getenv('SCIMARK') is None: + print('Environment variable SCIMARK is not defined. It must point to a directory with the SciMark benchmark jar.') + return 1 + if os.getenv('REFERENCE_JDK') is None: + print('Environment variable REFERENCE_JDK is not defined.') + return 1 + + # Option parsing + parser = argparse.ArgumentParser(description='Automated DaCapo and Scimark bechmarks') + parser.add_argument('-a', '-all', help='run all benchmarks for all compilers', action='store_true') + parser.add_argument('-c', type=str, help='compiler to use', default='graal', choices=['client', 'server', 'graal'], required=False) + parser.add_argument('-n', type=int, help='number of DaCapo benchmarks to run', default=20) + parser.add_argument('-o', type=str, help='graalVM options(quoted!)', default='') + parser.add_argument('-runonly', type=str, help='run specified benchmark only', default='all') + options = parser.parse_args() + compilerFlags = {'graal' : '-client -graal -G:+Time -XX:-GraalBailoutIsFatal -G:QuietBailout ', + 'client' : '-client', + 'server' : '-server'} + + if options.a: + compilers = ['graal', 'client', 'server'] + else: + compilers = [options.c] + + for compiler in compilers: + + outputFile = open(compiler+'.csv', 'w') + + # DaCapo Benchmarks + if compiler == 'graal': + vm = os.environ['JDK7'] + else : + vm = os.environ['REFERENCE_JDK'] + + cmd = vm + '/bin/java ' + compilerFlags[compiler] + ' -d64 ' + DEFAULT_DACAPO_OPTS + options.o + ' -classpath ' + \ + os.environ['DACAPO'] + '/dacapo-9.12-bach.jar Harness -n ' + str(options.n) + ' ' + benchmarks = runBash('java -jar ' + os.environ['DACAPO'] + '/dacapo-9.12-bach.jar -l').read().decode().split(' ') + + benchmarkTime = re.compile(r"===== DaCapo 9\.12 ([a-zA-Z0-9_]+) ((PASSED)|(completed warmup [0-9]+)) in ([0-9]+) msec =====") + + csvOutput = [['benchmark', 'type', 'time']] + csvOutputLine = 0 + for benchmark in benchmarks: + if options.runonly != 'all' and benchmark != options.runonly: + continue + nRuns = 0 + dcOutput = runBash(cmd + benchmark) + while True: + line = dcOutput.readline().decode() + if not line: + break + line = line.strip() + match = benchmarkTime.search(line) + if match: + csvOutputLine = csvOutputLine + 1 + nRuns = nRuns + 1 + csvOutput.append(list()) + csvOutput[csvOutputLine].append(str(nRuns)) + print('Benchmark type: '+match.group(1)) + print('Benchmark time: '+match.group(5)) + csvOutput[csvOutputLine].append(match.group(1)) + csvOutput[csvOutputLine].append(match.group(5)) + else: + matchGraalTime(line, csvOutput, csvOutputLine, options.n) + + if nRuns < options.n: + csvOutputLine = csvOutputLine + (options.n - nRuns) + for i in range(options.n - nRuns): + csvOutput.append([str(nRuns + i), benchmark, '0']) + + writeout(outputFile, csvOutput) + + if options.runonly != 'all' and options.runonly != 'scimark': + outputFile.close() + return 0 + + # Scimark Benchmarks + writeout(outputFile, [['']]) + cmd = vm + '/bin/java ' + compilerFlags[compiler] + ' -d64 ' + DEFAULT_SCIMARK_OPTS + options.o + \ + ' -Xbootclasspath/a:' + os.environ['SCIMARK'] + '/scimark2lib.jar jnt.scimark2.commandline' + + benchmarkScore = re.compile(r"([a-zA-Z0-9_\(\),= ]+):\s+([0-9]+\.[0-9]+)$") + + csvOutput = [['run'],[]] + scOutput = runBash(cmd) + while True: + line = scOutput.readline().decode() + if not line: + break + line = line.strip() + match = benchmarkScore.search(line) + if match: + print('Scimark '+match.group(1)+' score: '+match.group(2)) + csvOutput[0].append(match.group(1).strip()) + csvOutput[1].append(match.group(2)) + else: + matchGraalTime(line,csvOutput, 1, 1) + + writeout(outputFile, csvOutput) + outputFile.close() + + return 0 + +#This idiom means the below code only runs when executed from command line +if __name__ == '__main__': + sys.exit(main()) diff -r 536b02e3cd2b -r 38792f959479 runexamples.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runexamples.sh Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,21 @@ +#!/bin/bash +if [ -z "${JDK7}" ]; then + echo "JDK7 is not defined." + exit 1; +fi +if [ -z "${MAXINE}" ]; then + echo "MAXINE is not defined. It must point to a maxine repository directory." + exit 1; +fi +if [ -z "${GRAAL}" ]; then + echo "GRAAL is not defined. It must point to a maxine repository directory." + exit 1; +fi +if [ -z "${DACAPO}" ]; then + echo "DACAPO is not defined. It must point to a Dacapo benchmark directory." + exit 1; +fi +ant -f create_examples.xml +COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -G:Extend -Xcomp -XX:CompileOnly=examples $* -jar examples.jar" +echo $COMMAND +$COMMAND diff -r 536b02e3cd2b -r 38792f959479 runexamplescompare.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runexamplescompare.sh Fri Jul 08 15:00:16 2011 +0200 @@ -0,0 +1,27 @@ +#!/bin/bash +if [ -z "${JDK7}" ]; then + echo "JDK7 is not defined." + exit 1; +fi +if [ -z "${MAXINE}" ]; then + echo "MAXINE is not defined. It must point to a maxine repository directory." + exit 1; +fi +if [ -z "${GRAAL}" ]; then + echo "GRAAL is not defined. It must point to a maxine repository directory." + exit 1; +fi +if [ -z "${DACAPO}" ]; then + echo "DACAPO is not defined. It must point to a Dacapo benchmark directory." + exit 1; +fi +ant -f create_examples.xml +COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -G:Extend -Xcomp -XX:CompileOnly=examples $* -jar examples.jar" +echo $COMMAND +$COMMAND +COMMAND="${JDK7}/bin/java -client -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar" +echo $COMMAND +$COMMAND +COMMAND="${JDK7}/bin/java -server -d64 -Xms1g -Xmx2g -esa -Xcomp -XX:CompileOnly=examples $* -jar examples.jar" +echo $COMMAND +$COMMAND diff -r 536b02e3cd2b -r 38792f959479 runscimark.sh --- a/runscimark.sh Fri Jul 08 14:49:01 2011 +0200 +++ b/runscimark.sh Fri Jul 08 15:00:16 2011 +0200 @@ -12,16 +12,7 @@ exit 1; fi if [ -z "${SCIMARK}" ]; then - echo "SCIMARK is not defined. It must point to a SciMark benchmark jar." + echo "SCIMARK is not defined. It must point to a directory with the SciMark benchmark jar." exit 1; fi -COUNT=$1 -shift -if [ -z "${COUNT}" ]; then - COUNT=5000 -fi -for (( i = 1; i <= ${COUNT}; i++ )) ### Outer for loop ### -do - echo "$i " - ${JDK7}/jre/bin/java -client -d64 -graal -esa -ea -Xms32m -Xmx100m -Xbootclasspath/a:${SCIMARK} -G:+Time $@ jnt.scimark2.commandline -done +${JDK7}/jre/bin/java -client -d64 -graal -Xms256m -Xmx512m -Xbootclasspath/a:${SCIMARK}/scimark2lib.jar $@ jnt.scimark2.commandline diff -r 536b02e3cd2b -r 38792f959479 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Fri Jul 08 14:49:01 2011 +0200 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Fri Jul 08 15:00:16 2011 +0200 @@ -459,6 +459,7 @@ } while (should_repeat == true); if (h_method->method_data() != NULL) { + ResourceMark rm(thread); ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci); if (pdata != NULL) { int tstate0 = pdata->trap_state(); diff -r 536b02e3cd2b -r 38792f959479 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Fri Jul 08 14:49:01 2011 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Fri Jul 08 15:00:16 2011 +0200 @@ -1244,9 +1244,10 @@ if (trap_scope->rethrow_exception()) { if (TraceDeoptimization) { - tty->print_cr("Exception to be rethrown in the interpreter"); + tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci); } GrowableArray* expressions = trap_scope->expressions(); + guarantee(expressions != NULL, "must have exception to throw"); ScopeValue* topOfStack = expressions->top(); Handle topOfStackObj = cvf->create_stack_value(topOfStack)->get_obj(); THREAD->set_pending_exception(topOfStackObj(), NULL, 0); diff -r 536b02e3cd2b -r 38792f959479 src/share/vm/runtime/vframeArray.cpp --- a/src/share/vm/runtime/vframeArray.cpp Fri Jul 08 14:49:01 2011 +0200 +++ b/src/share/vm/runtime/vframeArray.cpp Fri Jul 08 15:00:16 2011 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" +#include "code/scopeDesc.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -62,7 +63,7 @@ _method = vf->method(); _bci = vf->raw_bci(); _reexecute = vf->should_reexecute(); - + int index; // Get the monitors off-stack @@ -126,28 +127,37 @@ // Now the expressions off-stack // Same silliness as above - - StackValueCollection *exprs = vf->expressions(); - _expressions = new StackValueCollection(exprs->size()); - for(index = 0; index < exprs->size(); index++) { - StackValue* value = exprs->at(index); - switch(value->type()) { - case T_OBJECT: - assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); - // preserve object type - _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); - break; - case T_CONFLICT: - // A dead stack element. Will be initialized to null/zero. - // This can occur when the compiler emits a state in which stack - // elements are known to be dead (because of an imminent exception). - _expressions->add( new StackValue()); - break; - case T_INT: - _expressions->add( new StackValue(value->get_int())); - break; - default: - ShouldNotReachHere(); + bool rethrow_exception = vf->scope()->rethrow_exception(); + if (rethrow_exception) { + // (tw) Make sure there are only null pointers on the stack, because the stack values do not correspond to the GC map at the bytecode at which the exception is rethrown. + _expressions = new StackValueCollection(vf->method()->max_stack()); + assert(Thread::current()->has_pending_exception(), "just checking"); + for (int i=0; imethod()->max_stack(); ++i) { + _expressions->add( new StackValue()); + } + } else { + StackValueCollection *exprs = vf->expressions(); + _expressions = new StackValueCollection(exprs->size()); + for(index = 0; index < exprs->size(); index++) { + StackValue* value = exprs->at(index); + switch(value->type()) { + case T_OBJECT: + assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); + // preserve object type + _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); + break; + case T_CONFLICT: + // A dead stack element. Will be initialized to null/zero. + // This can occur when the compiler emits a state in which stack + // elements are known to be dead (because of an imminent exception). + _expressions->add( new StackValue()); + break; + case T_INT: + _expressions->add( new StackValue(value->get_int())); + break; + default: + ShouldNotReachHere(); + } } } } @@ -314,8 +324,7 @@ // only unpacks the part of the expression stack not used by callee // as parameters. The callee parameters are unpacked as part of the // callee locals. - int i; - for(i = 0; i < expressions()->size(); i++) { + for(int i = 0; i < expressions()->size(); i++) { StackValue *value = expressions()->at(i); intptr_t* addr = iframe()->interpreter_frame_expression_stack_at(i); switch(value->type()) { @@ -352,7 +361,7 @@ // Unpack the locals - for(i = 0; i < locals()->size(); i++) { + for(int i = 0; i < locals()->size(); i++) { StackValue *value = locals()->at(i); intptr_t* addr = iframe()->interpreter_frame_local_at(i); switch(value->type()) {